aboutsummaryrefslogtreecommitdiff
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)
downloadgnunet-2b552a5f5e85fab1c14af73735c0de61b46cc3dc.tar.gz
gnunet-2b552a5f5e85fab1c14af73735c0de61b46cc3dc.zip
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 @@
1#!/bin/bash 1#!/bin/bash
2 2
3./bootstrap 3./bootstrap && ./configure --prefix=/tmp/gnunet --enable-experimental && make
4./configure --prefix=/tmp/gnunet --enable-experimental
5make
diff --git a/ChangeLog b/ChangeLog
index 4ed6576e7..98b3b40b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,66 @@
1Wed, 12 Aug 2020 09:36:33 +0200 (99f820453)
2fix: GNUNET_is_zero(ptr) should return enum GNUNET_GenericReturnValue. Fixes #6475. - Martin Schanzenbach
3
4Tue, 11 Aug 2020 11:35:06 +0200 (286759692)
5fix: mysql version detection - Martin Schanzenbach
6
7Thu, 6 Aug 2020 08:45:40 +0200 (1d4f5263a)
8reclaim: Refactoring and more standards compliance with respect to scopes - Martin Schanzenbach
9
10Wed, 5 Aug 2020 11:35:05 +0200 (6e764f4ab)
11reclaim: Make SPAs work with public clients. No longer encrypt code. - Martin Schanzenbach
12
13Tue, 4 Aug 2020 21:08:22 +0200 (ade9b5e52)
14reclaim: fix #6463 - Martin Schanzenbach
15
16Tue, 4 Aug 2020 19:40:23 +0200 (815ded19f)
17rest: fix #6462 - Martin Schanzenbach
18
19Tue, 4 Aug 2020 10:09:45 +0200 (080519e98)
20reclaim: do not store access token instead piggyback ticket - Martin Schanzenbach
21
22Mon, 3 Aug 2020 19:37:23 +0200 (8c86c4472)
23reclaim: support client credentials in POST body for token request - Martin Schanzenbach
24
25Sat, 1 Aug 2020 16:22:38 +0200 (e44686f08)
26fix: reclaim urlenc / revert accidental change - Martin Schanzenbach
27
28Sat, 1 Aug 2020 16:07:08 +0200 (754d8c1b4)
29util: add percent/url encoding - Martin Schanzenbach
30
31Thu, 30 Jul 2020 16:12:22 +0530 (8d312646c)
32fix SIGSEGV in GNUNET_buffer_write_data_encoded - Florian Dold
33
34Thu, 30 Jul 2020 15:15:59 +0530 (d335baac8)
35implement GNUNET_buffer_write_data_encoded - Florian Dold
36
37Wed, 22 Jul 2020 21:47:42 +0200 (8703a0516)
38ensure psql fails hard if there is an error in the SQL (fixes #6437) - Christian Grothoff
39
40Sat, 18 Jul 2020 00:44:39 +0200 (7f4ddbcab)
41merge flags into enum for GNUNET_DISK_pipe() API, fixing #6188 - Christian Grothoff
42
43Fri, 17 Jul 2020 22:35:36 +0200 (28ab2c446)
44avoid boolean flag in GNUNET_OS_start_process() API (fixes #6188) - Christian Grothoff
45
46Fri, 17 Jul 2020 14:26:45 +0200 (0c9911d73)
47TNG: Implemented 5530: add replay protection to TCP communicator. Added monotime value checks - t3sserakt
48
49Thu, 16 Jul 2020 20:36:12 +0200 (bbe0a0501)
50avoid boolean argument in GNUNET_CURL_job_add(), see #6188 - Christian Grothoff
51
52Thu, 16 Jul 2020 17:40:14 +0200 (ee1fbffa1)
53support context-wide client authentication - Christian Grothoff
54
55Thu, 16 Jul 2020 17:24:30 +0200 (23820348b)
56docs: fixed example for pinning a friends public key - rexxnor
57
58Wed, 15 Jul 2020 17:21:39 +0200 (9bb2c1e31)
59Load GNSRECORD plugins within GNUnet's context - Christian Grothoff
60
61Fri, 3 Jul 2020 22:37:42 +0200 (0f2ac01f3)
62Add function to return GNUnet's default configuration - Christian Grothoff
63
1Thu, 9 Jul 2020 09:09:50 +0200 (5a0df5e18) 64Thu, 9 Jul 2020 09:09:50 +0200 (5a0df5e18)
2fix: raise ATS quotas to 10 MiB #6426 - Martin Schanzenbach 65fix: raise ATS quotas to 10 MiB #6426 - Martin Schanzenbach
3 66
diff --git a/bootstrap b/bootstrap
index b4f5b4dc3..8fc4c4426 100755
--- a/bootstrap
+++ b/bootstrap
@@ -79,8 +79,8 @@ check_libtool()
79 existence libtoolize || \ 79 existence libtoolize || \
80 existence glibtoolize || \ 80 existence glibtoolize || \
81 existence slibtool; then 81 existence slibtool; then
82 autoreconf -if 82 autoreconf -if || exit 1
83 . "bin/pogen.sh" 83 . "bin/pogen.sh" || exit 1
84 else 84 else
85 echo "*** No libtoolize (libtool) or libtool found, please install it ***" >&2; 85 echo "*** No libtoolize (libtool) or libtool found, please install it ***" >&2;
86 exit 1 86 exit 1
@@ -97,15 +97,15 @@ submodules()
97 if ! git --version >/dev/null; then 97 if ! git --version >/dev/null; then
98 echo "git not installed, skipping submodule update" 98 echo "git not installed, skipping submodule update"
99 else 99 else
100 git submodule update --init || true 100 git submodule update --init || exit 1
101 git submodule update --recursive || true 101 git submodule update --recursive || exit 1
102 git submodule sync || true 102 git submodule sync || exit 1
103 fi 103 fi
104} 104}
105 105
106init_buildcommon_include() 106init_buildcommon_include()
107{ 107{
108 cp contrib/build-common/Makefile.inc contrib/Makefile.inc || true 108 cp contrib/build-common/Makefile.inc contrib/Makefile.inc || exit 1
109} 109}
110 110
111main() 111main()
diff --git a/configure.ac b/configure.ac
index 39e7ffa7e..bd92bd0e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@
21# 21#
22AC_PREREQ(2.61) 22AC_PREREQ(2.61)
23# Checks for programs. 23# Checks for programs.
24AC_INIT([gnunet], [0.13.1], [bug-gnunet@gnu.org]) 24AC_INIT([gnunet], [0.13.2], [bug-gnunet@gnu.org])
25AC_CONFIG_AUX_DIR([build-aux]) 25AC_CONFIG_AUX_DIR([build-aux])
26 26
27# check for legacy option that is no longer supported (#5627) and fail hard 27# check for legacy option that is no longer supported (#5627) and fail hard
@@ -142,9 +142,11 @@ AS_CASE(["$host_os"],
142 UNIXONLY="#" 142 UNIXONLY="#"
143 ], 143 ],
144 [*openbsd*],[ 144 [*openbsd*],[
145 LIBS=`echo $LIBS | sed -e "s/-ldl//"` 145 # We need to explicitly link libc
146 LDFLAGS="$LDFLAGS -Wl,-lc"
147 # We also need to enable PIC
148 CFLAGS="-fPIC $CFLAGS"
146 build_target="openbsd" 149 build_target="openbsd"
147 use_openbsd_libtool=true
148 LIBPREFIX= 150 LIBPREFIX=
149 DLLDIR=lib 151 DLLDIR=lib
150 UNIXONLY="#" 152 UNIXONLY="#"
@@ -1404,12 +1406,11 @@ AS_IF([test "$mysql" = "true" -a "x$enable_mysql_version_check" = "xyes"],
1404 AC_MSG_CHECKING(mysql version) 1406 AC_MSG_CHECKING(mysql version)
1405 AC_COMPILE_IFELSE([AC_LANG_PROGRAM( 1407 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
1406 [[ 1408 [[
1407 #include <mysql/mysql.h>]], 1409 #include <mysql/mysql_version.h>]],
1408 [[ 1410 [[
1409 #if (MYSQL_VERSION_ID < 40100) 1411 #if (MYSQL_VERSION_ID < 40100)
1410 #error needs at least version >= 4.1 1412 #error needs at least version >= 4.1
1411 #endif 1413 #endif
1412 int main () { return 0; }
1413 ]]) 1414 ]])
1414 ], 1415 ],
1415 [mysql=true], 1416 [mysql=true],
@@ -1423,6 +1424,21 @@ AS_IF([test "$mysql" = "true" -a "x$enable_mysql_version_check" = "xyes"],
1423 mysqlfail=false 1424 mysqlfail=false
1424 AC_MSG_RESULT(ok) 1425 AC_MSG_RESULT(ok)
1425 ]) 1426 ])
1427 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
1428 [[
1429 #include <mysql/mysql_version.h>]],
1430 [[
1431 #if (MYSQL_VERSION_ID < 80000)
1432 #error needs at least version >= 4.1
1433 #endif
1434 ]])
1435 ],
1436 [mysql8=true],
1437 [mysql8=false])
1438 AS_IF([test x$mysql8 = xtrue],
1439 [
1440 AC_DEFINE([HAVE_MYSQL8],[1],[Have mysql8])
1441 ],[])
1426]) 1442])
1427 1443
1428AM_CONDITIONAL(HAVE_MYSQL, test x$mysql = xtrue) 1444AM_CONDITIONAL(HAVE_MYSQL, test x$mysql = xtrue)
@@ -1923,6 +1939,10 @@ src/scalarproduct/Makefile
1923src/scalarproduct/scalarproduct.conf 1939src/scalarproduct/scalarproduct.conf
1924src/set/Makefile 1940src/set/Makefile
1925src/set/set.conf 1941src/set/set.conf
1942src/seti/Makefile
1943src/seti/seti.conf
1944src/setu/Makefile
1945src/setu/setu.conf
1926src/sq/Makefile 1946src/sq/Makefile
1927src/statistics/Makefile 1947src/statistics/Makefile
1928src/statistics/statistics.conf 1948src/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 @@
3# itself. 3# itself.
4 4
5BUILDCOMMON_SHLIB_FILES = \ 5BUILDCOMMON_SHLIB_FILES = \
6 build-common/sh/bin.sh/python.sh \
7 build-common/sh/lib.sh/existence.sh \
8 build-common/sh/lib.sh/existence_python.sh \
9 build-common/sh/lib.sh/msg.sh \
10 build-common/sh/lib.sh/progname.sh \
11 build-common/sh/lib.sh/version_gnunet.sh \
6 build-common/LICENSE 12 build-common/LICENSE
7 13
8BUILDCOMMON_CONF_FILES = \ 14BUILDCOMMON_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.
71* PEERINFO Subsystem:: 71* PEERINFO Subsystem::
72* PEERSTORE Subsystem:: 72* PEERSTORE Subsystem::
73* SET Subsystem:: 73* SET Subsystem::
74* SETI Subsystem::
75* SETU Subsystem::
74* STATISTICS Subsystem:: 76* STATISTICS Subsystem::
75* Distributed Hash Table (DHT):: 77* Distributed Hash Table (DHT)::
76* GNU Name System (GNS):: 78* GNU Name System (GNS)::
@@ -6535,10 +6537,13 @@ destroyed as well.
6535@node SET Subsystem 6537@node SET Subsystem
6536@section SET Subsystem 6538@section SET Subsystem
6537 6539
6538 6540The SET subsystem is in process of being replaced by the SETU and
6541SETI subsystems, which provide basically the same functionality,
6542just using two different subsystems. SETI and SETU should be used
6543for new code.
6539 6544
6540The SET service implements efficient set operations between two peers 6545The SET service implements efficient set operations between two peers
6541over a mesh tunnel. 6546over a CADET tunnel.
6542Currently, set union and set intersection are the only supported 6547Currently, set union and set intersection are the only supported
6543operations. Elements of a set consist of an @emph{element type} and 6548operations. Elements of a set consist of an @emph{element type} and
6544arbitrary binary @emph{data}. 6549arbitrary binary @emph{data}.
@@ -6907,6 +6912,513 @@ All Bloom filter operations use a salt to mingle keys before hashing them
6907into buckets, such that future iterations have a fresh chance of 6912into buckets, such that future iterations have a fresh chance of
6908succeeding if they failed due to collisions before. 6913succeeding if they failed due to collisions before.
6909 6914
6915
6916
6917
6918
6919
6920
6921
6922@cindex SETI Subsystem
6923@node SETI Subsystem
6924@section SETI Subsystem
6925
6926The SET service implements efficient set intersection between two peers
6927over a CADET tunnel.
6928Elements of a set consist of an @emph{element type} and
6929arbitrary binary @emph{data}.
6930The size of an element's data is limited to around 62 KB.
6931
6932@menu
6933* Intersection Sets::
6934* Set Intersection Modifications::
6935* Set Intersection Operations::
6936* Intersection Result Elements::
6937* libgnunetseti::
6938* The SETI Client-Service Protocol::
6939* The SETI Intersection Peer-to-Peer Protocol::
6940@end menu
6941
6942@node Intersection Sets
6943@subsection Intersection Sets
6944
6945Sets created by a local client can be modified (by adding additional elements)
6946and reused for multiple operations. If elements are to be removed, a fresh
6947set must be created by the client.
6948
6949@node Set Intersection Modifications
6950@subsection Set Intersection Modifications
6951
6952Even when set operations are active, one can add elements
6953to a set.
6954However, these changes will only be visible to operations that have been
6955created after the changes have taken place. That is, every set operation
6956only sees a snapshot of the set from the time the operation was started.
6957This mechanism is @emph{not} implemented by copying the whole set, but by
6958attaching @emph{generation information} to each element and operation.
6959
6960@node Set Intersection Operations
6961@subsection Set Intersection Operations
6962
6963Set operations can be started in two ways: Either by accepting an
6964operation request from a remote peer, or by requesting a set operation
6965from a remote peer.
6966Set operations are uniquely identified by the involved @emph{peers}, an
6967@emph{application id} and the @emph{operation type}.
6968
6969The client is notified of incoming set operations by @emph{set listeners}.
6970A set listener listens for incoming operations of a specific operation
6971type and application id.
6972Once notified of an incoming set request, the client can accept the set
6973request (providing a local set for the operation) or reject it.
6974
6975@node Intersection Result Elements
6976@subsection Intersection Result Elements
6977
6978The SET service has two @emph{result modes} that determine how an
6979operation's result set is delivered to the client:
6980
6981@itemize @bullet
6982@item @strong{Return intersection.} All elements of set resulting from the set
6983intersection are returned to the client.
6984@item @strong{Removed Elements.} Only elements that are in the local
6985peer's initial set but not in the intersection are returned.
6986@end itemize
6987
6988@cindex libgnunetseti
6989@node libgnunetseti
6990@subsection libgnunetseti
6991
6992@menu
6993* Intersection Set API::
6994* Intersection Listeners::
6995* Intersection Operations::
6996* Supplying a Set for Intersection::
6997* The Intersection Result Callback::
6998@end menu
6999
7000@node Intersection Set API
7001@subsubsection Intersection Set API
7002
7003New sets are created with @code{GNUNET_SETI_create}. Only the local peer's
7004configuration (as each set has its own client connection) must be provided.
7005The set exists until either the client calls @code{GNUNET_SET_destroy} or
7006the client's connection to the service is disrupted.
7007In the latter case, the client is notified by the return value of
7008functions dealing with sets. This return value must always be checked.
7009
7010Elements are added with @code{GNUNET_SET_add_element}.
7011
7012@node Intersection Listeners
7013@subsubsection Intersection Listeners
7014
7015Listeners are created with @code{GNUNET_SET_listen}. Each time time a
7016remote peer suggests a set operation with an application id and operation
7017type matching a listener, the listener's callback is invoked.
7018The client then must synchronously call either @code{GNUNET_SET_accept}
7019or @code{GNUNET_SET_reject}. Note that the operation will not be started
7020until the client calls @code{GNUNET_SET_commit}
7021(see Section "Supplying a Set").
7022
7023@node Intersection Operations
7024@subsubsection Intersection Operations
7025
7026Operations to be initiated by the local peer are created with
7027@code{GNUNET_SET_prepare}. Note that the operation will not be started
7028until the client calls @code{GNUNET_SET_commit}
7029(see Section "Supplying a Set").
7030
7031@node Supplying a Set for Intersection
7032@subsubsection Supplying a Set for Intersection
7033
7034To create symmetry between the two ways of starting a set operation
7035(accepting and initiating it), the operation handles returned by
7036@code{GNUNET_SET_accept} and @code{GNUNET_SET_prepare} do not yet have a
7037set to operate on, thus they can not do any work yet.
7038
7039The client must call @code{GNUNET_SET_commit} to specify a set to use for
7040an operation. @code{GNUNET_SET_commit} may only be called once per set
7041operation.
7042
7043@node The Intersection Result Callback
7044@subsubsection The Intersection Result Callback
7045
7046Clients must specify both a result mode and a result callback with
7047@code{GNUNET_SET_accept} and @code{GNUNET_SET_prepare}. The result
7048callback with a status indicating either that an element was received, or
7049the operation failed or succeeded.
7050The interpretation of the received element depends on the result mode.
7051The callback needs to know which result mode it is used in, as the
7052arguments do not indicate if an element is part of the full result set,
7053or if it is in the difference between the original set and the final set.
7054
7055@node The SETI Client-Service Protocol
7056@subsection The SETI Client-Service Protocol
7057
7058@menu
7059* Creating Intersection Sets::
7060* Listeners for Intersection::
7061* Initiating Intersection Operations::
7062* Modifying Intersection Sets::
7063* Intersection Results and Operation Status::
7064@end menu
7065
7066@node Creating Intersection Sets
7067@subsubsection Creating Intersection Sets
7068
7069For each set of a client, there exists a client connection to the service.
7070Sets are created by sending the @code{GNUNET_SERVICE_SETI_CREATE} message
7071over a new client connection. Multiple operations for one set are
7072multiplexed over one client connection, using a request id supplied by
7073the client.
7074
7075@node Listeners for Intersection
7076@subsubsection Listeners for Intersection
7077
7078Each listener also requires a seperate client connection. By sending the
7079@code{GNUNET_SERVICE_SETI_LISTEN} message, the client notifies the service
7080of the application id and operation type it is interested in. A client
7081rejects an incoming request by sending @code{GNUNET_SERVICE_SETI_REJECT}
7082on the listener's client connection.
7083In contrast, when accepting an incoming request, a
7084@code{GNUNET_SERVICE_SETI_ACCEPT} message must be sent over the@ set that
7085is supplied for the set operation.
7086
7087@node Initiating Intersection Operations
7088@subsubsection Initiating Intersection Operations
7089
7090Operations with remote peers are initiated by sending a
7091@code{GNUNET_SERVICE_SETI_EVALUATE} message to the service. The@ client
7092connection that this message is sent by determines the set to use.
7093
7094@node Modifying Intersection Sets
7095@subsubsection Modifying Intersection Sets
7096
7097Sets are modified with the @code{GNUNET_SERVICE_SETI_ADD} message.
7098
7099
7100@c %@menu
7101@c %* Results and Operation Status::
7102@c %* Iterating Sets::
7103@c %@end menu
7104
7105@node Intersection Results and Operation Status
7106@subsubsection Intersection Results and Operation Status
7107
7108The service notifies the client of result elements and success/failure of
7109a set operation with the @code{GNUNET_SERVICE_SETI_RESULT} message.
7110
7111@node The SETI Intersection Peer-to-Peer Protocol
7112@subsection The SETI Intersection Peer-to-Peer Protocol
7113
7114The intersection protocol operates over CADET and starts with a
7115GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST being sent by the peer
7116initiating the operation to the peer listening for inbound requests.
7117It includes the number of elements of the initiating peer, which is used
7118to decide which side will send a Bloom filter first.
7119
7120The listening peer checks if the operation type and application
7121identifier are acceptable for its current state.
7122If not, it responds with a GNUNET_MESSAGE_TYPE_SETI_RESULT and a status of
7123GNUNET_SETI_STATUS_FAILURE (and terminates the CADET channel).
7124
7125If the application accepts the request, the listener sends back a
7126@code{GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO} if it has
7127more elements in the set than the client.
7128Otherwise, it immediately starts with the Bloom filter exchange.
7129If the initiator receives a
7130@code{GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO} response,
7131it beings the Bloom filter exchange, unless the set size is indicated to
7132be zero, in which case the intersection is considered finished after
7133just the initial handshake.
7134
7135
7136@menu
7137* The Bloom filter exchange in SETI::
7138* Intersection Salt::
7139@end menu
7140
7141@node The Bloom filter exchange in SETI
7142@subsubsection The Bloom filter exchange in SETI
7143
7144In this phase, each peer transmits a Bloom filter over the remaining
7145keys of the local set to the other peer using a
7146@code{GNUNET_MESSAGE_TYPE_SETI_P2P_BF} message. This
7147message additionally includes the number of elements left in the sender's
7148set, as well as the XOR over all of the keys in that set.
7149
7150The number of bits 'k' set per element in the Bloom filter is calculated
7151based on the relative size of the two sets.
7152Furthermore, the size of the Bloom filter is calculated based on 'k' and
7153the number of elements in the set to maximize the amount of data filtered
7154per byte transmitted on the wire (while avoiding an excessively high
7155number of iterations).
7156
7157The receiver of the message removes all elements from its local set that
7158do not pass the Bloom filter test.
7159It then checks if the set size of the sender and the XOR over the keys
7160match what is left of its own set. If they do, it sends a
7161@code{GNUNET_MESSAGE_TYPE_SETI_P2P_DONE} back to indicate
7162that the latest set is the final result.
7163Otherwise, the receiver starts another Bloom filter exchange, except
7164this time as the sender.
7165
7166@node Intersection Salt
7167@subsubsection Intersection Salt
7168
7169Bloom filter operations are probabilistic: With some non-zero probability
7170the test may incorrectly say an element is in the set, even though it is
7171not.
7172
7173To mitigate this problem, the intersection protocol iterates exchanging
7174Bloom filters using a different random 32-bit salt in each iteration (the
7175salt is also included in the message).
7176With different salts, set operations may fail for different elements.
7177Merging the results from the executions, the probability of failure drops
7178to zero.
7179
7180The iterations terminate once both peers have established that they have
7181sets of the same size, and where the XOR over all keys computes the same
7182512-bit value (leaving a failure probability of 2-511).
7183
7184
7185@cindex SETU Subsystem
7186@node SETU Subsystem
7187@section SETU Subsystem
7188
7189The SETU service implements efficient set union operations between two peers
7190over a CADET tunnel. Elements of a set consist of an @emph{element type} and
7191arbitrary binary @emph{data}. The size of an element's data is limited to
7192around 62 KB.
7193
7194@menu
7195* Union Sets::
7196* Set Union Modifications::
7197* Set Union Operations::
7198* Union Result Elements::
7199* libgnunetsetu::
7200* The SETU Client-Service Protocol::
7201* The SETU Union Peer-to-Peer Protocol::
7202@end menu
7203
7204@node Union Sets
7205@subsection Union Sets
7206
7207Sets created by a local client can be modified (by adding additional elements)
7208and reused for multiple operations. If elements are to be removed, a fresh
7209set must be created by the client.
7210
7211@node Set Union Modifications
7212@subsection Set Union Modifications
7213
7214Even when set operations are active, one can add elements
7215to a set.
7216However, these changes will only be visible to operations that have been
7217created after the changes have taken place. That is, every set operation
7218only sees a snapshot of the set from the time the operation was started.
7219This mechanism is @emph{not} implemented by copying the whole set, but by
7220attaching @emph{generation information} to each element and operation.
7221
7222@node Set Union Operations
7223@subsection Set Union Operations
7224
7225Set operations can be started in two ways: Either by accepting an
7226operation request from a remote peer, or by requesting a set operation
7227from a remote peer.
7228Set operations are uniquely identified by the involved @emph{peers}, an
7229@emph{application id} and the @emph{operation type}.
7230
7231The client is notified of incoming set operations by @emph{set listeners}.
7232A set listener listens for incoming operations of a specific operation
7233type and application id.
7234Once notified of an incoming set request, the client can accept the set
7235request (providing a local set for the operation) or reject it.
7236
7237@node Union Result Elements
7238@subsection Union Result Elements
7239
7240The SET service has three @emph{result modes} that determine how an
7241operation's result set is delivered to the client:
7242
7243@itemize @bullet
7244@item @strong{Locally added Elements.} Elements that are in the union
7245but not already in the local peer's set are returned.
7246@item @strong{Remote added Elements.} Additionally, notify the client
7247if the remote peer lacked some elements and thus also return to the
7248local client those elements that we are sending to the remote peer to
7249be added to its union. Obtaining these elements requires setting
7250the @code{GNUNET_SETU_OPTION_SYMMETRIC} option.
7251@end itemize
7252
7253@cindex libgnunetsetu
7254@node libgnunetsetu
7255@subsection libgnunetsetu
7256
7257@menu
7258* Union Set API::
7259* Union Listeners::
7260* Union Operations::
7261* Supplying a Set for Union::
7262* The Union Result Callback::
7263@end menu
7264
7265@node Union Set API
7266@subsubsection Union Set API
7267
7268New sets are created with @code{GNUNET_SETU_create}. Only the local peer's
7269configuration (as each set has its own client connection) must be provided.
7270The set exists until either the client calls @code{GNUNET_SETU_destroy} or
7271the client's connection to the service is disrupted.
7272In the latter case, the client is notified by the return value of
7273functions dealing with sets. This return value must always be checked.
7274
7275Elements are added with @code{GNUNET_SETU_add_element}.
7276
7277@node Union Listeners
7278@subsubsection Union Listeners
7279
7280Listeners are created with @code{GNUNET_SETU_listen}. Each time time a
7281remote peer suggests a set operation with an application id and operation
7282type matching a listener, the listener's callback is invoked.
7283The client then must synchronously call either @code{GNUNET_SETU_accept}
7284or @code{GNUNET_SETU_reject}. Note that the operation will not be started
7285until the client calls @code{GNUNET_SETU_commit}
7286(see Section "Supplying a Set").
7287
7288@node Union Operations
7289@subsubsection Union Operations
7290
7291Operations to be initiated by the local peer are created with
7292@code{GNUNET_SETU_prepare}. Note that the operation will not be started
7293until the client calls @code{GNUNET_SETU_commit}
7294(see Section "Supplying a Set").
7295
7296@node Supplying a Set for Union
7297@subsubsection Supplying a Set for Union
7298
7299To create symmetry between the two ways of starting a set operation
7300(accepting and initiating it), the operation handles returned by
7301@code{GNUNET_SETU_accept} and @code{GNUNET_SETU_prepare} do not yet have a
7302set to operate on, thus they can not do any work yet.
7303
7304The client must call @code{GNUNET_SETU_commit} to specify a set to use for
7305an operation. @code{GNUNET_SETU_commit} may only be called once per set
7306operation.
7307
7308@node The Union Result Callback
7309@subsubsection The Union Result Callback
7310
7311Clients must specify both a result mode and a result callback with
7312@code{GNUNET_SETU_accept} and @code{GNUNET_SETU_prepare}. The result
7313callback with a status indicating either that an element was received,
7314transmitted to the other peer (if this information was requested), or
7315if the operation failed or ultimately succeeded.
7316
7317@node The SETU Client-Service Protocol
7318@subsection The SETU Client-Service Protocol
7319
7320@menu
7321* Creating Union Sets::
7322* Listeners for Union::
7323* Initiating Union Operations::
7324* Modifying Union Sets::
7325* Union Results and Operation Status::
7326@end menu
7327
7328@node Creating Union Sets
7329@subsubsection Creating Union Sets
7330
7331For each set of a client, there exists a client connection to the service.
7332Sets are created by sending the @code{GNUNET_SERVICE_SETU_CREATE} message
7333over a new client connection. Multiple operations for one set are
7334multiplexed over one client connection, using a request id supplied by
7335the client.
7336
7337@node Listeners for Union
7338@subsubsection Listeners for Union
7339
7340Each listener also requires a seperate client connection. By sending the
7341@code{GNUNET_SERVICE_SETU_LISTEN} message, the client notifies the service
7342of the application id and operation type it is interested in. A client
7343rejects an incoming request by sending @code{GNUNET_SERVICE_SETU_REJECT}
7344on the listener's client connection.
7345In contrast, when accepting an incoming request, a
7346@code{GNUNET_SERVICE_SETU_ACCEPT} message must be sent over the@ set that
7347is supplied for the set operation.
7348
7349@node Initiating Union Operations
7350@subsubsection Initiating Union Operations
7351
7352
7353
7354Operations with remote peers are initiated by sending a
7355@code{GNUNET_SERVICE_SETU_EVALUATE} message to the service. The@ client
7356connection that this message is sent by determines the set to use.
7357
7358@node Modifying Union Sets
7359@subsubsection Modifying Union Sets
7360
7361Sets are modified with the @code{GNUNET_SERVICE_SETU_ADD} message.
7362
7363
7364@c %@menu
7365@c %* Results and Operation Status::
7366@c %* Iterating Sets::
7367@c %@end menu
7368
7369@node Union Results and Operation Status
7370@subsubsection Union Results and Operation Status
7371
7372The service notifies the client of result elements and success/failure of
7373a set operation with the @code{GNUNET_SERVICE_SETU_RESULT} message.
7374
7375
7376@node The SETU Union Peer-to-Peer Protocol
7377@subsection The SETU Union Peer-to-Peer Protocol
7378
7379
7380The SET union protocol is based on Eppstein's efficient set reconciliation
7381without prior context. You should read this paper first if you want to
7382understand the protocol.
7383
7384The union protocol operates over CADET and starts with a
7385GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST being sent by the peer
7386initiating the operation to the peer listening for inbound requests.
7387It includes the number of elements of the initiating peer, which is
7388currently not used.
7389
7390The listening peer checks if the operation type and application
7391identifier are acceptable for its current state. If not, it responds with
7392a @code{GNUNET_MESSAGE_TYPE_SETU_RESULT} and a status of
7393@code{GNUNET_SETU_STATUS_FAILURE} (and terminates the CADET channel).
7394
7395If the application accepts the request, it sends back a strata estimator
7396using a message of type GNUNET_MESSAGE_TYPE_SETU_P2P_SE. The
7397initiator evaluates the strata estimator and initiates the exchange of
7398invertible Bloom filters, sending a GNUNET_MESSAGE_TYPE_SETU_P2P_IBF.
7399
7400During the IBF exchange, if the receiver cannot invert the Bloom filter or
7401detects a cycle, it sends a larger IBF in response (up to a defined
7402maximum limit; if that limit is reached, the operation fails).
7403Elements decoded while processing the IBF are transmitted to the other
7404peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS, or requested from the
7405other peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS messages,
7406depending on the sign observed during decoding of the IBF.
7407Peers respond to a GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS message
7408with the respective element in a GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS
7409message. If the IBF fully decodes, the peer responds with a
7410GNUNET_MESSAGE_TYPE_SETU_P2P_DONE message instead of another
7411GNUNET_MESSAGE_TYPE_SETU_P2P_IBF.
7412
7413All Bloom filter operations use a salt to mingle keys before hashing them
7414into buckets, such that future iterations have a fresh chance of
7415succeeding if they failed due to collisions before.
7416
7417
7418
7419
7420
7421
6910@cindex STATISTICS Subsystem 7422@cindex STATISTICS Subsystem
6911@node STATISTICS Subsystem 7423@node STATISTICS Subsystem
6912@section STATISTICS Subsystem 7424@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.
1988@node reclaimID Identity Provider 1988@node reclaimID Identity Provider
1989@section reclaimID Identity Provider 1989@section reclaimID Identity Provider
1990 1990
1991The reclaimID Identity Provider (IdP) is a decentralized IdP service. 1991The re:claimID Identity Provider (IdP) is a decentralized IdP service.
1992It allows its users to manage and authorize third parties to access 1992It allows its users to manage and authorize third parties to access
1993their identity attributes such as email or shipping addresses. 1993their identity attributes such as email or shipping addresses.
1994 1994
1995It basically mimics the concepts of centralized IdPs, such as those 1995It basically mimics the concepts of centralized IdPs, such as those
1996offered by Google or Facebook. 1996offered by Google or Facebook.
1997Like other IdPs, reclaimID features an (optional) OpenID-Connect 1997Like other IdPs, reclaimID features an (optional) OpenID Connect
19981.0-compliant protocol layer that can be used for websites to 19981.0-compliant protocol layer that can be used for websites to
1999integrate reclaimID as an Identity Provider with little effort. 1999integrate reclaimID as an Identity Provider with little effort.
2000 2000
@@ -2038,38 +2038,45 @@ In the future there might be more value types such as X.509 certificate credenti
2038If you want to allow a third party such as a website or friend to access to your attributes (or a subset thereof) execute: 2038If you want to allow a third party such as a website or friend to access to your attributes (or a subset thereof) execute:
2039 2039
2040@example 2040@example
2041$ gnunet-reclaim -e "user" -r "PKEY" -i "attribute1,attribute2,..." 2041$ TICKET=$(gnunet-reclaim -e "user" -r "$RP_KEY" -i "attribute1,attribute2,...")
2042@end example 2042@end example
2043 2043
2044Where "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.
2045
2046The command will return a "ticket" string. 2044The command will return a "ticket" string.
2047You must give this "ticket" to the requesting third party. 2045You must give $TICKET to the requesting third party.
2046
2047$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.
2048
2049The third party may retrieve the key in string format for use in the above
2050call using "gnunet-identity":
2051
2052@example
2053$ RP_KEY=$(gnunet-identity -d grep "relyingparty" | awk '@{print $3@}')
2054@end example
2048 2055
2049The third party can then retrieve your shared identity attributes using: 2056The third party can then retrieve your shared identity attributes using:
2050 2057
2051@example 2058@example
2052$ gnunet-reclaim -e "friend" -C "ticket" 2059$ gnunet-reclaim -e "relyingparty" -C "ticket"
2053@end example 2060@end example
2054 2061
2055Where "friend" is the name for "user" that the requesting party is using. 2062Where "relyingparty" is the name for the identity behind $RP_KEY that the
2063requesting party is using.
2056This will retrieve and list the shared identity attributes. 2064This will retrieve and list the shared identity attributes.
2057The above command will also work if the user is currently offline since the attributes are retrieved from GNS. 2065The above command will also work if the user is currently offline since the attributes are retrieved from GNS.
2058Further, 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. 2066Further, $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.
2059 2067
2060To list all given authorizations (tickets) you can execute: 2068To list all given authorizations (tickets) you can execute:
2061@example 2069@example
2062$ gnunet-reclaim -e "friend" -T (TODO there is only a C and REST API for this at this time) 2070$ gnunet-reclaim -e "user" -T
2063@end example 2071@end example
2064 2072
2065
2066@node Revoking Authorizations of Third Parties 2073@node Revoking Authorizations of Third Parties
2067@subsection Revoking Authorizations of Third Parties 2074@subsection Revoking Authorizations of Third Parties
2068 2075
2069If you want to revoke the access of a third party to your attributes you can execute: 2076If you want to revoke the access of a third party to your attributes you can execute:
2070 2077
2071@example 2078@example
2072$ gnunet-reclaim -e "user" -R "ticket" 2079$ gnunet-reclaim -e "user" -R $TICKET
2073@end example 2080@end example
2074 2081
2075This will prevent the third party from accessing the attribute in the future. 2082This 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.
2080@node OpenID Connect 2087@node OpenID Connect
2081@subsection OpenID Connect 2088@subsection OpenID Connect
2082 2089
2083There is an OpenID Connect API for use with reclaimID. 2090There is an @uref{OpenID Connect, https://openid.net/specs/openid-connect-core-1_0.html} API for use with re:claimID.
2084However, its use is quite complicated to setup. 2091However, its use is quite complicated to setup.
2085As a proof-of-concept, you can look at https://gitlab.com/reclaimid.
2086
2087In the PoC and by convention for reclaimID, the OpenID Connect Endpoints are
2088found at:
2089 2092
2090@example 2093@example
2091http://api.reclaim/openid/authorize 2094https://api.reclaim/openid/authorize
2092http://api.reclaim/openid/token 2095http://localhost:7776/openid/token
2093http://api.reclaim/openid/userinfo 2096http://localhost:7776/openid/userinfo
2094http://api.reclaim/openid/login 2097http://localhost:7776/openid/login
2095@end example 2098@end example
2096 2099
2097The token endpoint is protected using HTTP basic authentication. 2100The token endpoint is protected using HTTP basic authentication.
2098You can authenticate using any username and the password configured under: 2101You can authenticate using any username and the password configured under:
2099 2102
2100@example 2103@example
2101$ gnunet-config -s reclaim-rest-plugin -o PSW 2104$ gnunet-config -s reclaim-rest-plugin -o OIDC_CLIENT_SECRET
2102@end example 2105@end example
2103 2106
2104The authorize endpoint is protected using a Cookie which can be obtained through 2107The authorize endpoint is protected using a Cookie which can be obtained through
2105a request against the login endpoint. 2108a request against the login endpoint.
2106This flow is meant to be used in the context of the OpenID Connect authorization 2109This functionality is meant to be used in the context of the OpenID Connect authorization
2107flow to collect user consent interactively. 2110flow to collect user consent interactively.
2108Without a Cookie, the authorize endpoint redirects to a URI configured under: 2111Without a Cookie, the authorize endpoint redirects to a URI configured under:
2109 2112
@@ -2111,17 +2114,22 @@ Without a Cookie, the authorize endpoint redirects to a URI configured under:
2111$ gnunet-config -s reclaim-rest-plugin -o ADDRESS 2114$ gnunet-config -s reclaim-rest-plugin -o ADDRESS
2112@end example 2115@end example
2113 2116
2114Our PoC includes a user interface (https://gitlab.com/reclaimid) which
2115integrates this process is an OpenID Connect compatible fashion.
2116
2117The token endpoint is protected using OAuth2 and expects the grant 2117The token endpoint is protected using OAuth2 and expects the grant
2118which is retrieved from the authorization endpoint according to the standard. 2118which is retrieved from the authorization endpoint according to the standard.
2119 2119
2120The userinfo endpoint is protected using OAuth2 and expects a bearer access 2120The userinfo endpoint is protected using OAuth2 and expects a bearer access
2121token which is retrieved from a token request. 2121token which is retrieved from a token request.
2122 2122
2123In order to create and register a client you need to execute the following 2123In order to make use of OpenID Connect flows as a user, you need to install
2124steps: 2124the browser plugin:
2125
2126@itemize @bullet
2127@item @uref{https://addons.mozilla.org/addon/reclaimid/, Firefox Add-on}
2128@item @uref{https://chrome.google.com/webstore/detail/reclaimid/jiogompmdejcnacmlnjhnaicgkefcfll, Chrome Web Store}
2129@end itemize
2130
2131In order to create and register an OpenID Connect client as a relying party,
2132you need to execute the following steps:
2125 2133
2126@example 2134@example
2127$ gnunet-identity -C <client_name> 2135$ gnunet-identity -C <client_name>
@@ -2129,16 +2137,23 @@ $ gnunet-namestore -z <client_name> -a -n "@@" -t RECLAIM_OIDC_REDIRECT -V <redi
2129$ gnunet-namestore -z <client_name> -a -n "@@" -t RECLAIM_OIDC_CLIENT -V "My OIDC Client" -e 1d -p 2137$ gnunet-namestore -z <client_name> -a -n "@@" -t RECLAIM_OIDC_CLIENT -V "My OIDC Client" -e 1d -p
2130@end example 2138@end example
2131 2139
2132The client_id will be the public key of the client. 2140The "client_id" for use in OpenID Connect is the public key of the client as
2133As a redirect URI, you may use any globally unique DNS or GNS URI. 2141displayed using:
2134The client description will be displayed to the user on authorization. 2142@example
2143$ gnunet-identity -d grep "relyingparty" | awk '@{print $3@}'
2144@end example
2145
2146The RECLAIM_OIDC_REDIRECT record contains your website redirect URI.
2147You may use any globally unique DNS or GNS URI.
2148The RECLAIM_OIDC_CLIENT record represents the client description which whill
2149be displayed to users in an authorization request.
2135 2150
2136Any website or relying party must use the endpoint 2151Any website or relying party must use the authorization endpoint
2137https://api.reclaim/openid/authorize in its authorization redirects, e.g. 2152@uref{https://api.reclaim/openid/authorize} in its authorization redirects, e.g.
2138 2153
2139@example 2154@example
2140<a href="https://api.reclaim/openid/authorize?client_id=<PKEY>\ 2155<a href="https://api.reclaim/openid/authorize?client_id=<PKEY>\
2141 &scope=email\ 2156 &scope=openid email\
2142 &redirect_uri=<redirect_uri>\ 2157 &redirect_uri=<redirect_uri>\
2143 &nonce=<random>">Login</a> 2158 &nonce=<random>">Login</a>
2144@end example 2159@end example
@@ -2146,7 +2161,17 @@ https://api.reclaim/openid/authorize in its authorization redirects, e.g.
2146This will direct the user's browser onto his local reclaimID instance. 2161This will direct the user's browser onto his local reclaimID instance.
2147After giving consent, you will be provided with the OpenID Connect authorization 2162After giving consent, you will be provided with the OpenID Connect authorization
2148code according to the specifications at your provided redirect URI. 2163code according to the specifications at your provided redirect URI.
2149The example code for the PoC website can be found at https://gitlab.com/reclaimid/demo. 2164
2165The ID Tokens issues by the token endpoints are signed using HS512 with the
2166shared secret configured under:
2167
2168@example
2169$ gnunet-config -s reclaim-rest-plugin -o JWT_SECRET
2170@end example
2171
2172The authorization code flow optionally supports @uref{https://tools.ietf.org/html/rfc7636, Proof Key for Code Exchange}.
2173If PKCE is used, the client does not need to authenticate against the token
2174endpoint.
2150 2175
2151@node Using the Virtual Public Network 2176@node Using the Virtual Public Network
2152@section Using the Virtual Public Network 2177@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;
52 gns -> dnsstub; 52 gns -> dnsstub;
53 gns -> identity; 53 gns -> identity;
54 revocation -> core; 54 revocation -> core;
55 revocation -> set; 55 revocation -> setu;
56 namestore -> identity; 56 namestore -> identity;
57 namestore -> gnsrecord; 57 namestore -> gnsrecord;
58 dnsparser -> gnsrecord [style=dotted,color=blue]; 58 dnsparser -> gnsrecord [style=dotted,color=blue];
@@ -96,9 +96,11 @@ splines = true;
96 transport -> fragmentation; 96 transport -> fragmentation;
97 consensus -> set; 97 consensus -> set;
98 consensus -> cadet; 98 consensus -> cadet;
99 scalarproduct -> set; 99 scalarproduct -> seti;
100 scalarproduct -> cadet; 100 scalarproduct -> cadet;
101 set -> cadet; 101 set -> cadet;
102 seti -> cadet;
103 setu -> cadet;
102 peerinfo -> hello; 104 peerinfo -> hello;
103 fragmentation [shape=diamond]; 105 fragmentation [shape=diamond];
104 hello [shape=diamond]; 106 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
272src/reclaim/json_reclaim.c 272src/reclaim/json_reclaim.c
273src/reclaim/oidc_helper.c 273src/reclaim/oidc_helper.c
274src/reclaim/plugin_gnsrecord_reclaim.c 274src/reclaim/plugin_gnsrecord_reclaim.c
275src/reclaim/plugin_reclaim_attestation_jwt.c 275src/reclaim/plugin_reclaim_credential_jwt.c
276src/reclaim/plugin_reclaim_attribute_basic.c 276src/reclaim/plugin_reclaim_attribute_basic.c
277src/reclaim/plugin_rest_openid_connect.c 277src/reclaim/plugin_rest_openid_connect.c
278src/reclaim/plugin_rest_reclaim.c 278src/reclaim/plugin_rest_reclaim.c
279src/reclaim/reclaim_api.c 279src/reclaim/reclaim_api.c
280src/reclaim/reclaim_attestation.c 280src/reclaim/reclaim_credential.c
281src/reclaim/reclaim_attribute.c 281src/reclaim/reclaim_attribute.c
282src/regex/gnunet-daemon-regexprofiler.c 282src/regex/gnunet-daemon-regexprofiler.c
283src/regex/gnunet-regex-profiler.c 283src/regex/gnunet-regex-profiler.c
@@ -333,6 +333,19 @@ src/set/ibf.c
333src/set/ibf_sim.c 333src/set/ibf_sim.c
334src/set/plugin_block_set_test.c 334src/set/plugin_block_set_test.c
335src/set/set_api.c 335src/set/set_api.c
336src/seti/gnunet-service-set_intersection.c
337src/seti/gnunet-service-seti.c
338src/seti/gnunet-seti-profiler.c
339src/seti/plugin_block_seti_test.c
340src/seti/setu_api.c
341src/setu/gnunet-service-setu.c
342src/setu/gnunet-service-setu_strata_estimator.c
343src/setu/gnunet-setu-ibf-profiler.c
344src/setu/gnunet-setu-profiler.c
345src/setu/ibf.c
346src/setu/ibf_sim.c
347src/setu/plugin_block_setu_test.c
348src/setu/setu_api.c
336src/sq/sq.c 349src/sq/sq.c
337src/sq/sq_exec.c 350src/sq/sq_exec.c
338src/sq/sq_prepare.c 351src/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 = \
89 namestore \ 89 namestore \
90 cadet \ 90 cadet \
91 set \ 91 set \
92 seti \
93 setu \
92 consensus \ 94 consensus \
93 scalarproduct \ 95 scalarproduct \
94 revocation \ 96 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,
496 return; /* was canceled */ 496 return; /* was canceled */
497 497
498 memset (&allzeros, '\0', sizeof(allzeros)); 498 memset (&allzeros, '\0', sizeof(allzeros));
499 if ((0 == GNUNET_is_zero (&pi->peer)) && 499 if ((GNUNET_YES == GNUNET_is_zero (&pi->peer)) &&
500 (0 == plugin_name_length) && 500 (0 == plugin_name_length) &&
501 (0 == plugin_address_length)) 501 (0 == plugin_address_length))
502 { 502 {
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,
685 memset (&allzeros, 685 memset (&allzeros,
686 '\0', 686 '\0',
687 sizeof(struct GNUNET_PeerIdentity)); 687 sizeof(struct GNUNET_PeerIdentity));
688 if (0 == GNUNET_is_zero (&alrm->peer)) 688 if (GNUNET_YES == GNUNET_is_zero (&alrm->peer))
689 { 689 {
690 /* Return addresses for all peers */ 690 /* Return addresses for all peers */
691 GAS_addresses_get_peer_info (NULL, 691 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)
245 char *ret; 245 char *ret;
246 246
247 if ((NULL == cp) || 247 if ((NULL == cp) ||
248 (0 == GNUNET_is_zero (&cp->pid.public_key))) 248 (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key)))
249 return "NULL"; 249 return "NULL";
250 250
251 ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key); 251 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,
472 472
473 473
474/** 474/**
475 * Add @a extra_headers to the HTTP headers for @a job.
476 *
477 * @param[in,out] job the job to modify
478 * @param extra_headers headers to append
479 */
480void
481GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
482 const struct curl_slist *extra_headers)
483{
484 struct curl_slist *all_headers = job->job_headers;
485
486 for (const struct curl_slist *curr = extra_headers;
487 NULL != curr;
488 curr = curr->next)
489 {
490 GNUNET_assert (NULL !=
491 (all_headers = curl_slist_append (all_headers,
492 curr->data)));
493 }
494 job->job_headers = all_headers;
495}
496
497
498/**
475 * Schedule a CURL request to be executed and call the given @a jcc 499 * Schedule a CURL request to be executed and call the given @a jcc
476 * upon its completion. Note that the context will make use of the 500 * upon its completion. Note that the context will make use of the
477 * CURLOPT_PRIVATE facility of the CURL @a eh. Used to download 501 * CURLOPT_PRIVATE facility of the CURL @a eh. Used to download
@@ -864,7 +888,8 @@ do_benchmark (CURLMsg *cmsg)
864 curl -w "foo%{size_request} -XPOST --data "ABC" $URL 888 curl -w "foo%{size_request} -XPOST --data "ABC" $URL
865 the CURLINFO_REQUEST_SIZE should be the whole size of the request 889 the CURLINFO_REQUEST_SIZE should be the whole size of the request
866 including headers and body. 890 including headers and body.
867 */GNUNET_break (size_curl <= size_long); 891 *///
892 GNUNET_break (size_curl <= size_long);
868 893
869 urd = get_url_benchmark_data (url, (unsigned int) response_code); 894 urd = get_url_benchmark_data (url, (unsigned int) response_code);
870 urd->count++; 895 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
81struct RequestHandle 81struct RequestHandle
82{ 82{
83 /** 83 /**
84 * DLL
85 */
86 struct RequestHandle *next;
87
88 /**
89 * DLL
90 */
91 struct RequestHandle *prev;
92
93 /**
84 * Active GNS lookup 94 * Active GNS lookup
85 */ 95 */
86 struct GNUNET_GNS_LookupWithTldRequest *gns_lookup; 96 struct GNUNET_GNS_LookupWithTldRequest *gns_lookup;
@@ -136,6 +146,15 @@ struct RequestHandle
136 int response_code; 146 int response_code;
137}; 147};
138 148
149/**
150 * DLL
151 */
152static struct RequestHandle *requests_head;
153
154/**
155 * DLL
156 */
157static struct RequestHandle *requests_tail;
139 158
140/** 159/**
141 * Cleanup lookup handle 160 * Cleanup lookup handle
@@ -165,6 +184,9 @@ cleanup_handle (void *cls)
165 if (NULL != handle->emsg) 184 if (NULL != handle->emsg)
166 GNUNET_free (handle->emsg); 185 GNUNET_free (handle->emsg);
167 186
187 GNUNET_CONTAINER_DLL_remove (requests_head,
188 requests_tail,
189 handle);
168 GNUNET_free (handle); 190 GNUNET_free (handle);
169} 191}
170 192
@@ -198,7 +220,7 @@ do_error (void *cls)
198 handle->proc (handle->proc_cls, resp, handle->response_code); 220 handle->proc (handle->proc_cls, resp, handle->response_code);
199 json_decref (json_error); 221 json_decref (json_error);
200 GNUNET_free (response); 222 GNUNET_free (response);
201 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 223 cleanup_handle(handle);
202} 224}
203 225
204 226
@@ -374,8 +396,12 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
374 handle->proc_cls = proc_cls; 396 handle->proc_cls = proc_cls;
375 handle->proc = proc; 397 handle->proc = proc;
376 handle->rest_handle = rest_handle; 398 handle->rest_handle = rest_handle;
377
378 handle->url = GNUNET_strdup (rest_handle->url); 399 handle->url = GNUNET_strdup (rest_handle->url);
400 handle->timeout_task =
401 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
402 GNUNET_CONTAINER_DLL_insert (requests_head,
403 requests_tail,
404 handle);
379 if (handle->url[strlen (handle->url) - 1] == '/') 405 if (handle->url[strlen (handle->url) - 1] == '/')
380 handle->url[strlen (handle->url) - 1] = '\0'; 406 handle->url[strlen (handle->url) - 1] = '\0';
381 if (GNUNET_NO == 407 if (GNUNET_NO ==
@@ -386,8 +412,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
386 } 412 }
387 413
388 414
389 handle->timeout_task =
390 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
391 return GNUNET_YES; 415 return GNUNET_YES;
392} 416}
393 417
@@ -405,8 +429,6 @@ libgnunet_plugin_rest_gns_init (void *cls)
405 struct GNUNET_REST_Plugin *api; 429 struct GNUNET_REST_Plugin *api;
406 430
407 cfg = cls; 431 cfg = cls;
408 if (NULL != plugin.cfg)
409 return NULL; /* can only initialize once! */
410 memset (&plugin, 0, sizeof(struct Plugin)); 432 memset (&plugin, 0, sizeof(struct Plugin));
411 plugin.cfg = cfg; 433 plugin.cfg = cfg;
412 api = GNUNET_new (struct GNUNET_REST_Plugin); 434 api = GNUNET_new (struct GNUNET_REST_Plugin);
@@ -437,12 +459,18 @@ void *
437libgnunet_plugin_rest_gns_done (void *cls) 459libgnunet_plugin_rest_gns_done (void *cls)
438{ 460{
439 struct GNUNET_REST_Plugin *api = cls; 461 struct GNUNET_REST_Plugin *api = cls;
440 struct Plugin *plugin = api->cls; 462 struct RequestHandle *request;
463 struct Plugin *plugin;
464
465 while (NULL != (request = requests_head))
466 do_error (request);
441 467
442 plugin->cfg = NULL;
443 if (NULL != gns) 468 if (NULL != gns)
444 GNUNET_GNS_disconnect (gns); 469 GNUNET_GNS_disconnect (gns);
445 470
471 plugin = api->cls;
472
473 plugin->cfg = NULL;
446 474
447 GNUNET_free (allow_methods); 475 GNUNET_free (allow_methods);
448 GNUNET_free (api); 476 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
3test_gnsrecord_serialization 3test_gnsrecord_serialization
4zonefiles 4zonefiles
5perf_gnsrecord_crypto 5perf_gnsrecord_crypto
6gnunet-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
191struct RequestHandle 191struct RequestHandle
192{ 192{
193 /** 193 /**
194 * DLL
195 */
196 struct RequestHandle *next;
197
198 /**
199 * DLL
200 */
201 struct RequestHandle *prev;
202
203 /**
194 * The data from the REST request 204 * The data from the REST request
195 */ 205 */
196 const char *data; 206 const char *data;
@@ -252,6 +262,16 @@ struct RequestHandle
252}; 262};
253 263
254/** 264/**
265 * DLL
266 */
267static struct RequestHandle *requests_head;
268
269/**
270 * DLL
271 */
272static struct RequestHandle *requests_tail;
273
274/**
255 * Cleanup lookup handle 275 * Cleanup lookup handle
256 * @param handle Handle to clean up 276 * @param handle Handle to clean up
257 */ 277 */
@@ -273,7 +293,9 @@ cleanup_handle (void *cls)
273 GNUNET_free (handle->emsg); 293 GNUNET_free (handle->emsg);
274 if (NULL != handle->name) 294 if (NULL != handle->name)
275 GNUNET_free (handle->name); 295 GNUNET_free (handle->name);
276 296 GNUNET_CONTAINER_DLL_remove (requests_head,
297 requests_tail,
298 handle);
277 GNUNET_free (handle); 299 GNUNET_free (handle);
278} 300}
279 301
@@ -1274,13 +1296,13 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1274 struct RequestHandle *handle = GNUNET_new (struct RequestHandle); 1296 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1275 struct GNUNET_REST_RequestHandlerError err; 1297 struct GNUNET_REST_RequestHandlerError err;
1276 static const struct GNUNET_REST_RequestHandler handlers[] = 1298 static const struct GNUNET_REST_RequestHandler handlers[] =
1277 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all }, 1299 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1278 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1279 &ego_get_pubkey }, 1300 &ego_get_pubkey },
1280 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name }, 1301 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
1281 { MHD_HTTP_METHOD_GET, 1302 { MHD_HTTP_METHOD_GET,
1282 GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, 1303 GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
1283 &ego_get_subsystem }, 1304 &ego_get_subsystem },
1305 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
1284 { MHD_HTTP_METHOD_PUT, 1306 { MHD_HTTP_METHOD_PUT,
1285 GNUNET_REST_API_NS_IDENTITY_PUBKEY, 1307 GNUNET_REST_API_NS_IDENTITY_PUBKEY,
1286 &ego_edit_pubkey }, 1308 &ego_edit_pubkey },
@@ -1310,6 +1332,11 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1310 handle->url = GNUNET_strdup (rest_handle->url); 1332 handle->url = GNUNET_strdup (rest_handle->url);
1311 if (handle->url[strlen (handle->url) - 1] == '/') 1333 if (handle->url[strlen (handle->url) - 1] == '/')
1312 handle->url[strlen (handle->url) - 1] = '\0'; 1334 handle->url[strlen (handle->url) - 1] = '\0';
1335 handle->timeout_task =
1336 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1337 GNUNET_CONTAINER_DLL_insert (requests_head,
1338 requests_tail,
1339 handle);
1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); 1340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1314 if (GNUNET_NO == 1341 if (GNUNET_NO ==
1315 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) 1342 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
@@ -1318,8 +1345,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1318 return GNUNET_NO; 1345 return GNUNET_NO;
1319 } 1346 }
1320 1347
1321 handle->timeout_task =
1322 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); 1348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1324 return GNUNET_YES; 1349 return GNUNET_YES;
1325} 1350}
@@ -1353,6 +1378,7 @@ libgnunet_plugin_rest_identity_init (void *cls)
1353 MHD_HTTP_METHOD_PUT, 1378 MHD_HTTP_METHOD_PUT,
1354 MHD_HTTP_METHOD_DELETE, 1379 MHD_HTTP_METHOD_DELETE,
1355 MHD_HTTP_METHOD_OPTIONS); 1380 MHD_HTTP_METHOD_OPTIONS);
1381 state = ID_REST_STATE_INIT;
1356 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); 1382 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1357 1383
1358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n")); 1384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
@@ -1375,6 +1401,8 @@ libgnunet_plugin_rest_identity_done (void *cls)
1375 struct EgoEntry *ego_tmp; 1401 struct EgoEntry *ego_tmp;
1376 1402
1377 plugin->cfg = NULL; 1403 plugin->cfg = NULL;
1404 while (NULL != requests_head)
1405 cleanup_handle (requests_head);
1378 if (NULL != identity_handle) 1406 if (NULL != identity_handle)
1379 GNUNET_IDENTITY_disconnect (identity_handle); 1407 GNUNET_IDENTITY_disconnect (identity_handle);
1380 1408
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 = \
119 gnunet_transport_monitor_service.h \ 119 gnunet_transport_monitor_service.h \
120 gnunet_transport_plugin.h \ 120 gnunet_transport_plugin.h \
121 gnunet_tun_lib.h \ 121 gnunet_tun_lib.h \
122 gnunet_uri_lib.h \
122 gnunet_util_lib.h \ 123 gnunet_util_lib.h \
123 gnunet_vpn_service.h 124 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
137 * Contains either special marker elements or a nested block. 137 * Contains either special marker elements or a nested block.
138 */ 138 */
139 GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT = 25, 139 GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT = 25,
140
141 /**
142 * Block for testing set intersection. If first byte of the block
143 * is non-zero, the block is considered invalid.
144 */
145 GNUNET_BLOCK_TYPE_SETI_TEST = 24,
146
147 /**
148 * Block for testing set union. If first byte of the block
149 * is non-zero, the block is considered invalid.
150 */
151 GNUNET_BLOCK_TYPE_SETU_TEST = 24,
152
140}; 153};
141 154
142 155
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,
1173 * @param a pointer to @a n bytes which should be tested for the 1173 * @param a pointer to @a n bytes which should be tested for the
1174 * entire memory being zero'ed out. 1174 * entire memory being zero'ed out.
1175 * @param n number of bytes in @a to be tested 1175 * @param n number of bytes in @a to be tested
1176 * @return 0 if a is zero, non-zero otherwise 1176 * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
1177 */ 1177 */
1178int 1178enum GNUNET_GenericReturnValue
1179GNUNET_is_zero_ (const void *a, 1179GNUNET_is_zero_ (const void *a,
1180 size_t n); 1180 size_t n);
1181 1181
@@ -1185,7 +1185,7 @@ GNUNET_is_zero_ (const void *a,
1185 * 1185 *
1186 * @param a pointer to a struct which should be tested for the 1186 * @param a pointer to a struct which should be tested for the
1187 * entire memory being zero'ed out. 1187 * entire memory being zero'ed out.
1188 * @return 0 if a is zero, non-zero otherwise 1188 * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
1189 */ 1189 */
1190#define GNUNET_is_zero(a) \ 1190#define GNUNET_is_zero(a) \
1191 GNUNET_is_zero_ (a, sizeof (*a)) 1191 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" {
50#endif 50#endif
51#endif 51#endif
52 52
53#include <sodium.h>
53 54
54/** 55/**
55 * The identity of the host (wraps the signing key of the peer). 56 * The identity of the host (wraps the signing key of the peer).
@@ -668,6 +669,15 @@ GNUNET_CRYPTO_hash (const void *block,
668 669
669 670
670/** 671/**
672 * Value for a salt for #GNUNET_CRYPTO_pow_hash().
673 */
674struct GNUNET_CRYPTO_PowSalt
675{
676 char salt[crypto_pwhash_argon2id_SALTBYTES];
677};
678
679
680/**
671 * Calculate the 'proof-of-work' hash (an expensive hash). 681 * Calculate the 'proof-of-work' hash (an expensive hash).
672 * 682 *
673 * @param salt salt for the hash. Must be crypto_pwhash_argon2id_SALTBYTES long. 683 * @param salt salt for the hash. Must be crypto_pwhash_argon2id_SALTBYTES long.
@@ -676,7 +686,7 @@ GNUNET_CRYPTO_hash (const void *block,
676 * @param result where to write the resulting hash 686 * @param result where to write the resulting hash
677 */ 687 */
678void 688void
679GNUNET_CRYPTO_pow_hash (const char *salt, 689GNUNET_CRYPTO_pow_hash (const struct GNUNET_CRYPTO_PowSalt *salt,
680 const void *buf, 690 const void *buf,
681 size_t buf_len, 691 size_t buf_len,
682 struct GNUNET_HashCode *result); 692 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,
275 275
276 276
277/** 277/**
278 * Force use of the provided TLS client certificate 278 * Force use of the provided TLS client certificate for client authentication
279 * for client authentication for all operations performed 279 * for all operations performed with @a ctx.
280 * with @a ctx.
281 * 280 *
282 * Note that if the provided information is incorrect, 281 * Note that if the provided information is incorrect,
283 * the earliest operation that could fail is 282 * the earliest operation that could fail is
@@ -298,9 +297,9 @@ GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
298 297
299 298
300/** 299/**
301 * Schedule a CURL request to be executed and call the given @a jcc 300 * Schedule a CURL request to be executed and call the given @a jcc upon its
302 * upon its completion. Note that the context will make use of the 301 * completion. Note that the context will make use of the CURLOPT_PRIVATE
303 * CURLOPT_PRIVATE facility of the CURL @a eh. 302 * facility of the CURL @a eh.
304 * 303 *
305 * This function modifies the CURL handle to add the 304 * This function modifies the CURL handle to add the
306 * "Content-Type: application/json" header if @a add_json is set. 305 * "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,
345 344
346 345
347/** 346/**
347 * Add @a extra_headers to the HTTP headers for @a job.
348 *
349 * @param[in,out] job the job to modify
350 * @param extra_headers headers to append
351 */
352void
353GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
354 const struct curl_slist *extra_headers);
355
356
357/**
348 * Cancel a job. Must only be called before the job completion 358 * Cancel a job. Must only be called before the job completion
349 * callback is called for the respective job. 359 * callback is called for the respective job.
350 * 360 *
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" {
143/** 143/**
144 * Record type for an attribute attestation 144 * Record type for an attribute attestation
145 */ 145 */
146#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION 65554 146#define GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL 65554
147 147
148/** 148/**
149 * Record type for an attestation reference in a ticket 149 * Record type for a presentation of a credential (used
150 * in a ticket record set)
150 */ 151 */
151#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF 65555 152#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
152 153
153 154
154/** 155/**
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
245 /** 245 /**
246 * Memory for MySQL to notify us about NULL values. 246 * Memory for MySQL to notify us about NULL values.
247 */ 247 */
248 my_bool is_null; 248 MYSQL_BOOL is_null;
249}; 249};
250 250
251 251
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"
41#endif 41#endif
42#endif 42#endif
43 43
44#ifdef HAVE_MYSQL8
45 typedef bool MYSQL_BOOL;
46#else
47 typedef my_bool MYSQL_BOOL; //MySQL < 8 wants this
48#endif
49
44 50
45/** 51/**
46 * Mysql context. 52 * 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" {
1659 1659
1660 1660
1661/******************************************************************************* 1661/*******************************************************************************
1662 * SETU message types
1663 ******************************************************************************/
1664
1665
1666/**
1667 * Cancel a set operation
1668 */
1669#define GNUNET_MESSAGE_TYPE_SETU_CANCEL 550
1670
1671/**
1672 * Add element to set
1673 */
1674#define GNUNET_MESSAGE_TYPE_SETU_ADD 551
1675
1676/**
1677 * Create a new local set
1678 */
1679#define GNUNET_MESSAGE_TYPE_SETU_CREATE 552
1680
1681/**
1682 * Handle result message from operation
1683 */
1684#define GNUNET_MESSAGE_TYPE_SETU_RESULT 553
1685
1686/**
1687 * Evaluate a set operation
1688 */
1689#define GNUNET_MESSAGE_TYPE_SETU_EVALUATE 554
1690
1691/**
1692 * Listen for operation requests
1693 */
1694#define GNUNET_MESSAGE_TYPE_SETU_LISTEN 555
1695
1696/**
1697 * Reject a set request.
1698 */
1699#define GNUNET_MESSAGE_TYPE_SETU_REJECT 556
1700
1701/**
1702 * Accept an incoming set request
1703 */
1704#define GNUNET_MESSAGE_TYPE_SETU_ACCEPT 557
1705
1706/**
1707 * Notify the client of an incoming request from a remote peer
1708 */
1709#define GNUNET_MESSAGE_TYPE_SETU_REQUEST 558
1710
1711
1712/**
1713 * Demand the whole element from the other
1714 * peer, given only the hash code.
1715 */
1716#define GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL 559
1717
1718/**
1719 * Demand the whole element from the other
1720 * peer, given only the hash code.
1721 */
1722#define GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND 560
1723
1724/**
1725 * Tell the other peer to send us a list of
1726 * hashes that match an IBF key.
1727 */
1728#define GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY 561
1729
1730/**
1731 * Tell the other peer which hashes match a
1732 * given IBF key.
1733 */
1734#define GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER 562
1735
1736/**
1737 * Request a set union operation from a remote peer.
1738 */
1739#define GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST 563
1740
1741/**
1742 * Strata estimator.
1743 */
1744#define GNUNET_MESSAGE_TYPE_SETU_P2P_SE 564
1745
1746/**
1747 * Invertible bloom filter.
1748 */
1749#define GNUNET_MESSAGE_TYPE_SETU_P2P_IBF 565
1750
1751/**
1752 * Actual set elements.
1753 */
1754#define GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS 566
1755
1756/**
1757 * Requests for the elements with the given hashes.
1758 */
1759#define GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS 567
1760
1761/**
1762 * Set operation is done.
1763 */
1764#define GNUNET_MESSAGE_TYPE_SETU_P2P_DONE 568
1765
1766/**
1767 * Compressed strata estimator.
1768 */
1769#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEC 569
1770
1771/**
1772 * Request all missing elements from the other peer,
1773 * based on their sets and the elements we previously sent
1774 * with #GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS.
1775 */
1776#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE 570
1777
1778/**
1779 * Send a set element, not as response to a demand but because
1780 * we're sending the full set.
1781 */
1782#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT 571
1783
1784/**
1785 * Request all missing elements from the other peer,
1786 * based on their sets and the elements we previously sent
1787 * with #GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS.
1788 */
1789#define GNUNET_MESSAGE_TYPE_SETU_P2P_OVER 572
1790
1791
1792/*******************************************************************************
1793 * SETI message types
1794 ******************************************************************************/
1795
1796
1797/**
1798 * Cancel a set operation
1799 */
1800#define GNUNET_MESSAGE_TYPE_SETI_CANCEL 580
1801
1802/**
1803 * Add element to set.
1804 */
1805#define GNUNET_MESSAGE_TYPE_SETI_ADD 581
1806
1807/**
1808 * Create a new local set
1809 */
1810#define GNUNET_MESSAGE_TYPE_SETI_CREATE 582
1811
1812/**
1813 * Handle result message from operation
1814 */
1815#define GNUNET_MESSAGE_TYPE_SETI_RESULT 583
1816
1817/**
1818 * Evaluate a set operation
1819 */
1820#define GNUNET_MESSAGE_TYPE_SETI_EVALUATE 584
1821
1822/**
1823 * Listen for operation requests
1824 */
1825#define GNUNET_MESSAGE_TYPE_SETI_LISTEN 585
1826
1827/**
1828 * Reject a set request.
1829 */
1830#define GNUNET_MESSAGE_TYPE_SETI_REJECT 586
1831
1832/**
1833 * Accept an incoming set request
1834 */
1835#define GNUNET_MESSAGE_TYPE_SETI_ACCEPT 587
1836
1837/**
1838 * Notify the client of an incoming request from a remote peer
1839 */
1840#define GNUNET_MESSAGE_TYPE_SETI_REQUEST 588
1841
1842/**
1843 * Information about the element count for intersection
1844 */
1845#define GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO 591
1846
1847/**
1848 * Bloom filter message for intersection exchange started by Bob.
1849 */
1850#define GNUNET_MESSAGE_TYPE_SETI_P2P_BF 592
1851
1852/**
1853 * Intersection operation is done.
1854 */
1855#define GNUNET_MESSAGE_TYPE_SETI_P2P_DONE 593
1856
1857/**
1858 * Request to begin set intersection operation.
1859 */
1860#define GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST 594
1861
1862
1863/*******************************************************************************
1662 * SET message types 1864 * SET message types
1663 ******************************************************************************/ 1865 ******************************************************************************/
1664 1866
1867
1665/** 1868/**
1666 * Demand the whole element from the other 1869 * Demand the whole element from the other
1667 * peer, given only the hash code. 1870 * peer, given only the hash code.
@@ -2697,17 +2900,17 @@ extern "C" {
2697 2900
2698#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE 976 2901#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE 976
2699 2902
2700#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE 977 2903#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE 977
2701 2904
2702#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE 978 2905#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE 978
2703 2906
2704#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT 979 2907#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT 979
2705 2908
2706#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START 980 2909#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START 980
2707 2910
2708#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP 981 2911#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP 981
2709 2912
2710#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT 982 2913#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT 982
2711 2914
2712 2915
2713/************************************************** 2916/**************************************************
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" {
39 39
40#include "gnunet_util_lib.h" 40#include "gnunet_util_lib.h"
41 41
42enum GNUNET_RECLAIM_AttributeType {
43 /**
44 * No value attribute.
45 */
46 GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE = 0,
42 47
43/** 48 /**
44 * No value attribute. 49 * String attribute.
45 */ 50 */
46#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE 0 51 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING = 1
52};
47 53
48/** 54enum GNUNET_RECLAIM_CredentialType {
49 * String attribute. 55 /**
50 */ 56 * No value credential.
51#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING 1 57 */
58 GNUNET_RECLAIM_CREDENTIAL_TYPE_NONE = 0,
52 59
53/** 60 /**
54* No value attestation. 61 * A JSON Web Token credential.
55*/ 62 */
56#define GNUNET_RECLAIM_ATTESTATION_TYPE_NONE 10 63 GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT = 1,
57 64
58/** 65 /**
59* A JSON Web Token attestation. 66 * libpabc credential
60*/ 67 */
61#define GNUNET_RECLAIM_ATTESTATION_TYPE_JWT 11 68 GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC = 2
69};
62 70
63/** 71/**
64 * We want an ID to be a 256-bit symmetric key 72 * We want an ID to be a 256-bit symmetric key
65 */ 73 */
66#define GNUNET_RECLAIM_ID_LENGTH (256 / 8) 74#define GNUNET_RECLAIM_ID_LENGTH (256 / 8)
67 75
76GNUNET_NETWORK_STRUCT_BEGIN
68/** 77/**
69 * A reclaim identifier 78 * A reclaim identifier
70 * FIXME maybe put this in a different namespace 79 * FIXME maybe put this in a different namespace
@@ -74,6 +83,8 @@ struct GNUNET_RECLAIM_Identifier
74 char id[GNUNET_RECLAIM_ID_LENGTH]; 83 char id[GNUNET_RECLAIM_ID_LENGTH];
75}; 84};
76 85
86GNUNET_NETWORK_STRUCT_END
87
77static const struct GNUNET_RECLAIM_Identifier GNUNET_RECLAIM_ID_ZERO; 88static const struct GNUNET_RECLAIM_Identifier GNUNET_RECLAIM_ID_ZERO;
78 89
79#define GNUNET_RECLAIM_id_is_equal(a,b) ((0 == \ 90#define GNUNET_RECLAIM_id_is_equal(a,b) ((0 == \
@@ -104,9 +115,10 @@ struct GNUNET_RECLAIM_Attribute
104 struct GNUNET_RECLAIM_Identifier id; 115 struct GNUNET_RECLAIM_Identifier id;
105 116
106 /** 117 /**
107 * Referenced ID of Attestation (may be 0 if self-attested) 118 * Referenced ID of credential
119 * (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
108 */ 120 */
109 struct GNUNET_RECLAIM_Identifier attestation; 121 struct GNUNET_RECLAIM_Identifier credential;
110 122
111 /** 123 /**
112 * Type of Claim 124 * Type of Claim
@@ -138,9 +150,9 @@ struct GNUNET_RECLAIM_Attribute
138}; 150};
139 151
140/** 152/**
141 * An attestation. 153 * A credential.
142 */ 154 */
143struct GNUNET_RECLAIM_Attestation 155struct GNUNET_RECLAIM_Credential
144{ 156{
145 /** 157 /**
146 * ID 158 * ID
@@ -158,7 +170,7 @@ struct GNUNET_RECLAIM_Attestation
158 uint32_t flag; 170 uint32_t flag;
159 171
160 /** 172 /**
161 * The name of the attribute. Note "name" must never be individually 173 * The name of the credential. Note: must never be individually
162 * free'd 174 * free'd
163 */ 175 */
164 const char *name; 176 const char *name;
@@ -169,7 +181,36 @@ struct GNUNET_RECLAIM_Attestation
169 size_t data_size; 181 size_t data_size;
170 182
171 /** 183 /**
172 * Binary value stored as attribute value. Note: "data" must never 184 * Binary value stored as credential value. Note: "data" must never
185 * be individually 'malloc'ed, but instead always points into some
186 * existing data area.
187 */
188 const void *data;
189};
190
191
192/**
193 * A credential presentation.
194 */
195struct GNUNET_RECLAIM_Presentation
196{
197 /**
198 * The credential id of which this is a presentation.
199 */
200 struct GNUNET_RECLAIM_Identifier credential_id;
201
202 /**
203 * Type/Format of Claim
204 */
205 uint32_t type;
206
207 /**
208 * Number of bytes in @e data.
209 */
210 size_t data_size;
211
212 /**
213 * Binary value stored as presentation value. Note: "data" must never
173 * be individually 'malloc'ed, but instead always points into some 214 * be individually 'malloc'ed, but instead always points into some
174 * existing data area. 215 * existing data area.
175 */ 216 */
@@ -177,6 +218,7 @@ struct GNUNET_RECLAIM_Attestation
177}; 218};
178 219
179 220
221
180/** 222/**
181 * A list of GNUNET_RECLAIM_Attribute structures. 223 * A list of GNUNET_RECLAIM_Attribute structures.
182 */ 224 */
@@ -214,56 +256,94 @@ struct GNUNET_RECLAIM_AttributeListEntry
214}; 256};
215 257
216/** 258/**
217 * A list of GNUNET_RECLAIM_Attestation structures. 259 * A list of GNUNET_RECLAIM_Credential structures.
260 */
261struct GNUNET_RECLAIM_CredentialList
262{
263 /**
264 * List head
265 */
266 struct GNUNET_RECLAIM_CredentialListEntry *list_head;
267
268 /**
269 * List tail
270 */
271 struct GNUNET_RECLAIM_CredentialListEntry *list_tail;
272};
273
274
275struct GNUNET_RECLAIM_CredentialListEntry
276{
277 /**
278 * DLL
279 */
280 struct GNUNET_RECLAIM_CredentialListEntry *prev;
281
282 /**
283 * DLL
284 */
285 struct GNUNET_RECLAIM_CredentialListEntry *next;
286
287 /**
288 * The credential
289 */
290 struct GNUNET_RECLAIM_Credential *credential;
291
292};
293
294
295/**
296 * A list of GNUNET_RECLAIM_Presentation structures.
218 */ 297 */
219struct GNUNET_RECLAIM_AttestationList 298struct GNUNET_RECLAIM_PresentationList
220{ 299{
221 /** 300 /**
222 * List head 301 * List head
223 */ 302 */
224 struct GNUNET_RECLAIM_AttestationListEntry *list_head; 303 struct GNUNET_RECLAIM_PresentationListEntry *list_head;
225 304
226 /** 305 /**
227 * List tail 306 * List tail
228 */ 307 */
229 struct GNUNET_RECLAIM_AttestationListEntry *list_tail; 308 struct GNUNET_RECLAIM_PresentationListEntry *list_tail;
230}; 309};
231 310
232 311
233struct GNUNET_RECLAIM_AttestationListEntry 312struct GNUNET_RECLAIM_PresentationListEntry
234{ 313{
235 /** 314 /**
236 * DLL 315 * DLL
237 */ 316 */
238 struct GNUNET_RECLAIM_AttestationListEntry *prev; 317 struct GNUNET_RECLAIM_PresentationListEntry *prev;
239 318
240 /** 319 /**
241 * DLL 320 * DLL
242 */ 321 */
243 struct GNUNET_RECLAIM_AttestationListEntry *next; 322 struct GNUNET_RECLAIM_PresentationListEntry *next;
244 323
245 /** 324 /**
246 * The attestation 325 * The credential
247 */ 326 */
248 struct GNUNET_RECLAIM_Attestation *attestation; 327 struct GNUNET_RECLAIM_Presentation *presentation;
249 328
250}; 329};
251 330
252 331
332
253/** 333/**
254 * Create a new attribute claim. 334 * Create a new attribute claim.
255 * 335 *
256 * @param attr_name the attribute name 336 * @param attr_name the attribute name
257 * @param attestation ID of the attestation (may be NULL) 337 * @param credential ID of the credential (may be NULL)
258 * @param type the attribute type 338 * @param type the attribute type
259 * @param data the attribute value. Must be the mapped name if attestation not NULL 339 * @param data the attribute value. Must be #attr_name if credential not NULL
260 * @param data_size the attribute value size 340 * @param data_size the attribute value size
261 * @return the new attribute 341 * @return the new attribute
262 */ 342 */
263struct GNUNET_RECLAIM_Attribute * 343struct GNUNET_RECLAIM_Attribute *
264GNUNET_RECLAIM_attribute_new (const char *attr_name, 344GNUNET_RECLAIM_attribute_new (const char *attr_name,
265 const struct 345 const struct
266 GNUNET_RECLAIM_Identifier *attestation, 346 GNUNET_RECLAIM_Identifier *credential,
267 uint32_t type, 347 uint32_t type,
268 const void *data, 348 const void *data,
269 size_t data_size); 349 size_t data_size);
@@ -295,7 +375,7 @@ GNUNET_RECLAIM_attribute_list_destroy (
295 * 375 *
296 * @param attrs the attribute list to add to 376 * @param attrs the attribute list to add to
297 * @param attr_name the name of the new attribute claim 377 * @param attr_name the name of the new attribute claim
298 * @param attestation attestation ID (may be NULL) 378 * @param credential credential ID (may be NULL)
299 * @param type the type of the claim 379 * @param type the type of the claim
300 * @param data claim payload 380 * @param data claim payload
301 * @param data_size claim payload size 381 * @param data_size claim payload size
@@ -304,7 +384,7 @@ void
304GNUNET_RECLAIM_attribute_list_add ( 384GNUNET_RECLAIM_attribute_list_add (
305 struct GNUNET_RECLAIM_AttributeList *attrs, 385 struct GNUNET_RECLAIM_AttributeList *attrs,
306 const char *attr_name, 386 const char *attr_name,
307 const struct GNUNET_RECLAIM_Identifier *attestation, 387 const struct GNUNET_RECLAIM_Identifier *credential,
308 uint32_t type, 388 uint32_t type,
309 const void *data, 389 const void *data,
310 size_t data_size); 390 size_t data_size);
@@ -361,11 +441,13 @@ GNUNET_RECLAIM_attribute_serialize (const struct GNUNET_RECLAIM_Attribute *attr,
361 * 441 *
362 * @param data the serialized attribute 442 * @param data the serialized attribute
363 * @param data_size the length of the serialized data 443 * @param data_size the length of the serialized data
444 * @param attr deserialized attribute. Will be allocated. Must be free'd
364 * 445 *
365 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller 446 * @return number of bytes read or -1 for error
366 */ 447 */
367struct GNUNET_RECLAIM_Attribute * 448ssize_t
368GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size); 449GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
450 struct GNUNET_RECLAIM_Attribute **attr);
369 451
370 452
371/** 453/**
@@ -434,8 +516,8 @@ GNUNET_RECLAIM_attribute_number_to_typename (uint32_t type);
434 * @return the required buffer size 516 * @return the required buffer size
435 */ 517 */
436size_t 518size_t
437GNUNET_RECLAIM_attestation_list_serialize_get_size ( 519GNUNET_RECLAIM_credential_list_serialize_get_size (
438 const struct GNUNET_RECLAIM_AttestationList *attestations); 520 const struct GNUNET_RECLAIM_CredentialList *credentials);
439 521
440 522
441/** 523/**
@@ -444,8 +526,8 @@ GNUNET_RECLAIM_attestation_list_serialize_get_size (
444 * @param attrs list to destroy 526 * @param attrs list to destroy
445 */ 527 */
446void 528void
447GNUNET_RECLAIM_attestation_list_destroy ( 529GNUNET_RECLAIM_credential_list_destroy (
448 struct GNUNET_RECLAIM_AttestationList *attestations); 530 struct GNUNET_RECLAIM_CredentialList *credentials);
449 531
450 532
451/** 533/**
@@ -457,8 +539,8 @@ GNUNET_RECLAIM_attestation_list_destroy (
457 * @param data_size claim payload size 539 * @param data_size claim payload size
458 */ 540 */
459void 541void
460GNUNET_RECLAIM_attestation_list_add ( 542GNUNET_RECLAIM_credential_list_add (
461 struct GNUNET_RECLAIM_AttestationList *attrs, 543 struct GNUNET_RECLAIM_CredentialList *attrs,
462 const char *att_name, 544 const char *att_name,
463 uint32_t type, 545 uint32_t type,
464 const void *data, 546 const void *data,
@@ -473,8 +555,8 @@ GNUNET_RECLAIM_attestation_list_add (
473 * @return length of serialized data 555 * @return length of serialized data
474 */ 556 */
475size_t 557size_t
476GNUNET_RECLAIM_attestation_list_serialize ( 558GNUNET_RECLAIM_credential_list_serialize (
477 const struct GNUNET_RECLAIM_AttestationList *attrs, 559 const struct GNUNET_RECLAIM_CredentialList *attrs,
478 char *result); 560 char *result);
479 561
480 562
@@ -485,75 +567,75 @@ GNUNET_RECLAIM_attestation_list_serialize (
485 * @param data_size the length of the serialized data 567 * @param data_size the length of the serialized data
486 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller 568 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
487 */ 569 */
488struct GNUNET_RECLAIM_AttestationList * 570struct GNUNET_RECLAIM_CredentialList *
489GNUNET_RECLAIM_attestation_list_deserialize (const char *data, 571GNUNET_RECLAIM_credential_list_deserialize (const char *data,
490 size_t data_size); 572 size_t data_size);
491 573
492 574
493/** 575/**
494 * @param attestation the attestation to serialize 576 * @param credential the credential to serialize
495 * @return the required buffer size 577 * @return the required buffer size
496 */ 578 */
497size_t 579size_t
498GNUNET_RECLAIM_attestation_serialize_get_size ( 580GNUNET_RECLAIM_credential_serialize_get_size (
499 const struct GNUNET_RECLAIM_Attestation *attestation); 581 const struct GNUNET_RECLAIM_Credential *credential);
500 582
501 583
502/** 584/**
503 * Serialize an attestation 585 * Serialize an credential
504 * 586 *
505 * @param attestation the attestation to serialize 587 * @param credential the credential to serialize
506 * @param result the serialized attestation 588 * @param result the serialized credential
507 * @return length of serialized data 589 * @return length of serialized data
508 */ 590 */
509size_t 591size_t
510GNUNET_RECLAIM_attestation_serialize ( 592GNUNET_RECLAIM_credential_serialize (
511 const struct GNUNET_RECLAIM_Attestation *attestation, 593 const struct GNUNET_RECLAIM_Credential *credential,
512 char *result); 594 char *result);
513 595
514 596
515/** 597/**
516 * Deserialize an attestation 598 * Deserialize an credential
517 * 599 *
518 * @param data the serialized attestation 600 * @param data the serialized credential
519 * @param data_size the length of the serialized data 601 * @param data_size the length of the serialized data
520 * 602 *
521 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller 603 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
522 */ 604 */
523struct GNUNET_RECLAIM_Attestation * 605struct GNUNET_RECLAIM_Credential *
524GNUNET_RECLAIM_attestation_deserialize (const char *data, size_t data_size); 606GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size);
525 607
526 608
527/** 609/**
528 * Create a new attestation. 610 * Create a new credential.
529 * 611 *
530 * @param name the attestation name 612 * @param name the credential name
531 * @param type the attestation type 613 * @param type the credential type
532 * @param data the attestation value 614 * @param data the credential value
533 * @param data_size the attestation value size 615 * @param data_size the credential value size
534 * @return the new attestation 616 * @return the new credential
535 */ 617 */
536struct GNUNET_RECLAIM_Attestation * 618struct GNUNET_RECLAIM_Credential *
537GNUNET_RECLAIM_attestation_new (const char *name, 619GNUNET_RECLAIM_credential_new (const char *name,
538 uint32_t type, 620 uint32_t type,
539 const void *data, 621 const void *data,
540 size_t data_size); 622 size_t data_size);
541 623
542/** 624/**
543 * Convert the 'claim' of an attestation to a string 625 * Convert the 'claim' of an credential to a string
544 * 626 *
545 * @param type the type of attestation 627 * @param type the type of credential
546 * @param data claim in binary encoding 628 * @param data claim in binary encoding
547 * @param data_size number of bytes in @a data 629 * @param data_size number of bytes in @a data
548 * @return NULL on error, otherwise human-readable representation of the claim 630 * @return NULL on error, otherwise human-readable representation of the claim
549 */ 631 */
550char * 632char *
551GNUNET_RECLAIM_attestation_value_to_string (uint32_t type, 633GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
552 const void *data, 634 const void *data,
553 size_t data_size); 635 size_t data_size);
554 636
555/** 637/**
556 * Convert human-readable version of a 'claim' of an attestation to the binary 638 * Convert human-readable version of a 'claim' of an credential to the binary
557 * representation 639 * representation
558 * 640 *
559 * @param type type of the claim 641 * @param type type of the claim
@@ -563,48 +645,206 @@ GNUNET_RECLAIM_attestation_value_to_string (uint32_t type,
563 * @return #GNUNET_OK on success 645 * @return #GNUNET_OK on success
564 */ 646 */
565int 647int
566GNUNET_RECLAIM_attestation_string_to_value (uint32_t type, 648GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
567 const char *s, 649 const char *s,
568 void **data, 650 void **data,
569 size_t *data_size); 651 size_t *data_size);
570 652
571/** 653/**
572 * Convert an attestation type number to the corresponding attestation type string 654 * Convert an credential type number to the corresponding credential type string
573 * 655 *
574 * @param type number of a type 656 * @param type number of a type
575 * @return corresponding typestring, NULL on error 657 * @return corresponding typestring, NULL on error
576 */ 658 */
577const char * 659const char *
578GNUNET_RECLAIM_attestation_number_to_typename (uint32_t type); 660GNUNET_RECLAIM_credential_number_to_typename (uint32_t type);
579 661
580/** 662/**
581 * Convert an attestation type name to the corresponding number 663 * Convert an credential type name to the corresponding number
582 * 664 *
583 * @param typename name to convert 665 * @param typename name to convert
584 * @return corresponding number, UINT32_MAX on error 666 * @return corresponding number, UINT32_MAX on error
585 */ 667 */
586uint32_t 668uint32_t
587GNUNET_RECLAIM_attestation_typename_to_number (const char *typename); 669GNUNET_RECLAIM_credential_typename_to_number (const char *typename);
588 670
589/** 671/**
590 * Convert an attestation type name to the corresponding number 672 * Convert an credential type name to the corresponding number
591 * 673 *
592 * @param typename name to convert 674 * @param typename name to convert
593 * @return corresponding number, UINT32_MAX on error 675 * @return corresponding number, UINT32_MAX on error
594 */ 676 */
595struct GNUNET_RECLAIM_AttributeList* 677struct GNUNET_RECLAIM_AttributeList*
596GNUNET_RECLAIM_attestation_get_attributes (const struct 678GNUNET_RECLAIM_credential_get_attributes (const struct
597 GNUNET_RECLAIM_Attestation *attest); 679 GNUNET_RECLAIM_Credential *cred);
680
681char*
682GNUNET_RECLAIM_credential_get_issuer (const struct
683 GNUNET_RECLAIM_Credential *cred);
684
685int
686GNUNET_RECLAIM_credential_get_expiration (const struct
687 GNUNET_RECLAIM_Credential *cred,
688 struct GNUNET_TIME_Absolute *exp);
689
690/**
691 * Get required size for serialization buffer
692 *
693 * @param presentations the presentation list to serialize
694 * @return the required buffer size
695 */
696size_t
697GNUNET_RECLAIM_presentation_list_serialize_get_size (
698 const struct GNUNET_RECLAIM_PresentationList *presentations);
699
700
701/**
702 * Destroy presentations list
703 *
704 * @param presentations list to destroy
705 */
706void
707GNUNET_RECLAIM_presentation_list_destroy (
708 struct GNUNET_RECLAIM_PresentationList *presentations);
709
710
711/**
712 * Serialize a presentation list
713 *
714 * @param presentations the attribute list to serialize
715 * @param result the serialized list
716 * @return length of serialized data
717 */
718size_t
719GNUNET_RECLAIM_presentation_list_serialize (
720 const struct GNUNET_RECLAIM_PresentationList *presentations,
721 char *result);
722
723
724/**
725 * Deserialize a presentation list
726 *
727 * @param data the serialized list
728 * @param data_size the length of the serialized data
729 * @return a GNUNET_RECLAIM_PresentationList, must be free'd by caller
730 */
731struct GNUNET_RECLAIM_PresentationList *
732GNUNET_RECLAIM_presentation_list_deserialize (const char *data,
733 size_t data_size);
734
735
736/**
737 * @param presentation the presentation to serialize
738 * @return the required buffer size
739 */
740size_t
741GNUNET_RECLAIM_presentation_serialize_get_size (
742 const struct GNUNET_RECLAIM_Presentation *presentation);
743
744
745/**
746 * Serialize a presentation.
747 *
748 * @param presentation the presentation to serialize
749 * @param result the serialized presentation
750 * @return length of serialized data
751 */
752size_t
753GNUNET_RECLAIM_presentation_serialize (
754 const struct GNUNET_RECLAIM_Presentation *presentation,
755 char *result);
756
757
758/**
759 * Deserialize a presentation
760 *
761 * @param data the serialized presentation
762 * @param data_size the length of the serialized data
763 *
764 * @return a GNUNET_RECLAIM_Presentation, must be free'd by caller
765 */
766struct GNUNET_RECLAIM_Presentation *
767GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size);
768
769
770/**
771 * Convert the 'claim' of a presentation to a string
772 *
773 * @param type the type of presentation
774 * @param data presentation in binary encoding
775 * @param data_size number of bytes in @a data
776 * @return NULL on error, otherwise human-readable representation of the claim
777 */
778char *
779GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
780 const void *data,
781 size_t data_size);
782
783struct GNUNET_RECLAIM_Presentation *
784GNUNET_RECLAIM_presentation_new (uint32_t type,
785 const void *data,
786 size_t data_size);
787
788/**
789 * Convert human-readable version of a 'claim' of a presentation to the binary
790 * representation
791 *
792 * @param type type of the presentation
793 * @param s human-readable string
794 * @param data set to value in binary encoding (will be allocated)
795 * @param data_size set to number of bytes in @a data
796 * @return #GNUNET_OK on success
797 */
798int
799GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
800 const char *s,
801 void **data,
802 size_t *data_size);
803
804/**
805 * Convert a presentation type number to the corresponding credential type
806 * string.
807 *
808 * @param type number of a type
809 * @return corresponding typestring, NULL on error
810 */
811const char *
812GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type);
813
814struct GNUNET_RECLAIM_AttributeList*
815GNUNET_RECLAIM_presentation_get_attributes (const struct
816 GNUNET_RECLAIM_Presentation *cred);
598 817
599char* 818char*
600GNUNET_RECLAIM_attestation_get_issuer (const struct 819GNUNET_RECLAIM_presentation_get_issuer (const struct
601 GNUNET_RECLAIM_Attestation *attest); 820 GNUNET_RECLAIM_Presentation *cred);
602 821
603int 822int
604GNUNET_RECLAIM_attestation_get_expiration (const struct 823GNUNET_RECLAIM_presentation_get_expiration (const struct
605 GNUNET_RECLAIM_Attestation *attest, 824 GNUNET_RECLAIM_Presentation *cred,
606 struct GNUNET_TIME_Absolute *exp); 825 struct GNUNET_TIME_Absolute *exp);
607 826
827
828
829/**
830 * Create a presentation from a credential and a lift of (selected)
831 * attributes in the credential.
832 * FIXME not yet implemented
833 *
834 * @param cred the credential to use
835 * @param attrs the attributes to present from the credential
836 * @param presentation the credential presentation presenting the attributes according
837 * to the presentation mechanism of the credential
838 * or NULL on error.
839 * @return GNUNET_OK on success.
840 */
841int
842GNUNET_RECLAIM_credential_get_presentation (
843 const struct GNUNET_RECLAIM_Credential *cred,
844 const struct GNUNET_RECLAIM_AttributeList *attrs,
845 struct GNUNET_RECLAIM_Presentation **presentation);
846
847
608#if 0 /* keep Emacsens' auto-indent happy */ 848#if 0 /* keep Emacsens' auto-indent happy */
609{ 849{
610#endif 850#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 @@
27 * @defgroup reclaim-attribute-plugin reclaim plugin API for attributes/claims 27 * @defgroup reclaim-attribute-plugin reclaim plugin API for attributes/claims
28 * @{ 28 * @{
29 */ 29 */
30#ifndef GNUNET_RECLAIM_AttributePLUGIN_H 30#ifndef GNUNET_RECLAIM_PLUGIN_H
31#define GNUNET_RECLAIM_AttributePLUGIN_H 31#define GNUNET_RECLAIM_PLUGIN_H
32 32
33#include "gnunet_util_lib.h" 33#include "gnunet_util_lib.h"
34#include "gnunet_reclaim_lib.h" 34#include "gnunet_reclaim_lib.h"
@@ -113,7 +113,7 @@ typedef const char *(*GNUNET_RECLAIM_AttributeNumberToTypenameFunction) (
113 * @param data_size number of bytes in @a data 113 * @param data_size number of bytes in @a data
114 * @return NULL on error, otherwise human-readable representation of the value 114 * @return NULL on error, otherwise human-readable representation of the value
115 */ 115 */
116typedef char *(*GNUNET_RECLAIM_AttestationValueToStringFunction) ( 116typedef char *(*GNUNET_RECLAIM_CredentialValueToStringFunction) (
117 void *cls, 117 void *cls,
118 uint32_t type, 118 uint32_t type,
119 const void *data, 119 const void *data,
@@ -132,7 +132,7 @@ typedef char *(*GNUNET_RECLAIM_AttestationValueToStringFunction) (
132 * @param data_size set to number of bytes in @a data 132 * @param data_size set to number of bytes in @a data
133 * @return #GNUNET_OK on success 133 * @return #GNUNET_OK on success
134 */ 134 */
135typedef int (*GNUNET_RECLAIM_AttestationStringToValueFunction) ( 135typedef int (*GNUNET_RECLAIM_CredentialStringToValueFunction) (
136 void *cls, 136 void *cls,
137 uint32_t type, 137 uint32_t type,
138 const char *s, 138 const char *s,
@@ -148,7 +148,7 @@ typedef int (*GNUNET_RECLAIM_AttestationStringToValueFunction) (
148 * @param typename name to convert 148 * @param typename name to convert
149 * @return corresponding number, UINT32_MAX on error 149 * @return corresponding number, UINT32_MAX on error
150 */ 150 */
151typedef uint32_t (*GNUNET_RECLAIM_AttestationTypenameToNumberFunction) ( 151typedef uint32_t (*GNUNET_RECLAIM_CredentialTypenameToNumberFunction) (
152 void *cls, 152 void *cls,
153 const char *typename); 153 const char *typename);
154 154
@@ -161,47 +161,151 @@ typedef uint32_t (*GNUNET_RECLAIM_AttestationTypenameToNumberFunction) (
161 * @param type number of a type to convert 161 * @param type number of a type to convert
162 * @return corresponding typestring, NULL on error 162 * @return corresponding typestring, NULL on error
163 */ 163 */
164typedef const char *(*GNUNET_RECLAIM_AttestationNumberToTypenameFunction) ( 164typedef const char *(*GNUNET_RECLAIM_CredentialNumberToTypenameFunction) (
165 void *cls, 165 void *cls,
166 uint32_t type); 166 uint32_t type);
167 167
168/** 168/**
169 * Function called to extract attributes from an attestation 169 * Function called to extract attributes from a credential
170 * 170 *
171 * @param cls closure 171 * @param cls closure
172 * @param attest the attestation object 172 * @param cred the credential object
173 * @return an attribute list 173 * @return an attribute list
174 */ 174 */
175typedef struct 175typedef struct
176 GNUNET_RECLAIM_AttributeList *(* 176 GNUNET_RECLAIM_AttributeList *(*
177GNUNET_RECLAIM_AttestationGetAttributesFunction) ( 177GNUNET_RECLAIM_CredentialGetAttributesFunction) (
178 void *cls, 178 void *cls,
179 const struct GNUNET_RECLAIM_Attestation *attest); 179 const struct GNUNET_RECLAIM_Credential *cred);
180 180
181/** 181/**
182 * Function called to get the issuer of the attestation (as string) 182 * Function called to get the issuer of the credential (as string)
183 * 183 *
184 * @param cls closure 184 * @param cls closure
185 * @param attest the attestation object 185 * @param cred the credential object
186 * @return corresponding issuer string 186 * @return corresponding issuer string
187 */ 187 */
188typedef char *(*GNUNET_RECLAIM_AttestationGetIssuerFunction) ( 188typedef char *(*GNUNET_RECLAIM_CredentialGetIssuerFunction) (
189 void *cls, 189 void *cls,
190 const struct GNUNET_RECLAIM_Attestation *attest); 190 const struct GNUNET_RECLAIM_Credential *cred);
191 191
192/** 192/**
193 * Function called to get the expiration of the attestation 193 * Function called to get the expiration of the credential
194 * 194 *
195 * @param cls closure 195 * @param cls closure
196 * @param attest the attestation object 196 * @param cred the credential object
197 * @param where to write the value 197 * @param where to write the value
198 * @return GNUNET_OK if successful 198 * @return GNUNET_OK if successful
199 */ 199 */
200typedef int (*GNUNET_RECLAIM_AttestationGetExpirationFunction) ( 200typedef int (*GNUNET_RECLAIM_CredentialGetExpirationFunction) (
201 void *cls, 201 void *cls,
202 const struct GNUNET_RECLAIM_Attestation *attest, 202 const struct GNUNET_RECLAIM_Credential *cred,
203 struct GNUNET_TIME_Absolute *expiration); 203 struct GNUNET_TIME_Absolute *expiration);
204 204
205/**
206 * Function called to convert the binary value @a data of an attribute of
207 * type @a type to a human-readable string.
208 *
209 * @param cls closure
210 * @param type type of the attribute
211 * @param data value in binary encoding
212 * @param data_size number of bytes in @a data
213 * @return NULL on error, otherwise human-readable representation of the value
214 */
215typedef char *(*GNUNET_RECLAIM_PresentationValueToStringFunction) (
216 void *cls,
217 uint32_t type,
218 const void *data,
219 size_t data_size);
220
221
222/**
223 * Function called to convert human-readable version of the value @a s
224 * of an attribute of type @a type to the respective binary
225 * representation.
226 *
227 * @param cls closure
228 * @param type type of the attribute
229 * @param s human-readable string
230 * @param data set to value in binary encoding (will be allocated)
231 * @param data_size set to number of bytes in @a data
232 * @return #GNUNET_OK on success
233 */
234typedef int (*GNUNET_RECLAIM_PresentationStringToValueFunction) (
235 void *cls,
236 uint32_t type,
237 const char *s,
238 void **data,
239 size_t *data_size);
240
241
242/**
243 * Function called to convert a type name to the
244 * corresponding number.
245 *
246 * @param cls closure
247 * @param typename name to convert
248 * @return corresponding number, UINT32_MAX on error
249 */
250typedef uint32_t (*GNUNET_RECLAIM_PresentationTypenameToNumberFunction) (
251 void *cls,
252 const char *typename);
253
254
255/**
256 * Function called to convert a type number (i.e. 1) to the
257 * corresponding type string
258 *
259 * @param cls closure
260 * @param type number of a type to convert
261 * @return corresponding typestring, NULL on error
262 */
263typedef const char *(*GNUNET_RECLAIM_PresentationNumberToTypenameFunction) (
264 void *cls,
265 uint32_t type);
266
267/**
268 * Function called to extract attributes from a credential
269 *
270 * @param cls closure
271 * @param cred the credential object
272 * @return an attribute list
273 */
274typedef struct
275 GNUNET_RECLAIM_AttributeList *(*
276GNUNET_RECLAIM_PresentationGetAttributesFunction) (
277 void *cls,
278 const struct GNUNET_RECLAIM_Presentation *cred);
279
280/**
281 * Function called to get the issuer of the credential (as string)
282 *
283 * @param cls closure
284 * @param cred the credential object
285 * @return corresponding issuer string
286 */
287typedef char *(*GNUNET_RECLAIM_PresentationGetIssuerFunction) (
288 void *cls,
289 const struct GNUNET_RECLAIM_Presentation *cred);
290
291/**
292 * Function called to get the expiration of the credential
293 *
294 * @param cls closure
295 * @param cred the credential object
296 * @param where to write the value
297 * @return GNUNET_OK if successful
298 */
299typedef int (*GNUNET_RECLAIM_PresentationGetExpirationFunction) (
300 void *cls,
301 const struct GNUNET_RECLAIM_Presentation *cred,
302 struct GNUNET_TIME_Absolute *expiration);
303
304typedef int (*GNUNET_RECLAIM_CredentialToPresentation) (
305 void *cls,
306 const struct GNUNET_RECLAIM_Credential *cred,
307 const struct GNUNET_RECLAIM_AttributeList *attrs,
308 struct GNUNET_RECLAIM_Presentation **presentation);
205 309
206/** 310/**
207 * Each plugin is required to return a pointer to a struct of this 311 * Each plugin is required to return a pointer to a struct of this
@@ -240,7 +344,7 @@ struct GNUNET_RECLAIM_AttributePluginFunctions
240 * Each plugin is required to return a pointer to a struct of this 344 * Each plugin is required to return a pointer to a struct of this
241 * type as the return value from its entry point. 345 * type as the return value from its entry point.
242 */ 346 */
243struct GNUNET_RECLAIM_AttestationPluginFunctions 347struct GNUNET_RECLAIM_CredentialPluginFunctions
244{ 348{
245 /** 349 /**
246 * Closure for all of the callbacks. 350 * Closure for all of the callbacks.
@@ -250,37 +354,78 @@ struct GNUNET_RECLAIM_AttestationPluginFunctions
250 /** 354 /**
251 * Conversion to string. 355 * Conversion to string.
252 */ 356 */
253 GNUNET_RECLAIM_AttestationValueToStringFunction value_to_string; 357 GNUNET_RECLAIM_CredentialValueToStringFunction value_to_string;
358
359 /**
360 * Conversion to binary.
361 */
362 GNUNET_RECLAIM_CredentialStringToValueFunction string_to_value;
363
364 /**
365 * Typename to number.
366 */
367 GNUNET_RECLAIM_CredentialTypenameToNumberFunction typename_to_number;
368
369 /**
370 * Number to typename.
371 */
372 GNUNET_RECLAIM_CredentialNumberToTypenameFunction number_to_typename;
373
374 /**
375 * Attesation attributes.
376 */
377 GNUNET_RECLAIM_CredentialGetAttributesFunction get_attributes;
378
379 /**
380 * Attesation issuer.
381 */
382 GNUNET_RECLAIM_CredentialGetIssuerFunction get_issuer;
383
384 /**
385 * Expiration.
386 */
387 GNUNET_RECLAIM_CredentialGetExpirationFunction get_expiration;
388
389 /**
390 * Conversion to string.
391 */
392 GNUNET_RECLAIM_PresentationValueToStringFunction value_to_string_p;
254 393
255 /** 394 /**
256 * Conversion to binary. 395 * Conversion to binary.
257 */ 396 */
258 GNUNET_RECLAIM_AttestationStringToValueFunction string_to_value; 397 GNUNET_RECLAIM_PresentationStringToValueFunction string_to_value_p;
259 398
260 /** 399 /**
261 * Typename to number. 400 * Typename to number.
262 */ 401 */
263 GNUNET_RECLAIM_AttestationTypenameToNumberFunction typename_to_number; 402 GNUNET_RECLAIM_PresentationTypenameToNumberFunction typename_to_number_p;
264 403
265 /** 404 /**
266 * Number to typename. 405 * Number to typename.
267 */ 406 */
268 GNUNET_RECLAIM_AttestationNumberToTypenameFunction number_to_typename; 407 GNUNET_RECLAIM_PresentationNumberToTypenameFunction number_to_typename_p;
269 408
270 /** 409 /**
271 * Attesation attributes. 410 * Attesation attributes.
272 */ 411 */
273 GNUNET_RECLAIM_AttestationGetAttributesFunction get_attributes; 412 GNUNET_RECLAIM_PresentationGetAttributesFunction get_attributes_p;
274 413
275 /** 414 /**
276 * Attesation issuer. 415 * Attesation issuer.
277 */ 416 */
278 GNUNET_RECLAIM_AttestationGetIssuerFunction get_issuer; 417 GNUNET_RECLAIM_PresentationGetIssuerFunction get_issuer_p;
279 418
280 /** 419 /**
281 * Expiration. 420 * Expiration.
282 */ 421 */
283 GNUNET_RECLAIM_AttestationGetExpirationFunction get_expiration; 422 GNUNET_RECLAIM_PresentationGetExpirationFunction get_expiration_p;
423
424 /**
425 * Get presentation
426 */
427 GNUNET_RECLAIM_CredentialToPresentation create_presentation;
428
284}; 429};
285 430
286 431
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
92 * @param ticket the ticket 92 * @param ticket the ticket
93 */ 93 */
94typedef void (*GNUNET_RECLAIM_TicketCallback) ( 94typedef void (*GNUNET_RECLAIM_TicketCallback) (
95 void *cls, const struct GNUNET_RECLAIM_Ticket *ticket); 95 void *cls,
96 const struct GNUNET_RECLAIM_Ticket *ticket);
97
98/**
99 * Method called when a token has been issued.
100 * On success returns a ticket that can be given to a relying party
101 * in order for it retrive identity attributes
102 *
103 * @param cls closure
104 * @param ticket the ticket
105 */
106typedef void (*GNUNET_RECLAIM_IssueTicketCallback) (
107 void *cls,
108 const struct GNUNET_RECLAIM_Ticket *ticket,
109 const struct GNUNET_RECLAIM_PresentationList *presentations);
96 110
97 111
98/** 112/**
@@ -113,7 +127,6 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls,
113 * @param cls The callback closure 127 * @param cls The callback closure
114 * @param identity The identity authoritative over the attributes 128 * @param identity The identity authoritative over the attributes
115 * @param attr The attribute 129 * @param attr The attribute
116 * @param attestation The attestation for the attribute (may be NULL)
117 */ 130 */
118typedef void (*GNUNET_RECLAIM_AttributeResult) ( 131typedef void (*GNUNET_RECLAIM_AttributeResult) (
119 void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 132 void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
@@ -125,25 +138,25 @@ typedef void (*GNUNET_RECLAIM_AttributeResult) (
125 * @param cls The callback closure 138 * @param cls The callback closure
126 * @param identity The identity authoritative over the attributes 139 * @param identity The identity authoritative over the attributes
127 * @param attr The attribute 140 * @param attr The attribute
128 * @param attestation The attestation for the attribute (may be NULL) 141 * @param presentation The presentation for the credential (may be NULL)
129 */ 142 */
130typedef void (*GNUNET_RECLAIM_AttributeTicketResult) ( 143typedef void (*GNUNET_RECLAIM_AttributeTicketResult) (
131 void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 144 void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
132 const struct GNUNET_RECLAIM_Attribute *attr, 145 const struct GNUNET_RECLAIM_Attribute *attr,
133 const struct GNUNET_RECLAIM_Attestation *attestation); 146 const struct GNUNET_RECLAIM_Presentation *presentation);
134 147
135 148
136/** 149/**
137 * Callback used to notify the client of attestation results. 150 * Callback used to notify the client of credential results.
138 * 151 *
139 * @param cls The callback closure 152 * @param cls The callback closure
140 * @param identity The identity authoritative over the attributes 153 * @param identity The identity authoritative over the attributes
141 * @param attestation The attestation 154 * @param credential The credential
142 * @param attributes the parsed attributes 155 * @param attributes the parsed attributes
143 */ 156 */
144typedef void (*GNUNET_RECLAIM_AttestationResult) ( 157typedef void (*GNUNET_RECLAIM_CredentialResult) (
145 void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 158 void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
146 const struct GNUNET_RECLAIM_Attestation *attestation); 159 const struct GNUNET_RECLAIM_Credential *credential);
147 160
148 161
149/** 162/**
@@ -178,22 +191,22 @@ GNUNET_RECLAIM_attribute_store (
178 191
179 192
180/** 193/**
181 * Store an attestation. If the attestation is already present, 194 * Store a credential. If the credential is already present,
182 * it is replaced with the new attestation. 195 * it is replaced with the new credential.
183 * 196 *
184 * @param h handle to the re:claimID service 197 * @param h handle to the re:claimID service
185 * @param pkey private key of the identity 198 * @param pkey private key of the identity
186 * @param attr the attestation value 199 * @param attr the credential value
187 * @param exp_interval the relative expiration interval for the attestation 200 * @param exp_interval the relative expiration interval for the credential
188 * @param cont continuation to call when done 201 * @param cont continuation to call when done
189 * @param cont_cls closure for @a cont 202 * @param cont_cls closure for @a cont
190 * @return handle to abort the request 203 * @return handle to abort the request
191 */ 204 */
192struct GNUNET_RECLAIM_Operation * 205struct GNUNET_RECLAIM_Operation *
193GNUNET_RECLAIM_attestation_store ( 206GNUNET_RECLAIM_credential_store (
194 struct GNUNET_RECLAIM_Handle *h, 207 struct GNUNET_RECLAIM_Handle *h,
195 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, 208 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
196 const struct GNUNET_RECLAIM_Attestation *attestation, 209 const struct GNUNET_RECLAIM_Credential *credential,
197 const struct GNUNET_TIME_Relative *exp_interval, 210 const struct GNUNET_TIME_Relative *exp_interval,
198 GNUNET_RECLAIM_ContinuationWithStatus cont, 211 GNUNET_RECLAIM_ContinuationWithStatus cont,
199 void *cont_cls); 212 void *cont_cls);
@@ -218,21 +231,21 @@ GNUNET_RECLAIM_attribute_delete (
218 GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls); 231 GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls);
219 232
220/** 233/**
221 * Delete an attestation. Tickets used to share this attestation are updated 234 * Delete a credential. Tickets used to share use a presentation of this
222 * accordingly. 235 * credential are updated accordingly.
223 * 236 *
224 * @param h handle to the re:claimID service 237 * @param h handle to the re:claimID service
225 * @param pkey Private key of the identity to add an attribute to 238 * @param pkey Private key of the identity to add an attribute to
226 * @param attr The attestation 239 * @param cred The credential
227 * @param cont Continuation to call when done 240 * @param cont Continuation to call when done
228 * @param cont_cls Closure for @a cont 241 * @param cont_cls Closure for @a cont
229 * @return handle Used to to abort the request 242 * @return handle Used to to abort the request
230 */ 243 */
231struct GNUNET_RECLAIM_Operation * 244struct GNUNET_RECLAIM_Operation *
232GNUNET_RECLAIM_attestation_delete ( 245GNUNET_RECLAIM_credential_delete (
233 struct GNUNET_RECLAIM_Handle *h, 246 struct GNUNET_RECLAIM_Handle *h,
234 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, 247 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
235 const struct GNUNET_RECLAIM_Attestation *attr, 248 const struct GNUNET_RECLAIM_Credential *cred,
236 GNUNET_RECLAIM_ContinuationWithStatus cont, 249 GNUNET_RECLAIM_ContinuationWithStatus cont,
237 void *cont_cls); 250 void *cont_cls);
238 251
@@ -293,12 +306,12 @@ GNUNET_RECLAIM_get_attributes_stop (
293 306
294 307
295/** 308/**
296 * List all attestations for a local identity. 309 * List all credentials for a local identity.
297 * This MUST lock the `struct GNUNET_RECLAIM_Handle` 310 * This MUST lock the `struct GNUNET_RECLAIM_Handle`
298 * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and 311 * for any other calls than #GNUNET_RECLAIM_get_credentials_next() and
299 * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once 312 * #GNUNET_RECLAIM_get_credentials_stop. @a proc will be called once
300 * immediately, and then again after 313 * immediately, and then again after
301 * #GNUNET_RECLAIM_get_attestations_next() is invoked. 314 * #GNUNET_RECLAIM_get_credentials_next() is invoked.
302 * 315 *
303 * On error (disconnect), @a error_cb will be invoked. 316 * On error (disconnect), @a error_cb will be invoked.
304 * On normal completion, @a finish_cb proc will be 317 * On normal completion, @a finish_cb proc will be
@@ -309,34 +322,34 @@ GNUNET_RECLAIM_get_attributes_stop (
309 * @param error_cb Function to call on error (i.e. disconnect), 322 * @param error_cb Function to call on error (i.e. disconnect),
310 * the handle is afterwards invalid 323 * the handle is afterwards invalid
311 * @param error_cb_cls Closure for @a error_cb 324 * @param error_cb_cls Closure for @a error_cb
312 * @param proc Function to call on each attestation 325 * @param proc Function to call on each credential
313 * @param proc_cls Closure for @a proc 326 * @param proc_cls Closure for @a proc
314 * @param finish_cb Function to call on completion 327 * @param finish_cb Function to call on completion
315 * the handle is afterwards invalid 328 * the handle is afterwards invalid
316 * @param finish_cb_cls Closure for @a finish_cb 329 * @param finish_cb_cls Closure for @a finish_cb
317 * @return an iterator Handle to use for iteration 330 * @return an iterator Handle to use for iteration
318 */ 331 */
319struct GNUNET_RECLAIM_AttestationIterator * 332struct GNUNET_RECLAIM_CredentialIterator *
320GNUNET_RECLAIM_get_attestations_start ( 333GNUNET_RECLAIM_get_credentials_start (
321 struct GNUNET_RECLAIM_Handle *h, 334 struct GNUNET_RECLAIM_Handle *h,
322 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, 335 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
323 GNUNET_SCHEDULER_TaskCallback error_cb, 336 GNUNET_SCHEDULER_TaskCallback error_cb,
324 void *error_cb_cls, 337 void *error_cb_cls,
325 GNUNET_RECLAIM_AttestationResult proc, 338 GNUNET_RECLAIM_CredentialResult proc,
326 void *proc_cls, 339 void *proc_cls,
327 GNUNET_SCHEDULER_TaskCallback finish_cb, 340 GNUNET_SCHEDULER_TaskCallback finish_cb,
328 void *finish_cb_cls); 341 void *finish_cb_cls);
329 342
330 343
331/** 344/**
332 * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start 345 * Calls the record processor specified in #GNUNET_RECLAIM_get_credentials_start
333 * for the next record. 346 * for the next record.
334 * 347 *
335 * @param it the iterator 348 * @param it the iterator
336 */ 349 */
337void 350void
338GNUNET_RECLAIM_get_attestations_next (struct 351GNUNET_RECLAIM_get_credentials_next (
339 GNUNET_RECLAIM_AttestationIterator *ait); 352 struct GNUNET_RECLAIM_CredentialIterator *ait);
340 353
341 354
342/** 355/**
@@ -347,8 +360,8 @@ GNUNET_RECLAIM_get_attestations_next (struct
347 * @param it the iterator 360 * @param it the iterator
348 */ 361 */
349void 362void
350GNUNET_RECLAIM_get_attestations_stop (struct 363GNUNET_RECLAIM_get_credentials_stop (
351 GNUNET_RECLAIM_AttestationIterator *ait); 364 struct GNUNET_RECLAIM_CredentialIterator *ait);
352 365
353 366
354/** 367/**
@@ -370,7 +383,7 @@ GNUNET_RECLAIM_ticket_issue (
370 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, 383 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
371 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, 384 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
372 const struct GNUNET_RECLAIM_AttributeList *attrs, 385 const struct GNUNET_RECLAIM_AttributeList *attrs,
373 GNUNET_RECLAIM_TicketCallback cb, void *cb_cls); 386 GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls);
374 387
375 388
376/** 389/**
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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Florian Dold
22 * @author Christian Grothoff
23 *
24 * @file
25 * Two-peer set intersection operations
26 *
27 * @defgroup set Set intersection service
28 * Two-peer set operations
29 *
30 * @{
31 */
32
33#ifndef GNUNET_SETI_SERVICE_H
34#define GNUNET_SETI_SERVICE_H
35
36#ifdef __cplusplus
37extern "C"
38{
39#if 0 /* keep Emacsens' auto-indent happy */
40}
41#endif
42#endif
43
44#include "gnunet_common.h"
45#include "gnunet_time_lib.h"
46#include "gnunet_configuration_lib.h"
47
48
49/**
50 * Maximum size of a context message for set operation requests.
51 */
52#define GNUNET_SETI_CONTEXT_MESSAGE_MAX_SIZE ((1 << 16) - 1024)
53
54/**
55 * Opaque handle to a set.
56 */
57struct GNUNET_SETI_Handle;
58
59/**
60 * Opaque handle to a set operation request from another peer.
61 */
62struct GNUNET_SETI_Request;
63
64/**
65 * Opaque handle to a listen operation.
66 */
67struct GNUNET_SETI_ListenHandle;
68
69/**
70 * Opaque handle to a set operation.
71 */
72struct GNUNET_SETI_OperationHandle;
73
74
75/**
76 * Status for the result callback
77 */
78enum GNUNET_SETI_Status
79{
80
81 /**
82 * Element should be added to the result set of the local peer, i.e. the
83 * element is in the intersection.
84 */
85 GNUNET_SETI_STATUS_ADD_LOCAL,
86
87 /**
88 * Element should be delete from the result set of the local peer, i.e. the
89 * local peer is having an element that is not in the intersection.
90 */
91 GNUNET_SETI_STATUS_DEL_LOCAL,
92
93 /**
94 * The other peer refused to do the operation with us, or something went
95 * wrong.
96 */
97 GNUNET_SETI_STATUS_FAILURE,
98
99 /**
100 * Success, all elements have been sent (and received).
101 */
102 GNUNET_SETI_STATUS_DONE
103};
104
105
106/**
107 * Element stored in a set.
108 */
109struct GNUNET_SETI_Element
110{
111 /**
112 * Number of bytes in the buffer pointed to by data.
113 */
114 uint16_t size;
115
116 /**
117 * Application-specific element type.
118 */
119 uint16_t element_type;
120
121 /**
122 * Actual data of the element
123 */
124 const void *data;
125};
126
127
128/**
129 * Possible options to pass to a set operation.
130 *
131 * Used as tag for struct #GNUNET_SETI_Option.
132 */
133enum GNUNET_SETI_OptionType
134{
135 /**
136 * List terminator.
137 */
138 GNUNET_SETI_OPTION_END = 0,
139
140 /**
141 * Return the elements remaining in the intersection
142 * (#GNUNET_SETI_STATUS_ADD_LOCAL). If not given, the default is to return a
143 * list of the elements to be removed (#GNUNET_SETI_STATUS_DEL_LOCAL).
144 */
145 GNUNET_SETI_OPTION_RETURN_INTERSECTION = 1,
146};
147
148
149/**
150 * Option for set operations.
151 */
152struct GNUNET_SETI_Option
153{
154 /**
155 * Type of the option.
156 */
157 enum GNUNET_SETI_OptionType type;
158
159 /**
160 * Value for the option, only used with some options.
161 */
162 union
163 {
164 uint64_t num;
165 } v;
166};
167
168
169/**
170 * Callback for set union operation results. Called for each element
171 * in the result set.
172 *
173 * @param cls closure
174 * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
175 * @param current_size current set size
176 * @param status see `enum GNUNET_SETI_Status`
177 */
178typedef void
179(*GNUNET_SETI_ResultIterator) (void *cls,
180 const struct GNUNET_SETI_Element *element,
181 uint64_t current_size,
182 enum GNUNET_SETI_Status status);
183
184
185/**
186 * Called when another peer wants to do a set operation with the
187 * local peer. If a listen error occurs, the @a request is NULL.
188 *
189 * @param cls closure
190 * @param other_peer the other peer
191 * @param context_msg message with application specific information from
192 * the other peer
193 * @param request request from the other peer (never NULL), use GNUNET_SETI_accept()
194 * to accept it, otherwise the request will be refused
195 * Note that we can't just return value from the listen callback,
196 * as it is also necessary to specify the set we want to do the
197 * operation with, whith sometimes can be derived from the context
198 * message. It's necessary to specify the timeout.
199 */
200typedef void
201(*GNUNET_SETI_ListenCallback) (void *cls,
202 const struct GNUNET_PeerIdentity *other_peer,
203 const struct GNUNET_MessageHeader *context_msg,
204 struct GNUNET_SETI_Request *request);
205
206
207/**
208 * Create an empty set, supporting the specified operation.
209 *
210 * @param cfg configuration to use for connecting to the
211 * set service
212 * @return a handle to the set
213 */
214struct GNUNET_SETI_Handle *
215GNUNET_SETI_create (const struct GNUNET_CONFIGURATION_Handle *cfg);
216
217
218/**
219 * Add an element to the given set.
220 *
221 * @param set set to add element to
222 * @param element element to add to the set
223 * @param cb function to call when finished, can be NULL
224 * @param cb_cls closure for @a cb
225 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
226 * set is invalid (e.g. the set service crashed)
227 */
228int
229GNUNET_SETI_add_element (struct GNUNET_SETI_Handle *set,
230 const struct GNUNET_SETI_Element *element,
231 GNUNET_SCHEDULER_TaskCallback cb,
232 void *cb_cls);
233
234
235/**
236 * Destroy the set handle, and free all associated resources. Operations may
237 * still be pending when a set is destroyed (and will be allowed to complete).
238 *
239 * @param set set to destroy
240 */
241void
242GNUNET_SETI_destroy (struct GNUNET_SETI_Handle *set);
243
244
245/**
246 * Prepare a set operation to be evaluated with another peer. The evaluation
247 * will not start until the client provides a local set with
248 * GNUNET_SETI_commit().
249 *
250 * @param other_peer peer with the other set
251 * @param app_id hash for the application using the set
252 * @param context_msg additional information for the request
253 * @param options options to use when processing the request
254 * @param result_cb called on error or success
255 * @param result_cls closure for @a result_cb
256 * @return a handle to cancel the operation
257 */
258struct GNUNET_SETI_OperationHandle *
259GNUNET_SETI_prepare (const struct GNUNET_PeerIdentity *other_peer,
260 const struct GNUNET_HashCode *app_id,
261 const struct GNUNET_MessageHeader *context_msg,
262 const struct GNUNET_SETI_Option options[],
263 GNUNET_SETI_ResultIterator result_cb,
264 void *result_cls);
265
266
267/**
268 * Wait for set operation requests for the given application ID.
269 * If the connection to the set service is lost, the listener is
270 * re-created transparently with exponential backoff.
271 *
272 * @param cfg configuration to use for connecting to
273 * the set service
274 * @param app_id id of the application that handles set operation requests
275 * @param listen_cb called for each incoming request matching the operation
276 * and application id
277 * @param listen_cls handle for @a listen_cb
278 * @return a handle that can be used to cancel the listen operation
279 */
280struct GNUNET_SETI_ListenHandle *
281GNUNET_SETI_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
282 const struct GNUNET_HashCode *app_id,
283 GNUNET_SETI_ListenCallback listen_cb,
284 void *listen_cls);
285
286
287/**
288 * Cancel the given listen operation. After calling cancel, the
289 * listen callback for this listen handle will not be called again.
290 * Note that cancelling a listen operation will automatically reject
291 * all operations that have not yet been accepted.
292 *
293 * @param lh handle for the listen operation
294 */
295void
296GNUNET_SETI_listen_cancel (struct GNUNET_SETI_ListenHandle *lh);
297
298
299/**
300 * Accept a request we got via GNUNET_SETI_listen(). Must be called during
301 * GNUNET_SETI_listen(), as the `struct GNUNET_SETI_Request` becomes invalid
302 * afterwards.
303 * Call GNUNET_SETI_commit() to provide the local set to use for the operation,
304 * and to begin the exchange with the remote peer.
305 *
306 * @param request request to accept
307 * @param options options to use when processing the request
308 * @param result_cb callback for the results
309 * @param result_cls closure for @a result_cb
310 * @return a handle to cancel the operation
311 */
312struct GNUNET_SETI_OperationHandle *
313GNUNET_SETI_accept (struct GNUNET_SETI_Request *request,
314 const struct GNUNET_SETI_Option options[],
315 GNUNET_SETI_ResultIterator result_cb,
316 void *result_cls);
317
318
319/**
320 * Commit a set to be used with a set operation.
321 * This function is called once we have fully constructed
322 * the set that we want to use for the operation. At this
323 * time, the P2P protocol can then begin to exchange the
324 * set information and call the result callback with the
325 * result information.
326 *
327 * @param oh handle to the set operation
328 * @param set the set to use for the operation
329 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
330 * set is invalid (e.g. the set service crashed)
331 */
332int
333GNUNET_SETI_commit (struct GNUNET_SETI_OperationHandle *oh,
334 struct GNUNET_SETI_Handle *set);
335
336
337/**
338 * Cancel the given set operation. May not be called after the operation's
339 * `GNUNET_SETI_ResultIterator` has been called with a status of
340 * #GNUNET_SETI_STATUS_FAILURE or #GNUNET_SETI_STATUS_DONE.
341 *
342 * @param oh set operation to cancel
343 */
344void
345GNUNET_SETI_operation_cancel (struct GNUNET_SETI_OperationHandle *oh);
346
347
348/**
349 * Hash a set element.
350 *
351 * @param element the element that should be hashed
352 * @param[out] ret_hash a pointer to where the hash of @a element
353 * should be stored
354 */
355void
356GNUNET_SETI_element_hash (const struct GNUNET_SETI_Element *element,
357 struct GNUNET_HashCode *ret_hash);
358
359
360#if 0 /* keep Emacsens' auto-indent happy */
361{
362#endif
363#ifdef __cplusplus
364}
365#endif
366
367#endif
368
369/** @} */ /* 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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Florian Dold
22 * @author Christian Grothoff
23 *
24 * @file
25 * Two-peer set union operations
26 *
27 * @defgroup set Set union service
28 * Two-peer set operations
29 *
30 * @{
31 */
32
33#ifndef GNUNET_SETU_SERVICE_H
34#define GNUNET_SETU_SERVICE_H
35
36#ifdef __cplusplus
37extern "C"
38{
39#if 0 /* keep Emacsens' auto-indent happy */
40}
41#endif
42#endif
43
44#include "gnunet_common.h"
45#include "gnunet_time_lib.h"
46#include "gnunet_configuration_lib.h"
47
48
49/**
50 * Maximum size of a context message for set operation requests.
51 */
52#define GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE ((1 << 16) - 1024)
53
54/**
55 * Opaque handle to a set.
56 */
57struct GNUNET_SETU_Handle;
58
59/**
60 * Opaque handle to a set operation request from another peer.
61 */
62struct GNUNET_SETU_Request;
63
64/**
65 * Opaque handle to a listen operation.
66 */
67struct GNUNET_SETU_ListenHandle;
68
69/**
70 * Opaque handle to a set operation.
71 */
72struct GNUNET_SETU_OperationHandle;
73
74
75/**
76 * Status for the result callback
77 */
78enum GNUNET_SETU_Status
79{
80
81 /**
82 * Element should be added to the result set of the local peer, i.e. the
83 * local peer is missing an element.
84 */
85 GNUNET_SETU_STATUS_ADD_LOCAL,
86
87 /**
88 * Element should be added to the result set of the remote peer, i.e. the
89 * remote peer is missing an element. Only used if
90 * #GNUNET_SETU_OPTION_SYMMETRIC is set.
91 */
92 GNUNET_SETU_STATUS_ADD_REMOTE,
93
94 /**
95 * The other peer refused to do the operation with us, or something went
96 * wrong.
97 */
98 GNUNET_SETU_STATUS_FAILURE,
99
100 /**
101 * Success, all elements have been sent (and received).
102 */
103 GNUNET_SETU_STATUS_DONE
104};
105
106
107/**
108 * Element stored in a set.
109 */
110struct GNUNET_SETU_Element
111{
112 /**
113 * Number of bytes in the buffer pointed to by data.
114 */
115 uint16_t size;
116
117 /**
118 * Application-specific element type.
119 */
120 uint16_t element_type;
121
122 /**
123 * Actual data of the element
124 */
125 const void *data;
126};
127
128
129/**
130 * Possible options to pass to a set operation.
131 *
132 * Used as tag for struct #GNUNET_SETU_Option.
133 */
134enum GNUNET_SETU_OptionType
135{
136 /**
137 * List terminator.
138 */
139 GNUNET_SETU_OPTION_END=0,
140
141 /**
142 * Fail set operations when the other peer shows weird behavior
143 * that might by a Byzantine fault.
144 *
145 * For set union, 'v.num' is a lower bound on elements that the other peer
146 * must have in common with us.
147 */
148 GNUNET_SETU_OPTION_BYZANTINE=1,
149
150 /**
151 * Do not use the optimized set operation, but send full sets. Might
152 * trigger Byzantine fault detection.
153 */
154 GNUNET_SETU_OPTION_FORCE_FULL=2,
155
156 /**
157 * Only use optimized set operations, even though for this particular set
158 * operation they might be much slower. Might trigger Byzantine fault
159 * detection.
160 */
161 GNUNET_SETU_OPTION_FORCE_DELTA=4,
162
163 /**
164 * Notify client also if we are sending a value to the other peer.
165 */
166 GNUNET_SETU_OPTION_SYMMETRIC = 8
167};
168
169
170/**
171 * Option for set operations.
172 */
173struct GNUNET_SETU_Option
174{
175 /**
176 * Type of the option.
177 */
178 enum GNUNET_SETU_OptionType type;
179
180 /**
181 * Value for the option, only used with some options.
182 */
183 union
184 {
185 uint64_t num;
186 } v;
187};
188
189
190/**
191 * Callback for set union operation results. Called for each element
192 * in the result set.
193 *
194 * @param cls closure
195 * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
196 * @param current_size current set size
197 * @param status see `enum GNUNET_SETU_Status`
198 */
199typedef void
200(*GNUNET_SETU_ResultIterator) (void *cls,
201 const struct GNUNET_SETU_Element *element,
202 uint64_t current_size,
203 enum GNUNET_SETU_Status status);
204
205
206/**
207 * Called when another peer wants to do a set operation with the
208 * local peer. If a listen error occurs, the @a request is NULL.
209 *
210 * @param cls closure
211 * @param other_peer the other peer
212 * @param context_msg message with application specific information from
213 * the other peer
214 * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
215 * to accept it, otherwise the request will be refused
216 * Note that we can't just return value from the listen callback,
217 * as it is also necessary to specify the set we want to do the
218 * operation with, whith sometimes can be derived from the context
219 * message. It's necessary to specify the timeout.
220 */
221typedef void
222(*GNUNET_SETU_ListenCallback) (void *cls,
223 const struct GNUNET_PeerIdentity *other_peer,
224 const struct GNUNET_MessageHeader *context_msg,
225 struct GNUNET_SETU_Request *request);
226
227
228/**
229 * Create an empty set, supporting the specified operation.
230 *
231 * @param cfg configuration to use for connecting to the
232 * set service
233 * @return a handle to the set
234 */
235struct GNUNET_SETU_Handle *
236GNUNET_SETU_create (const struct GNUNET_CONFIGURATION_Handle *cfg);
237
238
239/**
240 * Add an element to the given set.
241 *
242 * @param set set to add element to
243 * @param element element to add to the set
244 * @param cb function to call when finished, can be NULL
245 * @param cb_cls closure for @a cb
246 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
247 * set is invalid (e.g. the set service crashed)
248 */
249int
250GNUNET_SETU_add_element (struct GNUNET_SETU_Handle *set,
251 const struct GNUNET_SETU_Element *element,
252 GNUNET_SCHEDULER_TaskCallback cb,
253 void *cb_cls);
254
255
256/**
257 * Destroy the set handle, and free all associated resources. Operations may
258 * still be pending when a set is destroyed (and will be allowed to complete).
259 *
260 * @param set set to destroy
261 */
262void
263GNUNET_SETU_destroy (struct GNUNET_SETU_Handle *set);
264
265
266/**
267 * Prepare a set operation to be evaluated with another peer. The evaluation
268 * will not start until the client provides a local set with
269 * GNUNET_SETU_commit().
270 *
271 * @param other_peer peer with the other set
272 * @param app_id hash for the application using the set
273 * @param context_msg additional information for the request
274 * @param options options to use when processing the request
275 * @param result_cb called on error or success
276 * @param result_cls closure for @a result_cb
277 * @return a handle to cancel the operation
278 */
279struct GNUNET_SETU_OperationHandle *
280GNUNET_SETU_prepare (const struct GNUNET_PeerIdentity *other_peer,
281 const struct GNUNET_HashCode *app_id,
282 const struct GNUNET_MessageHeader *context_msg,
283 const struct GNUNET_SETU_Option options[],
284 GNUNET_SETU_ResultIterator result_cb,
285 void *result_cls);
286
287
288/**
289 * Wait for set operation requests for the given application ID.
290 * If the connection to the set service is lost, the listener is
291 * re-created transparently with exponential backoff.
292 *
293 * @param cfg configuration to use for connecting to
294 * the set service
295 * @param app_id id of the application that handles set operation requests
296 * @param listen_cb called for each incoming request matching the operation
297 * and application id
298 * @param listen_cls handle for @a listen_cb
299 * @return a handle that can be used to cancel the listen operation
300 */
301struct GNUNET_SETU_ListenHandle *
302GNUNET_SETU_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
303 const struct GNUNET_HashCode *app_id,
304 GNUNET_SETU_ListenCallback listen_cb,
305 void *listen_cls);
306
307
308/**
309 * Cancel the given listen operation. After calling cancel, the
310 * listen callback for this listen handle will not be called again.
311 * Note that cancelling a listen operation will automatically reject
312 * all operations that have not yet been accepted.
313 *
314 * @param lh handle for the listen operation
315 */
316void
317GNUNET_SETU_listen_cancel (struct GNUNET_SETU_ListenHandle *lh);
318
319
320/**
321 * Accept a request we got via GNUNET_SETU_listen(). Must be called during
322 * GNUNET_SETU_listen(), as the `struct GNUNET_SETU_Request` becomes invalid
323 * afterwards.
324 * Call GNUNET_SETU_commit() to provide the local set to use for the operation,
325 * and to begin the exchange with the remote peer.
326 *
327 * @param request request to accept
328 * @param options options to use when processing the request
329 * @param result_cb callback for the results
330 * @param result_cls closure for @a result_cb
331 * @return a handle to cancel the operation
332 */
333struct GNUNET_SETU_OperationHandle *
334GNUNET_SETU_accept (struct GNUNET_SETU_Request *request,
335 const struct GNUNET_SETU_Option options[],
336 GNUNET_SETU_ResultIterator result_cb,
337 void *result_cls);
338
339
340/**
341 * Commit a set to be used with a set operation.
342 * This function is called once we have fully constructed
343 * the set that we want to use for the operation. At this
344 * time, the P2P protocol can then begin to exchange the
345 * set information and call the result callback with the
346 * result information.
347 *
348 * @param oh handle to the set operation
349 * @param set the set to use for the operation
350 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
351 * set is invalid (e.g. the set service crashed)
352 */
353int
354GNUNET_SETU_commit (struct GNUNET_SETU_OperationHandle *oh,
355 struct GNUNET_SETU_Handle *set);
356
357
358/**
359 * Cancel the given set operation. May not be called after the operation's
360 * `GNUNET_SETU_ResultIterator` has been called with a status of
361 * #GNUNET_SETU_STATUS_FAILURE or #GNUNET_SETU_STATUS_DONE.
362 *
363 * @param oh set operation to cancel
364 */
365void
366GNUNET_SETU_operation_cancel (struct GNUNET_SETU_OperationHandle *oh);
367
368
369/**
370 * Hash a set element.
371 *
372 * @param element the element that should be hashed
373 * @param[out] ret_hash a pointer to where the hash of @a element
374 * should be stored
375 */
376void
377GNUNET_SETU_element_hash (const struct GNUNET_SETU_Element *element,
378 struct GNUNET_HashCode *ret_hash);
379
380
381#if 0 /* keep Emacsens' auto-indent happy */
382{
383#endif
384#ifdef __cplusplus
385}
386#endif
387
388#endif
389
390/** @} */ /* 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 @@
1/**
2 * Copyright (C) 2016 Jack Engqvist Johansson
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22#ifndef GNUNET_URI_LIB_H
23#define GNUNET_URI_LIB_H
24
25
26/**
27 * The struct where the parsed values will be stored:
28 *
29 * scheme ":" [ "//" ] [ username ":" password "@" ] host [ ":" port ] [ "/" ] [ path ] [ "?" query ]
30 *
31 * Note: to make sure that no strings are copied, the first slash "/" in the
32 * path will be used to null terminate the hostname if no port is supplied.
33 */
34struct GNUNET_Uri {
35 char *scheme; /* scheme, without ":" and "//" */
36 char *username; /* username, default: NULL */
37 char *password; /* password, default: NULL */
38 char *host; /* hostname or IP address */
39 int port; /* port, default: 0 */
40 char *path; /* path, without leading "/", default: NULL */
41 char *query; /* query, default: NULL */
42 char *fragment; /* fragment, default: NULL */
43};
44
45
46/* A struct to hold the query string parameter values. */
47struct GNUNET_UriParam {
48 char *key;
49 char *val;
50};
51
52
53/**
54 * Parse a URL to a struct.
55 *
56 * The URL string should be in one of the following formats:
57 *
58 * Absolute URL:
59 * scheme ":" [ "//" ] [ username ":" password "@" ] host [ ":" port ] [ "/" ] [ path ] [ "?" query ] [ "#" fragment ]
60 *
61 * Relative URL:
62 * path [ "?" query ] [ "#" fragment ]
63 *
64 * The following parts will be parsed to the corresponding struct member.
65 *
66 * *url: a pointer to the struct where to store the parsed values.
67 * *url_str: a pointer to the url to be parsed (null terminated). The string
68 * will be modified.
69 *
70 * Returns 0 on success, otherwise -1.
71 */
72int
73GNUNET_uri_parse (struct GNUNET_Uri *url,
74 char *url_str);
75
76
77/**
78 * Split a path into several strings.
79 *
80 * No data is copied, the slashed are used as null terminators and then
81 * pointers to each path part will be stored in **parts. Double slashes will be
82 * treated as one.
83 *
84 * *path: the path to split. The string will be modified.
85 * **parts: a pointer to an array of (char *) where to store the result.
86 * max_parts: max number of parts to parse.
87 *
88 * Returns the number of parsed items. -1 on error.
89 */
90int
91GNUNET_uri_split_path (char *path,
92 char **parts,
93 int max_parts);
94
95
96/**
97 * Parse a query string into a key/value struct.
98 *
99 * The query string should be a null terminated string of parameters separated by
100 * a delimiter. Each parameter are checked for the equal sign character. If it
101 * appears in the parameter, it will be used as a null terminator and the part
102 * that comes after it will be the value of the parameter.
103 *
104 * No data are copied, the equal sign and delimiters are used as null
105 * terminators and then pointers to each parameter key and value will be stored
106 * in the yuarel_param struct.
107 *
108 * *query: the query string to parse. The string will be modified.
109 * delimiter: the character that separates the key/value pairs from eachother.
110 * *params: an array of (struct yuarel_param) where to store the result.
111 * max_values: max number of parameters to parse.
112 *
113 * Returns the number of parsed items. -1 on error.
114 */
115int
116GNUNET_uri_parse_query (char *query,
117 char delimiter,
118 struct GNUNET_UriParam *params,
119 int max_params);
120
121
122#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)
220 char *mysql_user; 220 char *mysql_user;
221 char *mysql_password; 221 char *mysql_password;
222 unsigned long long mysql_port; 222 unsigned long long mysql_port;
223 my_bool reconnect; 223 MYSQL_BOOL reconnect;
224 unsigned int timeout; 224 unsigned int timeout;
225 225
226 mc->dbf = mysql_init (NULL); 226 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)
1809 start = GNUNET_TIME_absolute_get (); 1809 start = GNUNET_TIME_absolute_get ();
1810 GNUNET_break (GNUNET_SYSERR != 1810 GNUNET_break (GNUNET_SYSERR !=
1811 GSN_database->iterate_records (GSN_database->cls, 1811 GSN_database->iterate_records (GSN_database->cls,
1812 (0 == GNUNET_is_zero (&zi->zone)) 1812 (GNUNET_YES == GNUNET_is_zero (&zi->zone))
1813 ? NULL 1813 ? NULL
1814 : &zi->zone, 1814 : &zi->zone,
1815 zi->seq, 1815 zi->seq,
@@ -2083,7 +2083,7 @@ monitor_iteration_next (void *cls)
2083 else 2083 else
2084 zm->iteration_cnt = zm->limit; /* use it all */ 2084 zm->iteration_cnt = zm->limit; /* use it all */
2085 ret = GSN_database->iterate_records (GSN_database->cls, 2085 ret = GSN_database->iterate_records (GSN_database->cls,
2086 (0 == GNUNET_is_zero (&zm->zone)) 2086 (GNUNET_YES == GNUNET_is_zero (&zm->zone))
2087 ? NULL 2087 ? NULL
2088 : &zm->zone, 2088 : &zm->zone,
2089 zm->seq, 2089 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)
139 139
140 (void) cls; 140 (void) cls;
141 if ((0 != GNUNET_memcmp (&lrm->private_key, &zm->zone)) && 141 if ((0 != GNUNET_memcmp (&lrm->private_key, &zm->zone)) &&
142 (0 != GNUNET_is_zero (&zm->zone))) 142 (GNUNET_NO == GNUNET_is_zero (&zm->zone)))
143 { 143 {
144 GNUNET_break (0); 144 GNUNET_break (0);
145 return GNUNET_SYSERR; 145 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
161struct RequestHandle 161struct RequestHandle
162{ 162{
163 /** 163 /**
164 * DLL
165 */
166 struct RequestHandle *next;
167
168 /**
169 * DLL
170 */
171 struct RequestHandle *prev;
172
173 /**
164 * Records to store 174 * Records to store
165 */ 175 */
166 char *record_name; 176 char *record_name;
@@ -258,6 +268,17 @@ struct RequestHandle
258}; 268};
259 269
260/** 270/**
271 * DLL
272 */
273static struct RequestHandle *requests_head;
274
275/**
276 * DLL
277 */
278static struct RequestHandle *requests_tail;
279
280
281/**
261 * Cleanup lookup handle 282 * Cleanup lookup handle
262 * @param handle Handle to clean up 283 * @param handle Handle to clean up
263 */ 284 */
@@ -298,7 +319,9 @@ cleanup_handle (void *cls)
298 { 319 {
299 json_decref (handle->resp_object); 320 json_decref (handle->resp_object);
300 } 321 }
301 322 GNUNET_CONTAINER_DLL_remove (requests_head,
323 requests_tail,
324 handle);
302 GNUNET_free (handle); 325 GNUNET_free (handle);
303} 326}
304 327
@@ -329,7 +352,7 @@ do_error (void *cls)
329 handle->proc (handle->proc_cls, resp, handle->response_code); 352 handle->proc (handle->proc_cls, resp, handle->response_code);
330 json_decref (json_error); 353 json_decref (json_error);
331 GNUNET_free (response); 354 GNUNET_free (response);
332 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 355 cleanup_handle (handle);
333} 356}
334 357
335 358
@@ -1024,10 +1047,14 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1024 handle->proc = proc; 1047 handle->proc = proc;
1025 handle->rest_handle = rest_handle; 1048 handle->rest_handle = rest_handle;
1026 handle->zone_pkey = NULL; 1049 handle->zone_pkey = NULL;
1027 1050 handle->timeout_task =
1051 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1028 handle->url = GNUNET_strdup (rest_handle->url); 1052 handle->url = GNUNET_strdup (rest_handle->url);
1029 if (handle->url[strlen (handle->url) - 1] == '/') 1053 if (handle->url[strlen (handle->url) - 1] == '/')
1030 handle->url[strlen (handle->url) - 1] = '\0'; 1054 handle->url[strlen (handle->url) - 1] = '\0';
1055 GNUNET_CONTAINER_DLL_insert (requests_head,
1056 requests_tail,
1057 handle);
1031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); 1058 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1032 if (GNUNET_NO == 1059 if (GNUNET_NO ==
1033 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) 1060 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
@@ -1036,9 +1063,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1036 return GNUNET_NO; 1063 return GNUNET_NO;
1037 } 1064 }
1038 1065
1039 handle->timeout_task =
1040 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1041
1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); 1066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1043 return GNUNET_YES; 1067 return GNUNET_YES;
1044} 1068}
@@ -1065,6 +1089,7 @@ libgnunet_plugin_rest_namestore_init (void *cls)
1065 api->cls = &plugin; 1089 api->cls = &plugin;
1066 api->name = GNUNET_REST_API_NS_NAMESTORE; 1090 api->name = GNUNET_REST_API_NS_NAMESTORE;
1067 api->process_request = &rest_process_request; 1091 api->process_request = &rest_process_request;
1092 state = ID_REST_STATE_INIT;
1068 GNUNET_asprintf (&allow_methods, 1093 GNUNET_asprintf (&allow_methods,
1069 "%s, %s, %s, %s, %s", 1094 "%s, %s, %s, %s, %s",
1070 MHD_HTTP_METHOD_GET, 1095 MHD_HTTP_METHOD_GET,
@@ -1091,10 +1116,13 @@ libgnunet_plugin_rest_namestore_done (void *cls)
1091{ 1116{
1092 struct GNUNET_REST_Plugin *api = cls; 1117 struct GNUNET_REST_Plugin *api = cls;
1093 struct Plugin *plugin = api->cls; 1118 struct Plugin *plugin = api->cls;
1119 struct RequestHandle *request;
1094 struct EgoEntry *ego_entry; 1120 struct EgoEntry *ego_entry;
1095 struct EgoEntry *ego_tmp; 1121 struct EgoEntry *ego_tmp;
1096 1122
1097 plugin->cfg = NULL; 1123 plugin->cfg = NULL;
1124 while (NULL != (request = requests_head))
1125 do_error (request);
1098 if (NULL != identity_handle) 1126 if (NULL != identity_handle)
1099 GNUNET_IDENTITY_disconnect (identity_handle); 1127 GNUNET_IDENTITY_disconnect (identity_handle);
1100 if (NULL != ns_handle) 1128 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;
113 113
114#endif 114#endif
115 115
116/**
117 * Salt for PoW calcualations.
118 */
119static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
120
116 121
117/** 122/**
118 * Per-peer information. 123 * Per-peer information.
@@ -806,7 +811,7 @@ check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
806 GNUNET_memcpy (&buf[sizeof(val)], 811 GNUNET_memcpy (&buf[sizeof(val)],
807 pkey, 812 pkey,
808 sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)); 813 sizeof(struct GNUNET_CRYPTO_EddsaPublicKey));
809 GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof", 814 GNUNET_CRYPTO_pow_hash (&salt,
810 buf, 815 buf,
811 sizeof(buf), 816 sizeof(buf),
812 &result); 817 &result);
@@ -861,7 +866,7 @@ find_proof (void *cls)
861 while ((counter != UINT64_MAX) && (i < ROUND_SIZE)) 866 while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
862 { 867 {
863 GNUNET_memcpy (buf, &counter, sizeof(uint64_t)); 868 GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
864 GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof", 869 GNUNET_CRYPTO_pow_hash (&salt,
865 buf, 870 buf,
866 sizeof(buf), 871 sizeof(buf),
867 &result); 872 &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 ()
34{ 34{
35 struct GNUNET_HashCode hc; 35 struct GNUNET_HashCode hc;
36 char buf[64]; 36 char buf[64];
37 struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
37 38
38 memset (buf, 1, sizeof(buf)); 39 memset (buf, 1, sizeof(buf));
39 for (unsigned int i = 0; i < 1024; i++) 40 for (unsigned int i = 0; i < 1024; i++)
40 GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof", 41 GNUNET_CRYPTO_pow_hash (&salt,
41 buf, 42 buf,
42 sizeof(buf), 43 sizeof(buf),
43 &hc); 44 &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;
180struct RequestHandle 180struct RequestHandle
181{ 181{
182 /** 182 /**
183 * DLL
184 */
185 struct RequestHandle *next;
186
187 /**
188 * DLL
189 */
190 struct RequestHandle *prev;
191
192 /**
183 * JSON temporary array 193 * JSON temporary array
184 */ 194 */
185 json_t *temp_array; 195 json_t *temp_array;
@@ -251,6 +261,15 @@ struct RequestHandle
251 int response_code; 261 int response_code;
252}; 262};
253 263
264/**
265 * DLL
266 */
267static struct RequestHandle *requests_head;
268
269/**
270 * DLL
271 */
272static struct RequestHandle *requests_tail;
254 273
255/** 274/**
256 * Cleanup lookup handle 275 * Cleanup lookup handle
@@ -300,7 +319,9 @@ cleanup_handle (void *cls)
300 GNUNET_PEERINFO_disconnect (peerinfo_handle); 319 GNUNET_PEERINFO_disconnect (peerinfo_handle);
301 peerinfo_handle = NULL; 320 peerinfo_handle = NULL;
302 } 321 }
303 322 GNUNET_CONTAINER_DLL_remove (requests_head,
323 requests_tail,
324 handle);
304 GNUNET_free (handle); 325 GNUNET_free (handle);
305} 326}
306 327
@@ -733,6 +754,13 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
733 handle->url = GNUNET_strdup (rest_handle->url); 754 handle->url = GNUNET_strdup (rest_handle->url);
734 if (handle->url[strlen (handle->url) - 1] == '/') 755 if (handle->url[strlen (handle->url) - 1] == '/')
735 handle->url[strlen (handle->url) - 1] = '\0'; 756 handle->url[strlen (handle->url) - 1] = '\0';
757 handle->timeout_task =
758 GNUNET_SCHEDULER_add_delayed (handle->timeout,
759 &do_error,
760 handle);
761 GNUNET_CONTAINER_DLL_insert (requests_head,
762 requests_tail,
763 handle);
736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); 764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
737 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, 765 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
738 handlers, 766 handlers,
@@ -742,10 +770,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
742 cleanup_handle (handle); 770 cleanup_handle (handle);
743 return GNUNET_NO; 771 return GNUNET_NO;
744 } 772 }
745 handle->timeout_task =
746 GNUNET_SCHEDULER_add_delayed (handle->timeout,
747 &do_error,
748 handle);
749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); 773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
750 return GNUNET_YES; 774 return GNUNET_YES;
751} 775}
@@ -800,6 +824,10 @@ libgnunet_plugin_rest_peerinfo_done (void *cls)
800 struct Plugin *plugin = api->cls; 824 struct Plugin *plugin = api->cls;
801 825
802 plugin->cfg = NULL; 826 plugin->cfg = NULL;
827 while (NULL != requests_head)
828 cleanup_handle (requests_head);
829 if (NULL != peerinfo_handle)
830 GNUNET_PEERINFO_disconnect (peerinfo_handle);
803 831
804 GNUNET_free (allow_methods); 832 GNUNET_free (allow_methods);
805 GNUNET_free (api); 833 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 = \
13 libgnunet_plugin_rest_openid_connect.la \ 13 libgnunet_plugin_rest_openid_connect.la \
14 libgnunet_plugin_rest_reclaim.la 14 libgnunet_plugin_rest_reclaim.la
15 15
16ATTESTATION_PLUGIN = \ 16CREDENTIAL_PLUGIN = \
17 libgnunet_plugin_reclaim_attestation_jwt.la 17 libgnunet_plugin_reclaim_credential_jwt.la
18 18
19EXTRA_DIST = \ 19EXTRA_DIST = \
20 reclaim.conf \ 20 reclaim.conf \
@@ -34,7 +34,7 @@ lib_LTLIBRARIES = \
34plugin_LTLIBRARIES = \ 34plugin_LTLIBRARIES = \
35 libgnunet_plugin_gnsrecord_reclaim.la \ 35 libgnunet_plugin_gnsrecord_reclaim.la \
36 libgnunet_plugin_reclaim_attribute_basic.la \ 36 libgnunet_plugin_reclaim_attribute_basic.la \
37 $(ATTESTATION_PLUGIN) \ 37 $(CREDENTIAL_PLUGIN) \
38 $(REST_PLUGIN) 38 $(REST_PLUGIN)
39 39
40bin_PROGRAMS = \ 40bin_PROGRAMS = \
@@ -115,8 +115,8 @@ libgnunetreclaim_la_SOURCES = \
115 reclaim.h \ 115 reclaim.h \
116 reclaim_attribute.c \ 116 reclaim_attribute.c \
117 reclaim_attribute.h \ 117 reclaim_attribute.h \
118 reclaim_attestation.c \ 118 reclaim_credential.c \
119 reclaim_attestation.h 119 reclaim_credential.h
120libgnunetreclaim_la_LIBADD = \ 120libgnunetreclaim_la_LIBADD = \
121 $(top_builddir)/src/util/libgnunetutil.la \ 121 $(top_builddir)/src/util/libgnunetutil.la \
122 $(GN_LIBINTL) $(XLIB) 122 $(GN_LIBINTL) $(XLIB)
@@ -133,14 +133,14 @@ libgnunet_plugin_reclaim_attribute_basic_la_LIBADD = \
133libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \ 133libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \
134 $(GN_PLUGIN_LDFLAGS) 134 $(GN_PLUGIN_LDFLAGS)
135 135
136libgnunet_plugin_reclaim_attestation_jwt_la_SOURCES = \ 136libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \
137 plugin_reclaim_attestation_jwt.c 137 plugin_reclaim_credential_jwt.c
138libgnunet_plugin_reclaim_attestation_jwt_la_LIBADD = \ 138libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \
139 $(top_builddir)/src/util/libgnunetutil.la \ 139 $(top_builddir)/src/util/libgnunetutil.la \
140 libgnunetreclaim.la \ 140 libgnunetreclaim.la \
141 -ljansson\ 141 -ljansson\
142 $(LTLIBINTL) 142 $(LTLIBINTL)
143libgnunet_plugin_reclaim_attestation_jwt_la_LDFLAGS = \ 143libgnunet_plugin_reclaim_credential_jwt_la_LDFLAGS = \
144 $(GN_PLUGIN_LDFLAGS) 144 $(GN_PLUGIN_LDFLAGS)
145 145
146gnunet_reclaim_SOURCES = \ 146gnunet_reclaim_SOURCES = \
@@ -152,11 +152,20 @@ gnunet_reclaim_LDADD = \
152 $(top_builddir)/src/identity/libgnunetidentity.la \ 152 $(top_builddir)/src/identity/libgnunetidentity.la \
153 $(GN_LIBINTL) 153 $(GN_LIBINTL)
154 154
155test_reclaim_attribute_SOURCES = \
156 test_reclaim_attribute.c
157test_reclaim_attribute_LDADD = \
158 $(top_builddir)/src/util/libgnunetutil.la \
159 libgnunetreclaim.la \
160 $(GN_LIBINTL)
161
155check_SCRIPTS = \ 162check_SCRIPTS = \
156 test_reclaim_attribute.sh \ 163 test_reclaim_attribute.sh \
157 test_reclaim_issue.sh \ 164 test_reclaim_issue.sh \
158 test_reclaim_consume.sh 165 test_reclaim_consume.sh
159# test_reclaim_revoke.sh 166
167check_PROGRAMS = \
168 test_reclaim_attribute
160 169
161if ENABLE_TEST_RUN 170if ENABLE_TEST_RUN
162 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 171 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;
43static int list; 43static int list;
44 44
45/** 45/**
46 * List attestations flag 46 * List credentials flag
47 */ 47 */
48static int list_attestations; 48static int list_credentials;
49 49
50/** 50/**
51 * Attestation ID string 51 * Credential ID string
52 */ 52 */
53static char *attestation_id; 53static char *credential_id;
54 54
55/** 55/**
56 * Attestation ID 56 * Credential ID
57 */ 57 */
58static struct GNUNET_RECLAIM_Identifier attestation; 58static struct GNUNET_RECLAIM_Identifier credential;
59 59
60/** 60/**
61 * Attestation name 61 * Credential name
62 */ 62 */
63static char *attestation_name; 63static char *credential_name;
64 64
65/** 65/**
66 * Attestation exists 66 * Credential type
67 */ 67 */
68static int attestation_exists; 68static char *credential_type;
69
70/**
71 * Credential exists
72 */
73static int credential_exists;
69 74
70/** 75/**
71 * Relying party 76 * Relying party
@@ -133,9 +138,9 @@ static struct GNUNET_RECLAIM_Operation *reclaim_op;
133static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator; 138static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
134 139
135/** 140/**
136 * Attestation iterator 141 * Credential iterator
137 */ 142 */
138static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator; 143static struct GNUNET_RECLAIM_CredentialIterator *cred_iterator;
139 144
140 145
141/** 146/**
@@ -143,10 +148,6 @@ static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator;
143 */ 148 */
144static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator; 149static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
145 150
146/**
147 * Master ABE key
148 */
149static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
150 151
151/** 152/**
152 * ego private key 153 * ego private key
@@ -208,25 +209,27 @@ do_cleanup (void *cls)
208 GNUNET_RECLAIM_cancel (reclaim_op); 209 GNUNET_RECLAIM_cancel (reclaim_op);
209 if (NULL != attr_iterator) 210 if (NULL != attr_iterator)
210 GNUNET_RECLAIM_get_attributes_stop (attr_iterator); 211 GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
211 if (NULL != attest_iterator) 212 if (NULL != cred_iterator)
212 GNUNET_RECLAIM_get_attestations_stop (attest_iterator); 213 GNUNET_RECLAIM_get_credentials_stop (cred_iterator);
213 if (NULL != ticket_iterator) 214 if (NULL != ticket_iterator)
214 GNUNET_RECLAIM_ticket_iteration_stop (ticket_iterator); 215 GNUNET_RECLAIM_ticket_iteration_stop (ticket_iterator);
215 if (NULL != reclaim_handle) 216 if (NULL != reclaim_handle)
216 GNUNET_RECLAIM_disconnect (reclaim_handle); 217 GNUNET_RECLAIM_disconnect (reclaim_handle);
217 if (NULL != identity_handle) 218 if (NULL != identity_handle)
218 GNUNET_IDENTITY_disconnect (identity_handle); 219 GNUNET_IDENTITY_disconnect (identity_handle);
219 if (NULL != abe_key)
220 GNUNET_free (abe_key);
221 if (NULL != attr_list) 220 if (NULL != attr_list)
222 GNUNET_free (attr_list); 221 GNUNET_free (attr_list);
223 if (NULL != attr_to_delete) 222 if (NULL != attr_to_delete)
224 GNUNET_free (attr_to_delete); 223 GNUNET_free (attr_to_delete);
224 if (NULL == credential_type)
225 GNUNET_free (credential_type);
225} 226}
226 227
227 228
228static void 229static void
229ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) 230ticket_issue_cb (void *cls,
231 const struct GNUNET_RECLAIM_Ticket *ticket,
232 const struct GNUNET_RECLAIM_PresentationList *presentations)
230{ 233{
231 char *ticket_str; 234 char *ticket_str;
232 235
@@ -260,7 +263,7 @@ static void
260process_attrs (void *cls, 263process_attrs (void *cls,
261 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 264 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
262 const struct GNUNET_RECLAIM_Attribute *attr, 265 const struct GNUNET_RECLAIM_Attribute *attr,
263 const struct GNUNET_RECLAIM_Attestation *attest) 266 const struct GNUNET_RECLAIM_Presentation *presentation)
264{ 267{
265 char *value_str; 268 char *value_str;
266 char *id; 269 char *id;
@@ -280,7 +283,7 @@ process_attrs (void *cls,
280 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type); 283 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
281 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id)); 284 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
282 value_str = NULL; 285 value_str = NULL;
283 if (NULL == attest) 286 if (NULL == presentation)
284 { 287 {
285 value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type, 288 value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
286 attr->data, 289 attr->data,
@@ -290,7 +293,7 @@ process_attrs (void *cls,
290 { 293 {
291 struct GNUNET_RECLAIM_AttributeListEntry *ale; 294 struct GNUNET_RECLAIM_AttributeListEntry *ale;
292 struct GNUNET_RECLAIM_AttributeList *al 295 struct GNUNET_RECLAIM_AttributeList *al
293 = GNUNET_RECLAIM_attestation_get_attributes (attest); 296 = GNUNET_RECLAIM_presentation_get_attributes (presentation);
294 297
295 for (ale = al->list_head; NULL != ale; ale = ale->next) 298 for (ale = al->list_head; NULL != ale; ale = ale->next)
296 { 299 {
@@ -298,10 +301,8 @@ process_attrs (void *cls,
298 continue; 301 continue;
299 value_str 302 value_str
300 = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type, 303 = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
301 ale->attribute-> 304 ale->attribute->data,
302 data, 305 ale->attribute->data_size);
303 ale->attribute->
304 data_size);
305 break; 306 break;
306 } 307 }
307 } 308 }
@@ -312,7 +313,7 @@ process_attrs (void *cls,
312 attr_type, 313 attr_type,
313 attr->flag, 314 attr->flag,
314 id, 315 id,
315 (NULL == attest) ? "" : "(ATTESTED)"); 316 (NULL == presentation) ? "" : "(ATTESTED)");
316 GNUNET_free (value_str); 317 GNUNET_free (value_str);
317 GNUNET_free (id); 318 GNUNET_free (id);
318} 319}
@@ -362,7 +363,7 @@ static void
362iter_error (void *cls) 363iter_error (void *cls)
363{ 364{
364 attr_iterator = NULL; 365 attr_iterator = NULL;
365 attest_iterator = NULL; 366 cred_iterator = NULL;
366 fprintf (stderr, "Failed\n"); 367 fprintf (stderr, "Failed\n");
367 368
368 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); 369 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
@@ -457,6 +458,7 @@ iter_finished (void *cls)
457 if (NULL == attr_to_delete) 458 if (NULL == attr_to_delete)
458 { 459 {
459 fprintf (stdout, "No such attribute ``%s''\n", attr_delete); 460 fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
461 GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
460 return; 462 return;
461 } 463 }
462 reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle, 464 reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
@@ -489,9 +491,9 @@ iter_finished (void *cls)
489 claim = 491 claim =
490 GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size); 492 GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size);
491 } 493 }
492 if (NULL != attestation_id) 494 if (NULL != credential_id)
493 { 495 {
494 claim->attestation = attestation; 496 claim->credential = credential;
495 } 497 }
496 reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle, 498 reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
497 pkey, 499 pkey,
@@ -524,7 +526,7 @@ iter_cb (void *cls,
524 if (0 == strcasecmp (attr_name, attr->name)) 526 if (0 == strcasecmp (attr_name, attr->name))
525 { 527 {
526 claim = GNUNET_RECLAIM_attribute_new (attr->name, 528 claim = GNUNET_RECLAIM_attribute_new (attr->name,
527 &attr->attestation, 529 &attr->credential,
528 attr->type, 530 attr->type,
529 attr->data, 531 attr->data,
530 attr->data_size); 532 attr->data_size);
@@ -543,7 +545,7 @@ iter_cb (void *cls,
543 } 545 }
544 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 546 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
545 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, 547 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
546 &attr->attestation, 548 &attr->credential,
547 attr->type, 549 attr->type,
548 attr->data, 550 attr->data,
549 attr->data_size); 551 attr->data_size);
@@ -562,7 +564,7 @@ iter_cb (void *cls,
562 if (0 == strcasecmp (attr_delete, label)) 564 if (0 == strcasecmp (attr_delete, label))
563 { 565 {
564 attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name, 566 attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name,
565 &attr->attestation, 567 &attr->credential,
566 attr->type, 568 attr->type,
567 attr->data, 569 attr->data,
568 attr->data_size); 570 attr->data_size);
@@ -577,7 +579,7 @@ iter_cb (void *cls,
577 attr->data_size); 579 attr->data_size);
578 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type); 580 attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
579 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id)); 581 id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
580 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation)) 582 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->credential))
581 { 583 {
582 fprintf (stdout, 584 fprintf (stdout,
583 "%s: ``%s'' (%s); ID: %s\n", 585 "%s: ``%s'' (%s); ID: %s\n",
@@ -588,17 +590,17 @@ iter_cb (void *cls,
588 } 590 }
589 else 591 else
590 { 592 {
591 char *attest_id = 593 char *cred_id =
592 GNUNET_STRINGS_data_to_string_alloc (&attr->attestation, 594 GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
593 sizeof(attr->attestation)); 595 sizeof(attr->credential));
594 fprintf (stdout, 596 fprintf (stdout,
595 "%s: <``%s'' in attestation %s> (%s); ID: %s\n", 597 "%s: ``%s'' in credential presentation `%s' (%s); ID: %s\n",
596 attr->name, 598 attr->name,
597 attr_str, 599 attr_str,
598 attest_id, 600 cred_id,
599 attr_type, 601 attr_type,
600 id); 602 id);
601 GNUNET_free (attest_id); 603 GNUNET_free (cred_id);
602 604
603 } 605 }
604 GNUNET_free (id); 606 GNUNET_free (id);
@@ -608,29 +610,31 @@ iter_cb (void *cls,
608 610
609 611
610static void 612static void
611attest_iter_finished (void *cls) 613cred_iter_finished (void *cls)
612{ 614{
613 attest_iterator = NULL; 615 cred_iterator = NULL;
614 616
615 // Add new attestation 617 // Add new credential
616 if ((NULL != attestation_name) && 618 if ((NULL != credential_name) &&
617 (NULL != attr_value)) 619 (NULL != attr_value))
618 { 620 {
619 struct GNUNET_RECLAIM_Attestation *attestation = 621 enum GNUNET_RECLAIM_CredentialType ctype =
620 GNUNET_RECLAIM_attestation_new (attestation_name, 622 GNUNET_RECLAIM_credential_typename_to_number (credential_type);
621 GNUNET_RECLAIM_ATTESTATION_TYPE_JWT, // FIXME hardcoded 623 struct GNUNET_RECLAIM_Credential *credential =
622 attr_value, 624 GNUNET_RECLAIM_credential_new (credential_name,
623 strlen (attr_value)); 625 ctype,
624 reclaim_op = GNUNET_RECLAIM_attestation_store (reclaim_handle, 626 attr_value,
625 pkey, 627 strlen (attr_value));
626 attestation, 628 reclaim_op = GNUNET_RECLAIM_credential_store (reclaim_handle,
627 &exp_interval, 629 pkey,
628 store_cont, 630 credential,
629 NULL); 631 &exp_interval,
632 store_cont,
633 NULL);
630 return; 634 return;
631 635
632 } 636 }
633 if (list_attestations) 637 if (list_credentials)
634 { 638 {
635 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); 639 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
636 return; 640 return;
@@ -648,34 +652,34 @@ attest_iter_finished (void *cls)
648 652
649 653
650static void 654static void
651attest_iter_cb (void *cls, 655cred_iter_cb (void *cls,
652 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 656 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
653 const struct GNUNET_RECLAIM_Attestation *attest) 657 const struct GNUNET_RECLAIM_Credential *cred)
654{ 658{
655 char *attest_str; 659 char *cred_str;
656 char *attr_str; 660 char *attr_str;
657 char *id; 661 char *id;
658 const char *attest_type; 662 const char *cred_type;
659 struct GNUNET_RECLAIM_AttributeListEntry *ale; 663 struct GNUNET_RECLAIM_AttributeListEntry *ale;
660 664
661 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&attestation, 665 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&credential,
662 &attest->id)) 666 &cred->id))
663 attestation_exists = GNUNET_YES; 667 credential_exists = GNUNET_YES;
664 if (list_attestations) 668 if (list_credentials)
665 { 669 {
666 attest_str = GNUNET_RECLAIM_attestation_value_to_string (attest->type, 670 cred_str = GNUNET_RECLAIM_credential_value_to_string (cred->type,
667 attest->data, 671 cred->data,
668 attest->data_size); 672 cred->data_size);
669 attest_type = GNUNET_RECLAIM_attestation_number_to_typename (attest->type); 673 cred_type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
670 id = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(attest->id)); 674 id = GNUNET_STRINGS_data_to_string_alloc (&cred->id, sizeof(cred->id));
671 fprintf (stdout, 675 fprintf (stdout,
672 "%s: ``%s'' (%s); ID: %s\n", 676 "%s: ``%s'' (%s); ID: %s\n",
673 attest->name, 677 cred->name,
674 attest_str, 678 cred_str,
675 attest_type, 679 cred_type,
676 id); 680 id);
677 struct GNUNET_RECLAIM_AttributeList *attrs = 681 struct GNUNET_RECLAIM_AttributeList *attrs =
678 GNUNET_RECLAIM_attestation_get_attributes (attest); 682 GNUNET_RECLAIM_credential_get_attributes (cred);
679 if (NULL != attrs) 683 if (NULL != attrs)
680 { 684 {
681 fprintf (stdout, 685 fprintf (stdout,
@@ -684,11 +688,8 @@ attest_iter_cb (void *cls,
684 { 688 {
685 attr_str = GNUNET_RECLAIM_attribute_value_to_string ( 689 attr_str = GNUNET_RECLAIM_attribute_value_to_string (
686 ale->attribute->type, 690 ale->attribute->type,
687 ale->attribute-> 691 ale->attribute->data,
688 data, 692 ale->attribute->data_size);
689 ale->attribute->
690 data_size);
691
692 fprintf (stdout, 693 fprintf (stdout,
693 "\t %s: %s\n", ale->attribute->name, attr_str); 694 "\t %s: %s\n", ale->attribute->name, attr_str);
694 GNUNET_free (attr_str); 695 GNUNET_free (attr_str);
@@ -697,7 +698,7 @@ attest_iter_cb (void *cls,
697 } 698 }
698 GNUNET_free (id); 699 GNUNET_free (id);
699 } 700 }
700 GNUNET_RECLAIM_get_attestations_next (attest_iterator); 701 GNUNET_RECLAIM_get_credentials_next (cred_iterator);
701} 702}
702 703
703 704
@@ -710,12 +711,14 @@ start_process ()
710 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); 711 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
711 return; 712 return;
712 } 713 }
713 attestation = GNUNET_RECLAIM_ID_ZERO; 714 if (NULL == credential_type)
714 if (NULL != attestation_id) 715 credential_type = GNUNET_strdup ("JWT");
715 GNUNET_STRINGS_string_to_data (attestation_id, 716 credential = GNUNET_RECLAIM_ID_ZERO;
716 strlen (attestation_id), 717 if (NULL != credential_id)
717 &attestation, sizeof(attestation)); 718 GNUNET_STRINGS_string_to_data (credential_id,
718 attestation_exists = GNUNET_NO; 719 strlen (credential_id),
720 &credential, sizeof(credential));
721 credential_exists = GNUNET_NO;
719 if (list_tickets) 722 if (list_tickets)
720 { 723 {
721 ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle, 724 ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
@@ -750,15 +753,14 @@ start_process ()
750 753
751 attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 754 attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
752 claim = NULL; 755 claim = NULL;
753 attest_iterator = GNUNET_RECLAIM_get_attestations_start (reclaim_handle, 756 cred_iterator = GNUNET_RECLAIM_get_credentials_start (reclaim_handle,
754 pkey, 757 pkey,
755 &iter_error, 758 &iter_error,
756 NULL, 759 NULL,
757 &attest_iter_cb, 760 &cred_iter_cb,
758 NULL, 761 NULL,
759 & 762 &cred_iter_finished,
760 attest_iter_finished, 763 NULL);
761 NULL);
762 764
763} 765}
764 766
@@ -856,20 +858,20 @@ main (int argc, char *const argv[])
856 gettext_noop ("List attributes for EGO"), 858 gettext_noop ("List attributes for EGO"),
857 &list), 859 &list),
858 GNUNET_GETOPT_option_flag ('A', 860 GNUNET_GETOPT_option_flag ('A',
859 "attestations", 861 "credentials",
860 gettext_noop ("List attestations for EGO"), 862 gettext_noop ("List credentials for EGO"),
861 &list_attestations), 863 &list_credentials),
862 GNUNET_GETOPT_option_string ('I', 864 GNUNET_GETOPT_option_string ('I',
863 "Attestation ID", 865 "Credential ID",
864 "ATTESTATION_ID", 866 "CREDENTIAL_ID",
865 gettext_noop ( 867 gettext_noop (
866 "Attestation to use for attribute"), 868 "Credential to use for attribute"),
867 &attestation_id), 869 &credential_id),
868 GNUNET_GETOPT_option_string ('N', 870 GNUNET_GETOPT_option_string ('N',
869 "attestation-name", 871 "credential-name",
870 "NAME", 872 "NAME",
871 gettext_noop ("Attestation name"), 873 gettext_noop ("Credential name"),
872 &attestation_name), 874 &credential_name),
873 GNUNET_GETOPT_option_string ('i', 875 GNUNET_GETOPT_option_string ('i',
874 "issue", 876 "issue",
875 "A1,A2,...", 877 "A1,A2,...",
@@ -891,6 +893,11 @@ main (int argc, char *const argv[])
891 "TYPE", 893 "TYPE",
892 gettext_noop ("Type of attribute"), 894 gettext_noop ("Type of attribute"),
893 &type_str), 895 &type_str),
896 GNUNET_GETOPT_option_string ('u',
897 "credential-type",
898 "TYPE",
899 gettext_noop ("Type of credential"),
900 &credential_type),
894 GNUNET_GETOPT_option_flag ('T', 901 GNUNET_GETOPT_option_flag ('T',
895 "tickets", 902 "tickets",
896 gettext_noop ("List tickets of ego"), 903 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
170 170
171 /** 171 /**
172 * Head of the DLL of 172 * Head of the DLL of
173 * Attribute iteration operations in 173 * Credential iteration operations in
174 * progress initiated by this client 174 * progress initiated by this client
175 */ 175 */
176 struct Iterator *attest_iter_head; 176 struct Iterator *cred_iter_head;
177 177
178 /** 178 /**
179 * Tail of the DLL of 179 * Tail of the DLL of
180 * Attribute iteration operations 180 * Credential iteration operations
181 * in progress initiated by this client 181 * in progress initiated by this client
182 */ 182 */
183 struct Iterator *attest_iter_tail; 183 struct Iterator *cred_iter_tail;
184 184
185 /** 185 /**
186 * Head of DLL of ticket iteration ops 186 * Head of DLL of ticket iteration ops
@@ -285,9 +285,9 @@ struct AttributeDeleteHandle
285 struct GNUNET_RECLAIM_Attribute *claim; 285 struct GNUNET_RECLAIM_Attribute *claim;
286 286
287 /** 287 /**
288 * The attestation to delete 288 * The credential to delete
289 */ 289 */
290 struct GNUNET_RECLAIM_Attestation *attest; 290 struct GNUNET_RECLAIM_Credential *credential;
291 291
292 /** 292 /**
293 * Tickets to update 293 * Tickets to update
@@ -352,9 +352,9 @@ struct AttributeStoreHandle
352 struct GNUNET_RECLAIM_Attribute *claim; 352 struct GNUNET_RECLAIM_Attribute *claim;
353 353
354 /** 354 /**
355 * The attestation to store 355 * The credential to store
356 */ 356 */
357 struct GNUNET_RECLAIM_Attestation *attest; 357 struct GNUNET_RECLAIM_Credential *credential;
358 358
359 /** 359 /**
360 * The attribute expiration interval 360 * The attribute expiration interval
@@ -488,8 +488,8 @@ cleanup_adh (struct AttributeDeleteHandle *adh)
488 GNUNET_free (adh->label); 488 GNUNET_free (adh->label);
489 if (NULL != adh->claim) 489 if (NULL != adh->claim)
490 GNUNET_free (adh->claim); 490 GNUNET_free (adh->claim);
491 if (NULL != adh->attest) 491 if (NULL != adh->credential)
492 GNUNET_free (adh->attest); 492 GNUNET_free (adh->credential);
493 while (NULL != (le = adh->tickets_to_update_head)) 493 while (NULL != (le = adh->tickets_to_update_head))
494 { 494 {
495 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head, 495 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
@@ -517,8 +517,8 @@ cleanup_as_handle (struct AttributeStoreHandle *ash)
517 GNUNET_NAMESTORE_cancel (ash->ns_qe); 517 GNUNET_NAMESTORE_cancel (ash->ns_qe);
518 if (NULL != ash->claim) 518 if (NULL != ash->claim)
519 GNUNET_free (ash->claim); 519 GNUNET_free (ash->claim);
520 if (NULL != ash->attest) 520 if (NULL != ash->credential)
521 GNUNET_free (ash->attest); 521 GNUNET_free (ash->credential);
522 GNUNET_free (ash); 522 GNUNET_free (ash);
523} 523}
524 524
@@ -569,9 +569,9 @@ cleanup_client (struct IdpClient *idp)
569 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai); 569 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
570 GNUNET_free (ai); 570 GNUNET_free (ai);
571 } 571 }
572 while (NULL != (ai = idp->attest_iter_head)) 572 while (NULL != (ai = idp->cred_iter_head))
573 { 573 {
574 GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail, 574 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
575 ai); 575 ai);
576 GNUNET_free (ai); 576 GNUNET_free (ai);
577 } 577 }
@@ -646,19 +646,33 @@ static void
646send_ticket_result (const struct IdpClient *client, 646send_ticket_result (const struct IdpClient *client,
647 uint32_t r_id, 647 uint32_t r_id,
648 const struct GNUNET_RECLAIM_Ticket *ticket, 648 const struct GNUNET_RECLAIM_Ticket *ticket,
649 const struct GNUNET_RECLAIM_PresentationList *presentations,
649 uint32_t success) 650 uint32_t success)
650{ 651{
651 struct TicketResultMessage *irm; 652 struct TicketResultMessage *irm;
652 struct GNUNET_MQ_Envelope *env; 653 struct GNUNET_MQ_Envelope *env;
654 size_t pres_len = 0;
653 655
654 env = GNUNET_MQ_msg (irm, 656 if (NULL != presentations)
655 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT); 657 {
658 pres_len =
659 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
660 }
661 env = GNUNET_MQ_msg_extra (irm,
662 pres_len,
663 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
656 if (NULL != ticket) 664 if (NULL != ticket)
657 { 665 {
658 irm->ticket = *ticket; 666 irm->ticket = *ticket;
659 } 667 }
660 // TODO add success member 668 // TODO add success member
661 irm->id = htonl (r_id); 669 irm->id = htonl (r_id);
670 irm->presentations_len = htons (pres_len);
671 if (NULL != presentations)
672 {
673 GNUNET_RECLAIM_presentation_list_serialize (presentations,
674 (char*) &irm[1]);
675 }
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n"); 676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
663 GNUNET_MQ_send (client->mq, env); 677 GNUNET_MQ_send (client->mq, env);
664} 678}
@@ -669,12 +683,14 @@ send_ticket_result (const struct IdpClient *client,
669 * 683 *
670 * @param cls out ticket issue operation handle 684 * @param cls out ticket issue operation handle
671 * @param ticket the issued ticket 685 * @param ticket the issued ticket
686 * @param presentations newly created credential presentations (NULL on error)
672 * @param success issue success status (GNUNET_OK if successful) 687 * @param success issue success status (GNUNET_OK if successful)
673 * @param emsg error message (NULL of success is GNUNET_OK) 688 * @param emsg error message (NULL of success is GNUNET_OK)
674 */ 689 */
675static void 690static void
676issue_ticket_result_cb (void *cls, 691issue_ticket_result_cb (void *cls,
677 struct GNUNET_RECLAIM_Ticket *ticket, 692 struct GNUNET_RECLAIM_Ticket *ticket,
693 struct GNUNET_RECLAIM_PresentationList *presentations,
678 int32_t success, 694 int32_t success,
679 const char *emsg) 695 const char *emsg)
680{ 696{
@@ -682,7 +698,7 @@ issue_ticket_result_cb (void *cls,
682 698
683 if (GNUNET_OK != success) 699 if (GNUNET_OK != success)
684 { 700 {
685 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR); 701 send_ticket_result (tio->client, tio->r_id, NULL, NULL, GNUNET_SYSERR);
686 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head, 702 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
687 tio->client->issue_op_tail, 703 tio->client->issue_op_tail,
688 tio); 704 tio);
@@ -690,7 +706,8 @@ issue_ticket_result_cb (void *cls,
690 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg); 706 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
691 return; 707 return;
692 } 708 }
693 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR); 709 send_ticket_result (tio->client, tio->r_id,
710 ticket, presentations, GNUNET_SYSERR);
694 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head, 711 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
695 tio->client->issue_op_tail, 712 tio->client->issue_op_tail,
696 tio); 713 tio);
@@ -732,6 +749,7 @@ handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
732 struct TicketIssueOperation *tio; 749 struct TicketIssueOperation *tio;
733 struct IdpClient *idp = cls; 750 struct IdpClient *idp = cls;
734 struct GNUNET_RECLAIM_AttributeList *attrs; 751 struct GNUNET_RECLAIM_AttributeList *attrs;
752 struct GNUNET_RECLAIM_AttributeListEntry *le;
735 size_t attrs_len; 753 size_t attrs_len;
736 754
737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n"); 755 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)
739 attrs_len = ntohs (im->attr_len); 757 attrs_len = ntohs (im->attr_len);
740 attrs = GNUNET_RECLAIM_attribute_list_deserialize ((char *) &im[1], 758 attrs = GNUNET_RECLAIM_attribute_list_deserialize ((char *) &im[1],
741 attrs_len); 759 attrs_len);
760 for (le = attrs->list_head; NULL != le; le = le->next)
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "List entry: %s\n", le->attribute->name);
763
742 tio->r_id = ntohl (im->id); 764 tio->r_id = ntohl (im->id);
743 tio->client = idp; 765 tio->client = idp;
744 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio); 766 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
@@ -842,7 +864,7 @@ static void
842consume_result_cb (void *cls, 864consume_result_cb (void *cls,
843 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 865 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
844 const struct GNUNET_RECLAIM_AttributeList *attrs, 866 const struct GNUNET_RECLAIM_AttributeList *attrs,
845 const struct GNUNET_RECLAIM_AttestationList *attests, 867 const struct GNUNET_RECLAIM_PresentationList *presentations,
846 int32_t success, 868 int32_t success,
847 const char *emsg) 869 const char *emsg)
848{ 870{
@@ -851,28 +873,28 @@ consume_result_cb (void *cls,
851 struct GNUNET_MQ_Envelope *env; 873 struct GNUNET_MQ_Envelope *env;
852 char *data_tmp; 874 char *data_tmp;
853 size_t attrs_len = 0; 875 size_t attrs_len = 0;
854 size_t attests_len = 0; 876 size_t pres_len = 0;
855 877
856 if (GNUNET_OK != success) 878 if (GNUNET_OK != success)
857 { 879 {
858 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg); 880 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
859 } 881 }
860 attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs); 882 attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
861 attests_len = GNUNET_RECLAIM_attestation_list_serialize_get_size (attests); 883 pres_len = GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
863 "Sending CONSUME_TICKET_RESULT message\n"); 885 "Sending CONSUME_TICKET_RESULT message\n");
864 env = GNUNET_MQ_msg_extra (crm, 886 env = GNUNET_MQ_msg_extra (crm,
865 attrs_len + attests_len, 887 attrs_len + pres_len,
866 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT); 888 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
867 crm->id = htonl (cop->r_id); 889 crm->id = htonl (cop->r_id);
868 crm->attrs_len = htons (attrs_len); 890 crm->attrs_len = htons (attrs_len);
869 crm->attestations_len = htons (attests_len); 891 crm->presentations_len = htons (pres_len);
870 crm->identity = *identity; 892 crm->identity = *identity;
871 crm->result = htonl (success); 893 crm->result = htonl (success);
872 data_tmp = (char *) &crm[1]; 894 data_tmp = (char *) &crm[1];
873 GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp); 895 GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
874 data_tmp += attrs_len; 896 data_tmp += attrs_len;
875 GNUNET_RECLAIM_attestation_list_serialize (attests, data_tmp); 897 GNUNET_RECLAIM_presentation_list_serialize (presentations, data_tmp);
876 GNUNET_MQ_send (cop->client->mq, env); 898 GNUNET_MQ_send (cop->client->mq, env);
877 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head, 899 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
878 cop->client->consume_op_tail, 900 cop->client->consume_op_tail,
@@ -1053,8 +1075,9 @@ handle_attribute_store_message (void *cls,
1053 data_len = ntohs (sam->attr_len); 1075 data_len = ntohs (sam->attr_len);
1054 1076
1055 ash = GNUNET_new (struct AttributeStoreHandle); 1077 ash = GNUNET_new (struct AttributeStoreHandle);
1056 ash->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1], 1078 GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1],
1057 data_len); 1079 data_len,
1080 &ash->claim);
1058 1081
1059 ash->r_id = ntohl (sam->id); 1082 ash->r_id = ntohl (sam->id);
1060 ash->identity = sam->identity; 1083 ash->identity = sam->identity;
@@ -1069,14 +1092,14 @@ handle_attribute_store_message (void *cls,
1069 1092
1070 1093
1071/** 1094/**
1072 * Attestation store result handler 1095 * Credential store result handler
1073 * 1096 *
1074 * @param cls our attribute store handle 1097 * @param cls our attribute store handle
1075 * @param success GNUNET_OK if successful 1098 * @param success GNUNET_OK if successful
1076 * @param emsg error message (NULL if success=GNUNET_OK) 1099 * @param emsg error message (NULL if success=GNUNET_OK)
1077 */ 1100 */
1078static void 1101static void
1079attest_store_cont (void *cls, int32_t success, const char *emsg) 1102cred_store_cont (void *cls, int32_t success, const char *emsg)
1080{ 1103{
1081 struct AttributeStoreHandle *ash = cls; 1104 struct AttributeStoreHandle *ash = cls;
1082 struct GNUNET_MQ_Envelope *env; 1105 struct GNUNET_MQ_Envelope *env;
@@ -1090,7 +1113,7 @@ attest_store_cont (void *cls, int32_t success, const char *emsg)
1090 if (GNUNET_SYSERR == success) 1113 if (GNUNET_SYSERR == success)
1091 { 1114 {
1092 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1093 "Failed to store attestation %s\n", 1116 "Failed to store credential: %s\n",
1094 emsg); 1117 emsg);
1095 cleanup_as_handle (ash); 1118 cleanup_as_handle (ash);
1096 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1119 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
@@ -1107,16 +1130,16 @@ attest_store_cont (void *cls, int32_t success, const char *emsg)
1107 1130
1108 1131
1109/** 1132/**
1110 * Error looking up potential attestation. Abort. 1133 * Error looking up potential credential. Abort.
1111 * 1134 *
1112 * @param cls our attribute store handle 1135 * @param cls our attribute store handle
1113 */ 1136 */
1114static void 1137static void
1115attest_error (void *cls) 1138cred_error (void *cls)
1116{ 1139{
1117 struct AttributeStoreHandle *ash = cls; 1140 struct AttributeStoreHandle *ash = cls;
1118 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1119 "Failed to check for existing Attestation\n"); 1142 "Failed to check for existing credential.\n");
1120 cleanup_as_handle (ash); 1143 cleanup_as_handle (ash);
1121 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1144 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1122 return; 1145 return;
@@ -1124,7 +1147,7 @@ attest_error (void *cls)
1124 1147
1125 1148
1126/** 1149/**
1127* Check for existing record before storing attestation 1150* Check for existing record before storing credential
1128* 1151*
1129* @param cls our attribute store handle 1152* @param cls our attribute store handle
1130* @param zone zone we are iterating 1153* @param zone zone we are iterating
@@ -1133,33 +1156,34 @@ attest_error (void *cls)
1133* @param rd records 1156* @param rd records
1134*/ 1157*/
1135static void 1158static void
1136attest_add_cb (void *cls, 1159cred_add_cb (void *cls,
1137 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1160 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1138 const char *label, 1161 const char *label,
1139 unsigned int rd_count, 1162 unsigned int rd_count,
1140 const struct GNUNET_GNSRECORD_Data *rd) 1163 const struct GNUNET_GNSRECORD_Data *rd)
1141{ 1164{
1142 struct AttributeStoreHandle *ash = cls; 1165 struct AttributeStoreHandle *ash = cls;
1166 struct GNUNET_GNSRECORD_Data rd_new[1];
1143 char *buf; 1167 char *buf;
1144 size_t buf_size; 1168 size_t buf_size;
1145 buf_size = GNUNET_RECLAIM_attestation_serialize_get_size (ash->attest); 1169
1170 buf_size = GNUNET_RECLAIM_credential_serialize_get_size (ash->credential);
1146 buf = GNUNET_malloc (buf_size); 1171 buf = GNUNET_malloc (buf_size);
1147 GNUNET_RECLAIM_attestation_serialize (ash->attest, buf); 1172 GNUNET_RECLAIM_credential_serialize (ash->credential, buf);
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1149 "Storing new Attestation\n"); 1174 "Storing new credential under `%s'.\n",
1150 struct GNUNET_GNSRECORD_Data rd_new[1]; 1175 label);
1151 rd_new[0].data_size = buf_size; 1176 rd_new[0].data_size = buf_size;
1152 rd_new[0].data = buf; 1177 rd_new[0].data = buf;
1153 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION; 1178 rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL;
1154 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 1179 rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1155 rd_new[0].expiration_time = ash->exp.rel_value_us; 1180 rd_new[0].expiration_time = ash->exp.rel_value_us;
1156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1157 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh, 1181 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1158 &ash->identity, 1182 &ash->identity,
1159 label, 1183 label,
1160 1, 1184 1,
1161 rd_new, 1185 rd_new,
1162 &attest_store_cont, 1186 &cred_store_cont,
1163 ash); 1187 ash);
1164 GNUNET_free (buf); 1188 GNUNET_free (buf);
1165 return; 1189 return;
@@ -1167,44 +1191,43 @@ attest_add_cb (void *cls,
1167 1191
1168 1192
1169/** 1193/**
1170 * Add a new attestation 1194 * Add a new credential
1171 * 1195 *
1172 * @param cls the AttributeStoreHandle 1196 * @param cls the AttributeStoreHandle
1173 */ 1197 */
1174static void 1198static void
1175attest_store_task (void *cls) 1199cred_store_task (void *cls)
1176{ 1200{
1177 struct AttributeStoreHandle *ash = cls; 1201 struct AttributeStoreHandle *ash = cls;
1178 char *label; 1202 char *label;
1179 1203
1180 // Give the ash a new id if unset 1204 // Give the ash a new id if unset
1181 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->attest->id)) 1205 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->credential->id))
1182 GNUNET_RECLAIM_id_generate (&ash->attest->id); 1206 GNUNET_RECLAIM_id_generate (&ash->credential->id);
1183 label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id, 1207 label = GNUNET_STRINGS_data_to_string_alloc (&ash->credential->id,
1184 sizeof (ash->attest->id)); 1208 sizeof (ash->credential->id));
1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186 "Looking up existing data under label %s\n", label); 1210 "Looking up existing data under label `%s'\n", label);
1187// Test for the content of the existing ID
1188 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh, 1211 ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1189 &ash->identity, 1212 &ash->identity,
1190 label, 1213 label,
1191 &attest_error, 1214 &cred_error,
1192 ash, 1215 ash,
1193 &attest_add_cb, 1216 &cred_add_cb,
1194 ash); 1217 ash);
1195 GNUNET_free (label); 1218 GNUNET_free (label);
1196} 1219}
1197 1220
1198 1221
1199/** 1222/**
1200 * Check an attestation store message 1223 * Check an credential store message
1201 * 1224 *
1202 * @param cls unused 1225 * @param cls unused
1203 * @param sam the message to check 1226 * @param sam the message to check
1204 */ 1227 */
1205static int 1228static int
1206check_attestation_store_message (void *cls, 1229check_credential_store_message (void *cls,
1207 const struct AttributeStoreMessage *sam) 1230 const struct AttributeStoreMessage *sam)
1208{ 1231{
1209 uint16_t size; 1232 uint16_t size;
1210 1233
@@ -1219,26 +1242,26 @@ check_attestation_store_message (void *cls,
1219 1242
1220 1243
1221/** 1244/**
1222* Handle an attestation store message 1245* Handle a credential store message
1223* 1246*
1224* @param cls our client 1247* @param cls our client
1225* @param sam the message to handle 1248* @param sam the message to handle
1226*/ 1249*/
1227static void 1250static void
1228handle_attestation_store_message (void *cls, 1251handle_credential_store_message (void *cls,
1229 const struct AttributeStoreMessage *sam) 1252 const struct AttributeStoreMessage *sam)
1230{ 1253{
1231 struct AttributeStoreHandle *ash; 1254 struct AttributeStoreHandle *ash;
1232 struct IdpClient *idp = cls; 1255 struct IdpClient *idp = cls;
1233 size_t data_len; 1256 size_t data_len;
1234 1257
1235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n"); 1258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_STORE message\n");
1236 1259
1237 data_len = ntohs (sam->attr_len); 1260 data_len = ntohs (sam->attr_len);
1238 1261
1239 ash = GNUNET_new (struct AttributeStoreHandle); 1262 ash = GNUNET_new (struct AttributeStoreHandle);
1240 ash->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &sam[1], 1263 ash->credential = GNUNET_RECLAIM_credential_deserialize ((char *) &sam[1],
1241 data_len); 1264 data_len);
1242 1265
1243 ash->r_id = ntohl (sam->id); 1266 ash->r_id = ntohl (sam->id);
1244 ash->identity = sam->identity; 1267 ash->identity = sam->identity;
@@ -1248,7 +1271,7 @@ handle_attestation_store_message (void *cls,
1248 GNUNET_SERVICE_client_continue (idp->client); 1271 GNUNET_SERVICE_client_continue (idp->client);
1249 ash->client = idp; 1272 ash->client = idp;
1250 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash); 1273 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1251 GNUNET_SCHEDULER_add_now (&attest_store_task, ash); 1274 GNUNET_SCHEDULER_add_now (&cred_store_task, ash);
1252} 1275}
1253 1276
1254 1277
@@ -1304,12 +1327,12 @@ ticket_iter (void *cls,
1304 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data, 1327 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1305 &adh->claim->id)) 1328 &adh->claim->id))
1306 continue; 1329 continue;
1307 if (adh->attest != NULL) 1330 if (adh->credential != NULL)
1308 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data, 1331 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1309 &adh->attest->id)) 1332 &adh->credential->id))
1310 continue; 1333 continue;
1311 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1312 "Attribute or Attestation to delete found (%s)\n", 1335 "Attribute to delete found (%s)\n",
1313 adh->label); 1336 adh->label);
1314 has_changed = GNUNET_YES; 1337 has_changed = GNUNET_YES;
1315 break; 1338 break;
@@ -1404,10 +1427,10 @@ update_tickets (void *cls)
1404 && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data, 1427 && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1405 &adh->claim->id))) 1428 &adh->claim->id)))
1406 continue; 1429 continue;
1407 if (adh->attest != NULL) 1430 if (adh->credential != NULL)
1408 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type) 1431 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1409 && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data, 1432 && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1410 &adh->attest->id))) 1433 &adh->credential->id)))
1411 continue; 1434 continue;
1412 rd_new[j] = rd[i]; 1435 rd_new[j] = rd[i];
1413 j++; 1436 j++;
@@ -1548,9 +1571,10 @@ handle_attribute_delete_message (void *cls,
1548 data_len = ntohs (dam->attr_len); 1571 data_len = ntohs (dam->attr_len);
1549 1572
1550 adh = GNUNET_new (struct AttributeDeleteHandle); 1573 adh = GNUNET_new (struct AttributeDeleteHandle);
1551 adh->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1], 1574 GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1],
1552 data_len); 1575 data_len,
1553 adh->attest = NULL; 1576 &adh->claim);
1577 adh->credential = NULL;
1554 1578
1555 adh->r_id = ntohl (dam->id); 1579 adh->r_id = ntohl (dam->id);
1556 adh->identity = dam->identity; 1580 adh->identity = dam->identity;
@@ -1571,14 +1595,14 @@ handle_attribute_delete_message (void *cls,
1571 1595
1572 1596
1573/** 1597/**
1574 * Attestation deleted callback 1598 * Credential deleted callback
1575 * 1599 *
1576 * @param cls our handle 1600 * @param cls our handle
1577 * @param success success status 1601 * @param success success status
1578 * @param emsg error message (NULL if success=GNUNET_OK) 1602 * @param emsg error message (NULL if success=GNUNET_OK)
1579 */ 1603 */
1580static void 1604static void
1581attest_delete_cont (void *cls, int32_t success, const char *emsg) 1605cred_delete_cont (void *cls, int32_t success, const char *emsg)
1582{ 1606{
1583 struct AttributeDeleteHandle *adh = cls; 1607 struct AttributeDeleteHandle *adh = cls;
1584 1608
@@ -1586,7 +1610,7 @@ attest_delete_cont (void *cls, int32_t success, const char *emsg)
1586 if (GNUNET_SYSERR == success) 1610 if (GNUNET_SYSERR == success)
1587 { 1611 {
1588 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1612 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1589 "Error deleting attestation %s\n", 1613 "Error deleting credential `%s'\n",
1590 adh->label); 1614 adh->label);
1591 send_delete_response (adh, GNUNET_SYSERR); 1615 send_delete_response (adh, GNUNET_SYSERR);
1592 cleanup_adh (adh); 1616 cleanup_adh (adh);
@@ -1598,14 +1622,14 @@ attest_delete_cont (void *cls, int32_t success, const char *emsg)
1598 1622
1599 1623
1600/** 1624/**
1601 * Check attestation delete message format 1625 * Check credential delete message format
1602 * 1626 *
1603 * @cls unused 1627 * @cls unused
1604 * @dam message to check 1628 * @dam message to check
1605 */ 1629 */
1606static int 1630static int
1607check_attestation_delete_message (void *cls, 1631check_credential_delete_message (void *cls,
1608 const struct AttributeDeleteMessage *dam) 1632 const struct AttributeDeleteMessage *dam)
1609{ 1633{
1610 uint16_t size; 1634 uint16_t size;
1611 1635
@@ -1620,33 +1644,33 @@ check_attestation_delete_message (void *cls,
1620 1644
1621 1645
1622/** 1646/**
1623 * Handle attestation deletion 1647 * Handle credential deletion
1624 * 1648 *
1625 * @param cls our client 1649 * @param cls our client
1626 * @param dam deletion message 1650 * @param dam deletion message
1627 */ 1651 */
1628static void 1652static void
1629handle_attestation_delete_message (void *cls, 1653handle_credential_delete_message (void *cls,
1630 const struct AttributeDeleteMessage *dam) 1654 const struct AttributeDeleteMessage *dam)
1631{ 1655{
1632 struct AttributeDeleteHandle *adh; 1656 struct AttributeDeleteHandle *adh;
1633 struct IdpClient *idp = cls; 1657 struct IdpClient *idp = cls;
1634 size_t data_len; 1658 size_t data_len;
1635 1659
1636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n"); 1660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_DELETE message\n");
1637 1661
1638 data_len = ntohs (dam->attr_len); 1662 data_len = ntohs (dam->attr_len);
1639 1663
1640 adh = GNUNET_new (struct AttributeDeleteHandle); 1664 adh = GNUNET_new (struct AttributeDeleteHandle);
1641 adh->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &dam[1], 1665 adh->credential = GNUNET_RECLAIM_credential_deserialize ((char *) &dam[1],
1642 data_len); 1666 data_len);
1643 adh->claim = NULL; 1667 adh->claim = NULL;
1644 1668
1645 adh->r_id = ntohl (dam->id); 1669 adh->r_id = ntohl (dam->id);
1646 adh->identity = dam->identity; 1670 adh->identity = dam->identity;
1647 adh->label 1671 adh->label
1648 = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id, 1672 = GNUNET_STRINGS_data_to_string_alloc (&adh->credential->id,
1649 sizeof(adh->attest->id)); 1673 sizeof(adh->credential->id));
1650 GNUNET_SERVICE_client_continue (idp->client); 1674 GNUNET_SERVICE_client_continue (idp->client);
1651 adh->client = idp; 1675 adh->client = idp;
1652 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh); 1676 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
@@ -1655,7 +1679,7 @@ handle_attestation_delete_message (void *cls,
1655 adh->label, 1679 adh->label,
1656 0, 1680 0,
1657 NULL, 1681 NULL,
1658 &attest_delete_cont, 1682 &cred_delete_cont,
1659 adh); 1683 adh);
1660} 1684}
1661 1685
@@ -1705,7 +1729,7 @@ attr_iter_error (void *cls)
1705 1729
1706 1730
1707/** 1731/**
1708 * Got record. Return if it is an attribute or attestation. 1732 * Got record. Return if it is an attribute.
1709 * 1733 *
1710 * @param cls our attribute iterator 1734 * @param cls our attribute iterator
1711 * @param zone zone we are iterating 1735 * @param zone zone we are iterating
@@ -1845,51 +1869,51 @@ handle_iteration_next (void *cls,
1845 1869
1846 1870
1847/************************************************* 1871/*************************************************
1848* Attestation iteration 1872* Credential iteration
1849*************************************************/ 1873*************************************************/
1850 1874
1851 1875
1852/** 1876/**
1853 * Done iterating over attestations 1877 * Done iterating over credentials
1854 * 1878 *
1855 * @param cls our iterator handle 1879 * @param cls our iterator handle
1856 */ 1880 */
1857static void 1881static void
1858attest_iter_finished (void *cls) 1882cred_iter_finished (void *cls)
1859{ 1883{
1860 struct Iterator *ai = cls; 1884 struct Iterator *ai = cls;
1861 struct GNUNET_MQ_Envelope *env; 1885 struct GNUNET_MQ_Envelope *env;
1862 struct AttestationResultMessage *arm; 1886 struct CredentialResultMessage *arm;
1863 1887
1864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTESTATION_RESULT message\n"); 1888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CREDENTIAL_RESULT message\n");
1865 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT); 1889 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
1866 arm->id = htonl (ai->request_id); 1890 arm->id = htonl (ai->request_id);
1867 arm->attestation_len = htons (0); 1891 arm->credential_len = htons (0);
1868 GNUNET_MQ_send (ai->client->mq, env); 1892 GNUNET_MQ_send (ai->client->mq, env);
1869 GNUNET_CONTAINER_DLL_remove (ai->client->attest_iter_head, 1893 GNUNET_CONTAINER_DLL_remove (ai->client->cred_iter_head,
1870 ai->client->attest_iter_tail, 1894 ai->client->cred_iter_tail,
1871 ai); 1895 ai);
1872 GNUNET_free (ai); 1896 GNUNET_free (ai);
1873} 1897}
1874 1898
1875 1899
1876/** 1900/**
1877 * Error iterating over attestations. Abort. 1901 * Error iterating over credentials. Abort.
1878 * 1902 *
1879 * @param cls our attribute iteration handle 1903 * @param cls our attribute iteration handle
1880 */ 1904 */
1881static void 1905static void
1882attest_iter_error (void *cls) 1906cred_iter_error (void *cls)
1883{ 1907{
1884 struct Iterator *ai = cls; 1908 struct Iterator *ai = cls;
1885 1909
1886 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attestations\n"); 1910 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over credentials\n");
1887 attest_iter_finished (ai); 1911 cred_iter_finished (ai);
1888} 1912}
1889 1913
1890 1914
1891/** 1915/**
1892 * Got record. Return attestation. 1916 * Got record. Return credential.
1893 * 1917 *
1894 * @param cls our attribute iterator 1918 * @param cls our attribute iterator
1895 * @param zone zone we are iterating 1919 * @param zone zone we are iterating
@@ -1898,32 +1922,32 @@ attest_iter_error (void *cls)
1898 * @param rd records 1922 * @param rd records
1899 */ 1923 */
1900static void 1924static void
1901attest_iter_cb (void *cls, 1925cred_iter_cb (void *cls,
1902 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1926 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1903 const char *label, 1927 const char *label,
1904 unsigned int rd_count, 1928 unsigned int rd_count,
1905 const struct GNUNET_GNSRECORD_Data *rd) 1929 const struct GNUNET_GNSRECORD_Data *rd)
1906{ 1930{
1907 struct Iterator *ai = cls; 1931 struct Iterator *ai = cls;
1908 struct GNUNET_MQ_Envelope *env; 1932 struct GNUNET_MQ_Envelope *env;
1909 struct AttestationResultMessage *arm; 1933 struct CredentialResultMessage *arm;
1910 char *data_tmp; 1934 char *data_tmp;
1911 1935
1912 if ((rd_count != 1) || 1936 if ((rd_count != 1) ||
1913 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd->record_type)) 1937 (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL != rd->record_type))
1914 { 1938 {
1915 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1); 1939 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1916 return; 1940 return;
1917 } 1941 }
1918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n", 1942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found credential under: %s\n",
1919 label); 1943 label);
1920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1921 "Sending ATTESTATION_RESULT message\n"); 1945 "Sending CREDENTIAL_RESULT message\n");
1922 env = GNUNET_MQ_msg_extra (arm, 1946 env = GNUNET_MQ_msg_extra (arm,
1923 rd->data_size, 1947 rd->data_size,
1924 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT); 1948 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
1925 arm->id = htonl (ai->request_id); 1949 arm->id = htonl (ai->request_id);
1926 arm->attestation_len = htons (rd->data_size); 1950 arm->credential_len = htons (rd->data_size);
1927 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity); 1951 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1928 data_tmp = (char *) &arm[1]; 1952 data_tmp = (char *) &arm[1];
1929 GNUNET_memcpy (data_tmp, rd->data, rd->data_size); 1953 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
@@ -1939,29 +1963,29 @@ attest_iter_cb (void *cls,
1939 * @param ais_msg the iteration message to start 1963 * @param ais_msg the iteration message to start
1940 */ 1964 */
1941static void 1965static void
1942handle_attestation_iteration_start (void *cls, 1966handle_credential_iteration_start (void *cls,
1943 const struct 1967 const struct
1944 AttestationIterationStartMessage *ais_msg) 1968 CredentialIterationStartMessage *ais_msg)
1945{ 1969{
1946 struct IdpClient *idp = cls; 1970 struct IdpClient *idp = cls;
1947 struct Iterator *ai; 1971 struct Iterator *ai;
1948 1972
1949 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1950 "Received ATTESTATION_ITERATION_START message\n"); 1974 "Received CREDENTIAL_ITERATION_START message\n");
1951 ai = GNUNET_new (struct Iterator); 1975 ai = GNUNET_new (struct Iterator);
1952 ai->request_id = ntohl (ais_msg->id); 1976 ai->request_id = ntohl (ais_msg->id);
1953 ai->client = idp; 1977 ai->client = idp;
1954 ai->identity = ais_msg->identity; 1978 ai->identity = ais_msg->identity;
1955 1979
1956 GNUNET_CONTAINER_DLL_insert (idp->attest_iter_head, idp->attest_iter_tail, 1980 GNUNET_CONTAINER_DLL_insert (idp->cred_iter_head, idp->cred_iter_tail,
1957 ai); 1981 ai);
1958 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh, 1982 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1959 &ai->identity, 1983 &ai->identity,
1960 &attest_iter_error, 1984 &cred_iter_error,
1961 ai, 1985 ai,
1962 &attest_iter_cb, 1986 &cred_iter_cb,
1963 ai, 1987 ai,
1964 &attest_iter_finished, 1988 &cred_iter_finished,
1965 ai); 1989 ai);
1966 GNUNET_SERVICE_client_continue (idp->client); 1990 GNUNET_SERVICE_client_continue (idp->client);
1967} 1991}
@@ -1974,9 +1998,9 @@ handle_attestation_iteration_start (void *cls,
1974 * @param ais_msg the stop message 1998 * @param ais_msg the stop message
1975 */ 1999 */
1976static void 2000static void
1977handle_attestation_iteration_stop (void *cls, 2001handle_credential_iteration_stop (void *cls,
1978 const struct 2002 const struct
1979 AttestationIterationStopMessage *ais_msg) 2003 CredentialIterationStopMessage *ais_msg)
1980{ 2004{
1981 struct IdpClient *idp = cls; 2005 struct IdpClient *idp = cls;
1982 struct Iterator *ai; 2006 struct Iterator *ai;
@@ -1984,9 +2008,9 @@ handle_attestation_iteration_stop (void *cls,
1984 2008
1985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1986 "Received `%s' message\n", 2010 "Received `%s' message\n",
1987 "ATTESTATION_ITERATION_STOP"); 2011 "CREDENTIAL_ITERATION_STOP");
1988 rid = ntohl (ais_msg->id); 2012 rid = ntohl (ais_msg->id);
1989 for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next) 2013 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
1990 if (ai->request_id == rid) 2014 if (ai->request_id == rid)
1991 break; 2015 break;
1992 if (NULL == ai) 2016 if (NULL == ai)
@@ -1995,7 +2019,7 @@ handle_attestation_iteration_stop (void *cls,
1995 GNUNET_SERVICE_client_drop (idp->client); 2019 GNUNET_SERVICE_client_drop (idp->client);
1996 return; 2020 return;
1997 } 2021 }
1998 GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail, 2022 GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
1999 ai); 2023 ai);
2000 GNUNET_free (ai); 2024 GNUNET_free (ai);
2001 GNUNET_SERVICE_client_continue (idp->client); 2025 GNUNET_SERVICE_client_continue (idp->client);
@@ -2003,24 +2027,24 @@ handle_attestation_iteration_stop (void *cls,
2003 2027
2004 2028
2005/** 2029/**
2006 * Client requests next attestation from iterator 2030 * Client requests next credential from iterator
2007 * 2031 *
2008 * @param cls the client 2032 * @param cls the client
2009 * @param ais_msg the message 2033 * @param ais_msg the message
2010 */ 2034 */
2011static void 2035static void
2012handle_attestation_iteration_next (void *cls, 2036handle_credential_iteration_next (void *cls,
2013 const struct 2037 const struct
2014 AttestationIterationNextMessage *ais_msg) 2038 CredentialIterationNextMessage *ais_msg)
2015{ 2039{
2016 struct IdpClient *idp = cls; 2040 struct IdpClient *idp = cls;
2017 struct Iterator *ai; 2041 struct Iterator *ai;
2018 uint32_t rid; 2042 uint32_t rid;
2019 2043
2020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2021 "Received ATTESTATION_ITERATION_NEXT message\n"); 2045 "Received CREDENTIAL_ITERATION_NEXT message\n");
2022 rid = ntohl (ais_msg->id); 2046 rid = ntohl (ais_msg->id);
2023 for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next) 2047 for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
2024 if (ai->request_id == rid) 2048 if (ai->request_id == rid)
2025 break; 2049 break;
2026 if (NULL == ai) 2050 if (NULL == ai)
@@ -2262,16 +2286,16 @@ GNUNET_SERVICE_MAIN (
2262 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE, 2286 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2263 struct AttributeStoreMessage, 2287 struct AttributeStoreMessage,
2264 NULL), 2288 NULL),
2265 GNUNET_MQ_hd_var_size (attestation_store_message, 2289 GNUNET_MQ_hd_var_size (credential_store_message,
2266 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE, 2290 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE,
2267 struct AttributeStoreMessage, 2291 struct AttributeStoreMessage,
2268 NULL), 2292 NULL),
2269 GNUNET_MQ_hd_var_size (attribute_delete_message, 2293 GNUNET_MQ_hd_var_size (attribute_delete_message,
2270 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE, 2294 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2271 struct AttributeDeleteMessage, 2295 struct AttributeDeleteMessage,
2272 NULL), 2296 NULL),
2273 GNUNET_MQ_hd_var_size (attestation_delete_message, 2297 GNUNET_MQ_hd_var_size (credential_delete_message,
2274 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE, 2298 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE,
2275 struct AttributeDeleteMessage, 2299 struct AttributeDeleteMessage,
2276 NULL), 2300 NULL),
2277 GNUNET_MQ_hd_fixed_size (iteration_start, 2301 GNUNET_MQ_hd_fixed_size (iteration_start,
@@ -2286,17 +2310,17 @@ GNUNET_SERVICE_MAIN (
2286 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP, 2310 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2287 struct AttributeIterationStopMessage, 2311 struct AttributeIterationStopMessage,
2288 NULL), 2312 NULL),
2289 GNUNET_MQ_hd_fixed_size (attestation_iteration_start, 2313 GNUNET_MQ_hd_fixed_size (credential_iteration_start,
2290 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START, 2314 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START,
2291 struct AttestationIterationStartMessage, 2315 struct CredentialIterationStartMessage,
2292 NULL), 2316 NULL),
2293 GNUNET_MQ_hd_fixed_size (attestation_iteration_next, 2317 GNUNET_MQ_hd_fixed_size (credential_iteration_next,
2294 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT, 2318 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT,
2295 struct AttestationIterationNextMessage, 2319 struct CredentialIterationNextMessage,
2296 NULL), 2320 NULL),
2297 GNUNET_MQ_hd_fixed_size (attestation_iteration_stop, 2321 GNUNET_MQ_hd_fixed_size (credential_iteration_stop,
2298 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP, 2322 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP,
2299 struct AttestationIterationStopMessage, 2323 struct CredentialIterationStopMessage,
2300 NULL), 2324 NULL),
2301 2325
2302 GNUNET_MQ_hd_var_size (issue_ticket_message, 2326 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
114 struct GNUNET_RECLAIM_AttributeList *attrs; 114 struct GNUNET_RECLAIM_AttributeList *attrs;
115 115
116 /** 116 /**
117 * Attestations 117 * Presentations
118 */ 118 */
119 struct GNUNET_RECLAIM_AttestationList *attests; 119 struct GNUNET_RECLAIM_PresentationList *presentations;
120 120
121 /** 121 /**
122 * Lookup time 122 * Lookup time
@@ -173,6 +173,11 @@ struct TicketIssueHandle
173 struct GNUNET_RECLAIM_AttributeList *attrs; 173 struct GNUNET_RECLAIM_AttributeList *attrs;
174 174
175 /** 175 /**
176 * Presentations to add
177 */
178 struct GNUNET_RECLAIM_PresentationList *presentations;
179
180 /**
176 * Issuer Key 181 * Issuer Key
177 */ 182 */
178 struct GNUNET_CRYPTO_EcdsaPrivateKey identity; 183 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
@@ -694,8 +699,9 @@ rvk_move_attr_cb (void *cls,
694 { 699 {
695 /** find a new place for this attribute **/ 700 /** find a new place for this attribute **/
696 struct GNUNET_RECLAIM_Attribute *claim; 701 struct GNUNET_RECLAIM_Attribute *claim;
697 claim = GNUNET_RECLAIM_attribute_deserialize (rd[i].data, 702 GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
698 rd[i].data_size); 703 rd[i].data_size,
704 &claim);
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
700 "Attribute to update: Name=%s\n", 706 "Attribute to update: Name=%s\n",
701 claim->name); 707 claim->name);
@@ -714,20 +720,20 @@ rvk_move_attr_cb (void *cls,
714 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label); 720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
715 GNUNET_free (claim); 721 GNUNET_free (claim);
716 } 722 }
717 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION == rd[i].record_type) 723 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
718 { 724 {
719 struct GNUNET_RECLAIM_Attestation *attest; 725 struct GNUNET_RECLAIM_Credential *credential;
720 attest = GNUNET_RECLAIM_attestation_deserialize (rd[i].data, 726 credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
721 rd[i].data_size); 727 rd[i].data_size);
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723 "Attestation to update: Name=%s\n", 729 "Credential to update: Name=%s\n",
724 attest->name); 730 credential->name);
725 attest->id = rvk->move_attr->new_id; 731 credential->id = rvk->move_attr->new_id;
726 new_rd[i].data_size = 732 new_rd[i].data_size =
727 GNUNET_RECLAIM_attestation_serialize_get_size (attest); 733 GNUNET_RECLAIM_credential_serialize_get_size (credential);
728 attr_data = GNUNET_malloc (rd[i].data_size); 734 attr_data = GNUNET_malloc (rd[i].data_size);
729 new_rd[i].data_size = GNUNET_RECLAIM_attestation_serialize (attest, 735 new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential,
730 attr_data); 736 attr_data);
731 new_rd[i].data = attr_data; 737 new_rd[i].data = attr_data;
732 new_rd[i].record_type = rd[i].record_type; 738 new_rd[i].record_type = rd[i].record_type;
733 new_rd[i].flags = rd[i].flags; 739 new_rd[i].flags = rd[i].flags;
@@ -735,9 +741,9 @@ rvk_move_attr_cb (void *cls,
735 new_label = 741 new_label =
736 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, 742 GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
737 sizeof (rvk->move_attr->new_id)); 743 sizeof (rvk->move_attr->new_id));
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation %s\n", 744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n",
739 new_label); 745 new_label);
740 GNUNET_free (attest); 746 GNUNET_free (credential);
741 } 747 }
742 } 748 }
743 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, 749 rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
@@ -980,8 +986,8 @@ cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
980 986
981 if (NULL != cth->attrs) 987 if (NULL != cth->attrs)
982 GNUNET_RECLAIM_attribute_list_destroy (cth->attrs); 988 GNUNET_RECLAIM_attribute_list_destroy (cth->attrs);
983 if (NULL != cth->attests) 989 if (NULL != cth->presentations)
984 GNUNET_RECLAIM_attestation_list_destroy (cth->attests); 990 GNUNET_RECLAIM_presentation_list_destroy (cth->presentations);
985 GNUNET_free (cth); 991 GNUNET_free (cth);
986} 992}
987 993
@@ -1026,40 +1032,20 @@ process_parallel_lookup_result (void *cls,
1026 // REMARK: It is possible now to find rd_count > 1 1032 // REMARK: It is possible now to find rd_count > 1
1027 for (int i = 0; i < rd_count; i++) 1033 for (int i = 0; i < rd_count; i++)
1028 { 1034 {
1029 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type) 1035 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type)
1030 {
1031 attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1032 attr_le->attribute =
1033 GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size);
1034 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1035 cth->attrs->list_tail,
1036 attr_le);
1037 }
1038 else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION == rd[i].record_type)
1039 {
1040 struct GNUNET_RECLAIM_AttestationListEntry *ale;
1041 ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
1042 ale->attestation =
1043 GNUNET_RECLAIM_attestation_deserialize (rd[i].data,
1044 rd[i].data_size);
1045 GNUNET_CONTAINER_DLL_insert (cth->attests->list_head,
1046 cth->attests->list_tail,
1047 ale);
1048 }
1049 else
1050 {
1051 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 "Parallel Lookup of Reference without Attestation");
1053 continue; 1036 continue;
1054 } 1037 attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1055 1038 GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size,
1056 1039 &attr_le->attribute);
1040 GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
1041 cth->attrs->list_tail,
1042 attr_le);
1057 } 1043 }
1058 if (NULL != cth->parallel_lookups_head) 1044 if (NULL != cth->parallel_lookups_head)
1059 return; // Wait for more 1045 return; // Wait for more
1060 /* Else we are done */ 1046 /* Else we are done */
1061 cth->cb (cth->cb_cls, &cth->ticket.identity, 1047 cth->cb (cth->cb_cls, &cth->ticket.identity,
1062 cth->attrs, cth->attests, GNUNET_OK, NULL); 1048 cth->attrs, cth->presentations, GNUNET_OK, NULL);
1063 cleanup_cth (cth); 1049 cleanup_cth (cth);
1064} 1050}
1065 1051
@@ -1109,6 +1095,7 @@ lookup_authz_cb (void *cls,
1109 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls; 1095 struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
1110 struct ParallelLookup *parallel_lookup; 1096 struct ParallelLookup *parallel_lookup;
1111 char *lbl; 1097 char *lbl;
1098 struct GNUNET_RECLAIM_PresentationListEntry *ale;
1112 1099
1113 cth->lookup_request = NULL; 1100 cth->lookup_request = NULL;
1114 1101
@@ -1125,26 +1112,44 @@ lookup_authz_cb (void *cls,
1125 1112
1126 for (int i = 0; i < rd_count; i++) 1113 for (int i = 0; i < rd_count; i++)
1127 { 1114 {
1128 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) && 1115 /**
1129 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF != rd[i].record_type)) 1116 * Check if record is a credential presentation or an attribute
1130 continue; 1117 * reference.
1131 lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size); 1118 */
1132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl); 1119 switch (rd[i].record_type)
1133 parallel_lookup = GNUNET_new (struct ParallelLookup); 1120 {
1134 parallel_lookup->handle = cth; 1121 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
1135 parallel_lookup->label = lbl; 1122 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1136 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get (); 1123 ale->presentation =
1137 parallel_lookup->lookup_request = 1124 GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1138 GNUNET_GNS_lookup (gns, 1125 rd[i].data_size);
1139 lbl, 1126 GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head,
1140 &cth->ticket.identity, 1127 cth->presentations->list_tail,
1141 GNUNET_GNSRECORD_TYPE_ANY, 1128 ale);
1142 GNUNET_GNS_LO_DEFAULT, 1129 break;
1143 &process_parallel_lookup_result, 1130 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
1144 parallel_lookup); 1131 lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
1145 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head, 1132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl);
1146 cth->parallel_lookups_tail, 1133 parallel_lookup = GNUNET_new (struct ParallelLookup);
1147 parallel_lookup); 1134 parallel_lookup->handle = cth;
1135 parallel_lookup->label = lbl;
1136 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
1137 parallel_lookup->lookup_request =
1138 GNUNET_GNS_lookup (gns,
1139 lbl,
1140 &cth->ticket.identity,
1141 GNUNET_GNSRECORD_TYPE_ANY,
1142 GNUNET_GNS_LO_DEFAULT,
1143 &process_parallel_lookup_result,
1144 parallel_lookup);
1145 GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
1146 cth->parallel_lookups_tail,
1147 parallel_lookup);
1148 break;
1149 default:
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151 "Ignoring unknown record type %d", rd[i].record_type);
1152 }
1148 } 1153 }
1149 /** 1154 /**
1150 * We started lookups. Add a timeout task. 1155 * We started lookups. Add a timeout task.
@@ -1162,7 +1167,7 @@ lookup_authz_cb (void *cls,
1162 * No references found, return empty attribute list 1167 * No references found, return empty attribute list
1163 */ 1168 */
1164 cth->cb (cth->cb_cls, &cth->ticket.identity, 1169 cth->cb (cth->cb_cls, &cth->ticket.identity,
1165 cth->attrs, cth->attests, GNUNET_OK, NULL); 1170 cth->attrs, NULL, GNUNET_OK, NULL);
1166 cleanup_cth (cth); 1171 cleanup_cth (cth);
1167} 1172}
1168 1173
@@ -1192,7 +1197,7 @@ RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_EcdsaPrivateKey *id,
1192 cth->identity = *id; 1197 cth->identity = *id;
1193 GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub); 1198 GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
1194 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 1199 cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1195 cth->attests = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); 1200 cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1196 cth->ticket = *ticket; 1201 cth->ticket = *ticket;
1197 cth->cb = cb; 1202 cth->cb = cb;
1198 cth->cb_cls = cb_cls; 1203 cth->cb_cls = cb_cls;
@@ -1230,8 +1235,8 @@ RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
1230 1235
1231 1236
1232/******************************* 1237/*******************************
1233* Ticket issue 1238 * Ticket issue
1234*******************************/ 1239 *******************************/
1235 1240
1236/** 1241/**
1237 * Cleanup ticket consume handle 1242 * Cleanup ticket consume handle
@@ -1264,11 +1269,15 @@ store_ticket_issue_cont (void *cls, int32_t success, const char *emsg)
1264 { 1269 {
1265 handle->cb (handle->cb_cls, 1270 handle->cb (handle->cb_cls,
1266 &handle->ticket, 1271 &handle->ticket,
1272 NULL,
1267 GNUNET_SYSERR, 1273 GNUNET_SYSERR,
1268 "Error storing AuthZ ticket in GNS"); 1274 "Error storing AuthZ ticket in GNS");
1269 return; 1275 return;
1270 } 1276 }
1271 handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL); 1277 handle->cb (handle->cb_cls,
1278 &handle->ticket,
1279 handle->presentations,
1280 GNUNET_OK, NULL);
1272 cleanup_issue_handle (handle); 1281 cleanup_issue_handle (handle);
1273} 1282}
1274 1283
@@ -1284,48 +1293,92 @@ static void
1284issue_ticket (struct TicketIssueHandle *ih) 1293issue_ticket (struct TicketIssueHandle *ih)
1285{ 1294{
1286 struct GNUNET_RECLAIM_AttributeListEntry *le; 1295 struct GNUNET_RECLAIM_AttributeListEntry *le;
1296 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1287 struct GNUNET_GNSRECORD_Data *attrs_record; 1297 struct GNUNET_GNSRECORD_Data *attrs_record;
1288 char *label; 1298 char *label;
1289 int i; 1299 int i;
1300 int j;
1290 int attrs_count = 0; 1301 int attrs_count = 0;
1291 1302
1292 for (le = ih->attrs->list_head; NULL != le; le = le->next) 1303 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1293 attrs_count++; 1304 attrs_count++;
1294 1305
1295 // Worst case we have one attestation per attribute 1306 // Worst case we have one presentation per attribute
1296 attrs_record = 1307 attrs_record =
1297 GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data)); 1308 GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data));
1298 i = 0; 1309 i = 0;
1299 for (le = ih->attrs->list_head; NULL != le; le = le->next) 1310 for (le = ih->attrs->list_head; NULL != le; le = le->next)
1300 { 1311 {
1312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1313 "Adding list entry: %s\n", le->attribute->name);
1314
1301 attrs_record[i].data = &le->attribute->id; 1315 attrs_record[i].data = &le->attribute->id;
1302 attrs_record[i].data_size = sizeof(le->attribute->id); 1316 attrs_record[i].data_size = sizeof(le->attribute->id);
1303 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us; 1317 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1304 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF; 1318 attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF;
1305 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 1319 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1306 i++; 1320 i++;
1307 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation)) 1321 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1308 { 1322 {
1309 int j; 1323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1324 "Attribute is backed by credential. Adding...\n");
1325 struct GNUNET_RECLAIM_Presentation *pres = NULL;
1310 for (j = 0; j < i; j++) 1326 for (j = 0; j < i; j++)
1311 { 1327 {
1312 if (attrs_record[j].record_type 1328 if (attrs_record[j].record_type
1313 != GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF) 1329 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1330 continue;
1331 pres = GNUNET_RECLAIM_presentation_deserialize (attrs_record[j].data,
1332 attrs_record[j].
1333 data_size);
1334 if (NULL == pres)
1335 {
1336 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1337 "Failed to deserialize presentation\n");
1314 continue; 1338 continue;
1315 if (0 == memcmp (attrs_record[j].data, 1339 }
1316 &le->attribute->attestation, 1340 if (0 == memcmp (&pres->credential_id,
1317 sizeof (le->attribute->attestation))) 1341 &le->attribute->credential,
1342 sizeof (le->attribute->credential)))
1318 break; 1343 break;
1344 GNUNET_free (pres);
1345 pres = NULL;
1346 }
1347 if (NULL != pres)
1348 {
1349 GNUNET_free (pres);
1350 continue; // Skip as we have already added this credential presentation.
1351 }
1352 for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next)
1353 {
1354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1355 "Checking presentation....\n");
1356
1357 if (0 != memcmp (&le->attribute->credential,
1358 &ple->presentation->credential_id,
1359 sizeof (le->attribute->credential)))
1360 {
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1362 "Presentation does not match credential ID.\n");
1363 continue;
1364 }
1365 char *pres_buf;
1366 size_t pres_size;
1367 pres_size =
1368 GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation);
1369 pres_buf = GNUNET_malloc (pres_size);
1370 GNUNET_RECLAIM_presentation_serialize (ple->presentation,
1371 pres_buf);
1372 attrs_record[i].data = pres_buf;
1373 attrs_record[i].data_size = pres_size;
1374 attrs_record[i].expiration_time =
1375 ticket_refresh_interval.rel_value_us;
1376 attrs_record[i].record_type =
1377 GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION;
1378 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1379 i++;
1380 break;
1319 } 1381 }
1320 if (j < i)
1321 continue; // Skip as we have already added this attestation.
1322 attrs_record[i].data = &le->attribute->attestation;
1323 attrs_record[i].data_size = sizeof(le->attribute->attestation);
1324 attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
1325 attrs_record[i].record_type =
1326 GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF;
1327 attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1328 i++;
1329 } 1382 }
1330 } 1383 }
1331 attrs_record[i].data = &ih->ticket; 1384 attrs_record[i].data = &ih->ticket;
@@ -1347,14 +1400,23 @@ issue_ticket (struct TicketIssueHandle *ih)
1347 attrs_record, 1400 attrs_record,
1348 &store_ticket_issue_cont, 1401 &store_ticket_issue_cont,
1349 ih); 1402 ih);
1403 for (j = 0; j > i; j++)
1404 {
1405 if (attrs_record[j].record_type
1406 != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
1407 continue;
1408 // Yes, we are allowed to do this because we allocated it above
1409 char *ptr = (char*) attrs_record[j].data;
1410 GNUNET_free (ptr);
1411 }
1350 GNUNET_free (attrs_record); 1412 GNUNET_free (attrs_record);
1351 GNUNET_free (label); 1413 GNUNET_free (label);
1352} 1414}
1353 1415
1354 1416
1355/************************************************* 1417/*************************************************
1356* Ticket iteration (finding a specific ticket) 1418 * Ticket iteration (finding a specific ticket)
1357*************************************************/ 1419 *************************************************/
1358 1420
1359 1421
1360/** 1422/**
@@ -1370,6 +1432,7 @@ filter_tickets_error_cb (void *cls)
1370 tih->ns_it = NULL; 1432 tih->ns_it = NULL;
1371 tih->cb (tih->cb_cls, 1433 tih->cb (tih->cb_cls,
1372 &tih->ticket, 1434 &tih->ticket,
1435 NULL,
1373 GNUNET_SYSERR, 1436 GNUNET_SYSERR,
1374 "Error storing AuthZ ticket in GNS"); 1437 "Error storing AuthZ ticket in GNS");
1375 cleanup_issue_handle (tih); 1438 cleanup_issue_handle (tih);
@@ -1397,22 +1460,25 @@ filter_tickets_cb (void *cls,
1397{ 1460{
1398 struct TicketIssueHandle *tih = cls; 1461 struct TicketIssueHandle *tih = cls;
1399 struct GNUNET_RECLAIM_Ticket *ticket = NULL; 1462 struct GNUNET_RECLAIM_Ticket *ticket = NULL;
1400 1463 struct GNUNET_RECLAIM_Presentation *pres;
1401 // figure out the number of requested attributes 1464 struct GNUNET_RECLAIM_PresentationList *ticket_presentations;
1465 struct GNUNET_RECLAIM_Credential *cred;
1466 struct GNUNET_RECLAIM_PresentationListEntry *ple;
1402 struct GNUNET_RECLAIM_AttributeListEntry *le; 1467 struct GNUNET_RECLAIM_AttributeListEntry *le;
1403 unsigned int attr_cnt = 0; 1468 unsigned int attr_cnt = 0;
1404 unsigned int attest_cnt = 0; 1469 unsigned int pres_cnt = 0;
1405 1470
1406 for (le = tih->attrs->list_head; NULL != le; le = le->next) 1471 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1407 { 1472 {
1408 attr_cnt++; 1473 attr_cnt++;
1409 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation)) 1474 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
1410 attest_cnt++; 1475 pres_cnt++;
1411 } 1476 }
1412 1477
1413 // ticket search 1478 // ticket search
1414 unsigned int found_attrs_cnt = 0; 1479 unsigned int found_attrs_cnt = 0;
1415 unsigned int found_attests_cnt = 0; 1480 unsigned int found_pres_cnt = 0;
1481 ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1416 1482
1417 for (int i = 0; i < rd_count; i++) 1483 for (int i = 0; i < rd_count; i++)
1418 { 1484 {
@@ -1432,20 +1498,75 @@ filter_tickets_cb (void *cls,
1432 } 1498 }
1433 1499
1434 // cmp requested attributes with ticket attributes 1500 // cmp requested attributes with ticket attributes
1435 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) && 1501 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1436 (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF != rd[i].record_type))
1437 continue;
1438 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1439 { 1502 {
1440 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data, 1503 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1441 &le->attribute->id)) 1504 {
1442 found_attrs_cnt++; 1505 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1506 &le->attribute->id))
1507 found_attrs_cnt++;
1508 }
1509 }
1510 if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
1511 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1513 "Found credential...\n");
1514
1515 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1516 {
1517 cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
1518 rd[i].data_size);
1519 if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id,
1520 &le->attribute->credential))
1521 {
1522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1523 "No match.\n");
1524 GNUNET_free (cred);
1525 continue;
1526 }
1527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1528 "Match, creating presentation...\n");
1529 if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation (
1530 cred,
1531 tih->attrs,
1532 &pres))
1533 {
1534 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1535 "Unable to retrieve presentation from credential\n");
1536 GNUNET_free (cred);
1537 continue;
1538 }
1539 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1540 ple->presentation = pres;
1541 GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head,
1542 tih->presentations->list_tail,
1543 ple);
1544 GNUNET_free (cred);
1545 }
1443 } 1546 }
1444 for (le = tih->attrs->list_head; NULL != le; le = le->next) 1547 if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type)
1445 { 1548 {
1446 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data, 1549 for (le = tih->attrs->list_head; NULL != le; le = le->next)
1447 &le->attribute->attestation)) 1550 {
1448 found_attests_cnt++; 1551 pres = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
1552 rd[i].data_size);
1553 if (NULL == pres)
1554 {
1555 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1556 "Failed to deserialize presentation\n");
1557 continue;
1558 }
1559 if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&pres->credential_id,
1560 &le->attribute->credential))
1561 {
1562 found_pres_cnt++;
1563 ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
1564 ple->presentation = pres;
1565 GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head,
1566 ticket_presentations->list_tail,
1567 ple);
1568 }
1569 }
1449 } 1570 }
1450 } 1571 }
1451 1572
@@ -1454,11 +1575,12 @@ filter_tickets_cb (void *cls,
1454 * we are done. 1575 * we are done.
1455 */ 1576 */
1456 if ((attr_cnt == found_attrs_cnt) && 1577 if ((attr_cnt == found_attrs_cnt) &&
1457 (attest_cnt == found_attests_cnt) && 1578 (pres_cnt == found_pres_cnt) &&
1458 (NULL != ticket)) 1579 (NULL != ticket))
1459 { 1580 {
1460 GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it); 1581 GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it);
1461 tih->cb (tih->cb_cls, &tih->ticket, GNUNET_OK, NULL); 1582 tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL);
1583 GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
1462 cleanup_issue_handle (tih); 1584 cleanup_issue_handle (tih);
1463 return; 1585 return;
1464 } 1586 }
@@ -1510,6 +1632,7 @@ RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1510 tih->cb = cb; 1632 tih->cb = cb;
1511 tih->cb_cls = cb_cls; 1633 tih->cb_cls = cb_cls;
1512 tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs); 1634 tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs);
1635 tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
1513 tih->identity = *identity; 1636 tih->identity = *identity;
1514 tih->ticket.audience = *audience; 1637 tih->ticket.audience = *audience;
1515 1638
@@ -1527,8 +1650,8 @@ RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1527 1650
1528 1651
1529/************************************ 1652/************************************
1530* Ticket iteration 1653 * Ticket iteration
1531************************************/ 1654 ************************************/
1532 1655
1533/** 1656/**
1534 * Cleanup ticket iterator 1657 * 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) (
113 * 113 *
114 * @param cls closure 114 * @param cls closure
115 * @param ticket the ticket 115 * @param ticket the ticket
116 * @param presentations new presentations for ticket (NULL on error)
116 * @param success #GNUNET_SYSERR on failure (including timeout/queue 117 * @param success #GNUNET_SYSERR on failure (including timeout/queue
117 * drop/failure to validate) #GNUNET_OK on success 118 * drop/failure to validate) #GNUNET_OK on success
118 * @param emsg NULL on success, otherwise an error message 119 * @param emsg NULL on success, otherwise an error message
@@ -120,6 +121,7 @@ typedef void (*RECLAIM_TICKETS_TicketIter) (
120typedef void (*RECLAIM_TICKETS_TicketResult) ( 121typedef void (*RECLAIM_TICKETS_TicketResult) (
121 void *cls, 122 void *cls,
122 struct GNUNET_RECLAIM_Ticket *ticket, 123 struct GNUNET_RECLAIM_Ticket *ticket,
124 struct GNUNET_RECLAIM_PresentationList *presentations,
123 int32_t success, 125 int32_t success,
124 const char *emsg); 126 const char *emsg);
125 127
@@ -129,7 +131,8 @@ typedef void (*RECLAIM_TICKETS_TicketResult) (
129 * 131 *
130 * @param cls closure 132 * @param cls closure
131 * @param identity the issuer of the ticket/attributes 133 * @param identity the issuer of the ticket/attributes
132 * @param l attribute list retrieved through ticket 134 * @param attributes attribute list retrieved through ticket
135 * @param presentations attribute presentations (may be NULL)
133 * @param success GNUNET_OK on success 136 * @param success GNUNET_OK on success
134 * @param emsg error message (NULL on success) 137 * @param emsg error message (NULL on success)
135 */ 138 */
@@ -137,7 +140,7 @@ typedef void (*RECLAIM_TICKETS_ConsumeCallback) (
137 void *cls, 140 void *cls,
138 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 141 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
139 const struct GNUNET_RECLAIM_AttributeList *attributes, 142 const struct GNUNET_RECLAIM_AttributeList *attributes,
140 const struct GNUNET_RECLAIM_AttestationList *attestations, 143 const struct GNUNET_RECLAIM_PresentationList *presentations,
141 int32_t success, 144 int32_t success,
142 const char *emsg); 145 const char *emsg);
143 146
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)
46 const char *val_str = NULL; 46 const char *val_str = NULL;
47 const char *type_str = NULL; 47 const char *type_str = NULL;
48 const char *id_str = NULL; 48 const char *id_str = NULL;
49 const char *attest_str = NULL; 49 const char *cred_str = NULL;
50 const char *flag_str = NULL; 50 const char *flag_str = NULL;
51 char *data; 51 char *data;
52 int unpack_state; 52 int unpack_state;
@@ -68,8 +68,8 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
68 &name_str, 68 &name_str,
69 "id", 69 "id",
70 &id_str, 70 &id_str,
71 "attestation", 71 "credential",
72 &attest_str, 72 &cred_str,
73 "type", 73 "type",
74 &type_str, 74 &type_str,
75 "value", 75 "value",
@@ -95,12 +95,12 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
95 } 95 }
96 attr = GNUNET_RECLAIM_attribute_new (name_str, NULL, 96 attr = GNUNET_RECLAIM_attribute_new (name_str, NULL,
97 type, data, data_size); 97 type, data, data_size);
98 if ((NULL != attest_str) && (0 != strlen (attest_str))) 98 if ((NULL != cred_str) && (0 != strlen (cred_str)))
99 { 99 {
100 GNUNET_STRINGS_string_to_data (attest_str, 100 GNUNET_STRINGS_string_to_data (cred_str,
101 strlen (attest_str), 101 strlen (cred_str),
102 &attr->attestation, 102 &attr->credential,
103 sizeof(attr->attestation)); 103 sizeof(attr->credential));
104 } 104 }
105 if ((NULL == id_str) || (0 == strlen (id_str))) 105 if ((NULL == id_str) || (0 == strlen (id_str)))
106 memset (&attr->id, 0, sizeof (attr->id)); 106 memset (&attr->id, 0, sizeof (attr->id));
@@ -142,7 +142,7 @@ clean_attr (void *cls, struct GNUNET_JSON_Specification *spec)
142 * @return JSON Specification 142 * @return JSON Specification
143 */ 143 */
144struct GNUNET_JSON_Specification 144struct GNUNET_JSON_Specification
145GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_Attribute **attr) 145GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr)
146{ 146{
147 struct GNUNET_JSON_Specification ret = { .parser = &parse_attr, 147 struct GNUNET_JSON_Specification ret = { .parser = &parse_attr,
148 .cleaner = &clean_attr, 148 .cleaner = &clean_attr,
@@ -279,7 +279,7 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
279 279
280 280
281/** 281/**
282 * Parse given JSON object to an attestation claim 282 * Parse given JSON object to a credential claim
283 * 283 *
284 * @param cls closure, NULL 284 * @param cls closure, NULL
285 * @param root the json object representing data 285 * @param root the json object representing data
@@ -287,9 +287,9 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
287 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 287 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
288 */ 288 */
289static int 289static int
290parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) 290parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
291{ 291{
292 struct GNUNET_RECLAIM_Attestation *attr; 292 struct GNUNET_RECLAIM_Credential *cred;
293 const char *name_str = NULL; 293 const char *name_str = NULL;
294 const char *val_str = NULL; 294 const char *val_str = NULL;
295 const char *type_str = NULL; 295 const char *type_str = NULL;
@@ -325,26 +325,26 @@ parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
325 "Error json object has a wrong format!\n"); 325 "Error json object has a wrong format!\n");
326 return GNUNET_SYSERR; 326 return GNUNET_SYSERR;
327 } 327 }
328 type = GNUNET_RECLAIM_attestation_typename_to_number (type_str); 328 type = GNUNET_RECLAIM_credential_typename_to_number (type_str);
329 if (GNUNET_SYSERR == 329 if (GNUNET_SYSERR ==
330 (GNUNET_RECLAIM_attestation_string_to_value (type, 330 (GNUNET_RECLAIM_credential_string_to_value (type,
331 val_str, 331 val_str,
332 (void **) &data, 332 (void **) &data,
333 &data_size))) 333 &data_size)))
334 { 334 {
335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attestation value invalid!\n"); 335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Credential value invalid!\n");
336 return GNUNET_SYSERR; 336 return GNUNET_SYSERR;
337 } 337 }
338 attr = GNUNET_RECLAIM_attestation_new (name_str, type, data, data_size); 338 cred = GNUNET_RECLAIM_credential_new (name_str, type, data, data_size);
339 if ((NULL == id_str) || (0 == strlen (id_str))) 339 if ((NULL == id_str) || (0 == strlen (id_str)))
340 memset (&attr->id, 0, sizeof (attr->id)); 340 memset (&cred->id, 0, sizeof (cred->id));
341 else 341 else
342 GNUNET_STRINGS_string_to_data (id_str, 342 GNUNET_STRINGS_string_to_data (id_str,
343 strlen (id_str), 343 strlen (id_str),
344 &attr->id, 344 &cred->id,
345 sizeof(attr->id)); 345 sizeof(cred->id));
346 346
347 *(struct GNUNET_RECLAIM_Attestation **) spec->ptr = attr; 347 *(struct GNUNET_RECLAIM_Credential **) spec->ptr = cred;
348 return GNUNET_OK; 348 return GNUNET_OK;
349} 349}
350 350
@@ -356,11 +356,11 @@ parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
356 * @param[out] spec where to free the data 356 * @param[out] spec where to free the data
357 */ 357 */
358static void 358static void
359clean_attest (void *cls, struct GNUNET_JSON_Specification *spec) 359clean_credential (void *cls, struct GNUNET_JSON_Specification *spec)
360{ 360{
361 struct GNUNET_RECLAIM_Attestation **attr; 361 struct GNUNET_RECLAIM_Credential **attr;
362 362
363 attr = (struct GNUNET_RECLAIM_Attestation **) spec->ptr; 363 attr = (struct GNUNET_RECLAIM_Credential **) spec->ptr;
364 if (NULL != *attr) 364 if (NULL != *attr)
365 { 365 {
366 GNUNET_free (*attr); 366 GNUNET_free (*attr);
@@ -370,23 +370,23 @@ clean_attest (void *cls, struct GNUNET_JSON_Specification *spec)
370 370
371 371
372/** 372/**
373 * JSON Specification for Reclaim attestation claims. 373 * JSON Specification for credential claims.
374 * 374 *
375 * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill 375 * @param attr struct of GNUNET_RECLAIM_Credential to fill
376 * @return JSON Specification 376 * @return JSON Specification
377 */ 377 */
378struct GNUNET_JSON_Specification 378struct GNUNET_JSON_Specification
379GNUNET_RECLAIM_JSON_spec_claim_attest (struct 379GNUNET_RECLAIM_JSON_spec_credential (struct
380 GNUNET_RECLAIM_Attestation **attr) 380 GNUNET_RECLAIM_Credential **cred)
381{ 381{
382 struct GNUNET_JSON_Specification ret = { .parser = &parse_attest, 382 struct GNUNET_JSON_Specification ret = { .parser = &parse_credential,
383 .cleaner = &clean_attest, 383 .cleaner = &clean_credential,
384 .cls = NULL, 384 .cls = NULL,
385 .field = NULL, 385 .field = NULL,
386 .ptr = attr, 386 .ptr = cred,
387 .ptr_size = 0, 387 .ptr_size = 0,
388 .size_ptr = NULL }; 388 .size_ptr = NULL };
389 389
390 *attr = NULL; 390 *cred = NULL;
391 return ret; 391 return ret;
392} 392}
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 @@
32/** 32/**
33 * JSON Specification for Reclaim claims. 33 * JSON Specification for Reclaim claims.
34 * 34 *
35 * @param ticket struct of GNUNET_RECLAIM_ATTRIBUTE_Claim to fill 35 * @param attr struct of GNUNET_RECLAIM_Attribute to fill
36 * @return JSON Specification 36 * @return JSON Specification
37 */ 37 */
38struct GNUNET_JSON_Specification 38struct GNUNET_JSON_Specification
39GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_Attribute **attr); 39GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr);
40 40
41/** 41/**
42 * JSON Specification for Reclaim tickets. 42 * JSON Specification for Reclaim tickets.
@@ -48,11 +48,10 @@ struct GNUNET_JSON_Specification
48GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket); 48GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket);
49 49
50/** 50/**
51 * JSON Specification for Reclaim attestation claims. 51 * JSON Specification for credentials.
52 * 52 *
53 * @param ticket struct of GNUNET_RECLAIM_Attestation to fill 53 * @param cred struct of GNUNET_RECLAIM_Credential to fill
54 * @return JSON Specification 54 * @return JSON Specification
55 */ 55 */
56struct GNUNET_JSON_Specification 56struct GNUNET_JSON_Specification
57GNUNET_RECLAIM_JSON_spec_claim_attest (struct 57GNUNET_RECLAIM_JSON_spec_credential (struct GNUNET_RECLAIM_Credential **cred);
58 GNUNET_RECLAIM_Attestation **attr);
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
62 uint32_t attr_list_len GNUNET_PACKED; 62 uint32_t attr_list_len GNUNET_PACKED;
63 63
64 /** 64 /**
65 * The length of the attestation list 65 * The length of the presentation list
66 */ 66 */
67 uint32_t attest_list_len GNUNET_PACKED; 67 uint32_t pres_list_len GNUNET_PACKED;
68}; 68};
69 69
70GNUNET_NETWORK_STRUCT_END 70GNUNET_NETWORK_STRUCT_END
@@ -156,25 +156,25 @@ fix_base64 (char *str)
156 156
157static json_t* 157static json_t*
158generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 158generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
159 struct GNUNET_RECLAIM_AttributeList *attrs, 159 const struct GNUNET_RECLAIM_AttributeList *attrs,
160 struct GNUNET_RECLAIM_AttestationList *attests) 160 const struct GNUNET_RECLAIM_PresentationList *presentations)
161{ 161{
162 struct GNUNET_RECLAIM_AttributeListEntry *le; 162 struct GNUNET_RECLAIM_AttributeListEntry *le;
163 struct GNUNET_RECLAIM_AttestationListEntry *ale; 163 struct GNUNET_RECLAIM_PresentationListEntry *ple;
164 char *subject; 164 char *subject;
165 char *source_name; 165 char *source_name;
166 char *attr_val_str; 166 char *attr_val_str;
167 char *attest_val_str; 167 char *pres_val_str;
168 json_t *body; 168 json_t *body;
169 json_t *aggr_names; 169 json_t *aggr_names;
170 json_t *aggr_sources; 170 json_t *aggr_sources;
171 json_t *aggr_sources_jwt; 171 json_t *aggr_sources_jwt;
172 json_t *addr_claim = NULL; 172 json_t *addr_claim = NULL;
173 int num_attestations = 0; 173 int num_presentations = 0;
174 for (le = attrs->list_head; NULL != le; le = le->next) 174 for (le = attrs->list_head; NULL != le; le = le->next)
175 { 175 {
176 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation)) 176 if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
177 num_attestations++; 177 num_presentations++;
178 } 178 }
179 179
180 subject = 180 subject =
@@ -191,23 +191,25 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
191 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS)); 191 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
192 // sub REQUIRED public key identity, not exceed 255 ASCII length 192 // sub REQUIRED public key identity, not exceed 255 ASCII length
193 json_object_set_new (body, "sub", json_string (subject)); 193 json_object_set_new (body, "sub", json_string (subject));
194 attest_val_str = NULL; 194 pres_val_str = NULL;
195 source_name = NULL; 195 source_name = NULL;
196 int i = 0; 196 int i = 0;
197 for (ale = attests->list_head; NULL != ale; ale = ale->next) 197 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
198 { 198 {
199 // New Attestation 199 // New presentation
200 GNUNET_asprintf (&source_name, 200 GNUNET_asprintf (&source_name,
201 "src%d", 201 "src%d",
202 i); 202 i);
203 aggr_sources_jwt = json_object (); 203 aggr_sources_jwt = json_object ();
204 attest_val_str = 204 pres_val_str =
205 GNUNET_RECLAIM_attestation_value_to_string (ale->attestation->type, 205 GNUNET_RECLAIM_presentation_value_to_string (ple->presentation->type,
206 ale->attestation->data, 206 ple->presentation->data,
207 ale->attestation->data_size); 207 ple->presentation->data_size);
208 json_object_set_new (aggr_sources_jwt, "JWT", 208 json_object_set_new (aggr_sources_jwt,
209 json_string (attest_val_str) ); 209 GNUNET_RECLAIM_presentation_number_to_typename (ple->presentation->type),
210 json_string (pres_val_str) );
210 json_object_set_new (aggr_sources, source_name, aggr_sources_jwt); 211 json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
212 GNUNET_free (pres_val_str);
211 GNUNET_free (source_name); 213 GNUNET_free (source_name);
212 source_name = NULL; 214 source_name = NULL;
213 i++; 215 i++;
@@ -216,7 +218,7 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
216 for (le = attrs->list_head; NULL != le; le = le->next) 218 for (le = attrs->list_head; NULL != le; le = le->next)
217 { 219 {
218 220
219 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation)) 221 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
220 { 222 {
221 223
222 attr_val_str = 224 attr_val_str =
@@ -247,18 +249,24 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
247 } 249 }
248 else 250 else
249 { 251 {
250 // Check if attest is there 252 // Check if presentation is there
251 int j = 0; 253 int j = 0;
252 for (ale = attests->list_head; NULL != ale; ale = ale->next) 254 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
253 { 255 {
254 if (GNUNET_YES == 256 if (GNUNET_YES ==
255 GNUNET_RECLAIM_id_is_equal (&ale->attestation->id, 257 GNUNET_RECLAIM_id_is_equal (&ple->presentation->credential_id,
256 &le->attribute->attestation)) 258 &le->attribute->credential))
257 break; 259 break;
258 j++; 260 j++;
259 } 261 }
260 GNUNET_assert (NULL != ale); 262 if (NULL == ple)
261 // Attestation is existing, hence take the respective source str 263 {
264 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
265 "Presentation for `%s' missing...\n",
266 le->attribute->name);
267 continue;
268 }
269 // Presentation exists, hence take the respective source str
262 GNUNET_asprintf (&source_name, 270 GNUNET_asprintf (&source_name,
263 "src%d", 271 "src%d",
264 j); 272 j);
@@ -269,9 +277,6 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
269 } 277 }
270 if (NULL != addr_claim) 278 if (NULL != addr_claim)
271 json_object_set_new (body, "address", addr_claim); 279 json_object_set_new (body, "address", addr_claim);
272
273 if (NULL != attest_val_str)
274 GNUNET_free (attest_val_str);
275 if (0 != i) 280 if (0 != i)
276 { 281 {
277 json_object_set_new (body, "_claim_names", aggr_names); 282 json_object_set_new (body, "_claim_names", aggr_names);
@@ -286,18 +291,18 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
286 * 291 *
287 * @param sub_key the subject (user) 292 * @param sub_key the subject (user)
288 * @param attrs user attribute list 293 * @param attrs user attribute list
289 * @param attests user attribute attestation list (may be empty) 294 * @param presentations credential presentation list (may be empty)
290 * @return Userinfo JSON 295 * @return Userinfo JSON
291 */ 296 */
292char * 297char *
293OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 298OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
294 struct GNUNET_RECLAIM_AttributeList *attrs, 299 const struct GNUNET_RECLAIM_AttributeList *attrs,
295 struct GNUNET_RECLAIM_AttestationList *attests) 300 const struct GNUNET_RECLAIM_PresentationList *presentations)
296{ 301{
297 char *body_str; 302 char *body_str;
298 json_t* body = generate_userinfo_json (sub_key, 303 json_t* body = generate_userinfo_json (sub_key,
299 attrs, 304 attrs,
300 attests); 305 presentations);
301 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT); 306 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
302 json_decref (body); 307 json_decref (body);
303 return body_str; 308 return body_str;
@@ -310,6 +315,7 @@ OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
310 * @param aud_key the public of the audience 315 * @param aud_key the public of the audience
311 * @param sub_key the public key of the subject 316 * @param sub_key the public key of the subject
312 * @param attrs the attribute list 317 * @param attrs the attribute list
318 * @param presentations credential presentation list (may be empty)
313 * @param expiration_time the validity of the token 319 * @param expiration_time the validity of the token
314 * @param secret_key the key used to sign the JWT 320 * @param secret_key the key used to sign the JWT
315 * @return a new base64-encoded JWT string. 321 * @return a new base64-encoded JWT string.
@@ -317,8 +323,8 @@ OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
317char * 323char *
318OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 324OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
319 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 325 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
320 struct GNUNET_RECLAIM_AttributeList *attrs, 326 const struct GNUNET_RECLAIM_AttributeList *attrs,
321 struct GNUNET_RECLAIM_AttestationList *attests, 327 const struct GNUNET_RECLAIM_PresentationList *presentations,
322 const struct GNUNET_TIME_Relative *expiration_time, 328 const struct GNUNET_TIME_Relative *expiration_time,
323 const char *nonce, 329 const char *nonce,
324 const char *secret_key) 330 const char *secret_key)
@@ -339,7 +345,7 @@ OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
339 345
340 body = generate_userinfo_json (sub_key, 346 body = generate_userinfo_json (sub_key,
341 attrs, 347 attrs,
342 attests); 348 presentations);
343 // iat REQUIRED time now 349 // iat REQUIRED time now
344 time_now = GNUNET_TIME_absolute_get (); 350 time_now = GNUNET_TIME_absolute_get ();
345 // exp REQUIRED time expired from config 351 // exp REQUIRED time expired from config
@@ -426,6 +432,7 @@ OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
426 * @param issuer the issuer of the ticket, used to sign the ticket and nonce 432 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
427 * @param ticket the ticket to include in the code 433 * @param ticket the ticket to include in the code
428 * @param attrs list of attributes which are shared 434 * @param attrs list of attributes which are shared
435 * @param presentations credential presentation list (may be empty)
429 * @param nonce the nonce to include in the code 436 * @param nonce the nonce to include in the code
430 * @param code_challenge PKCE code challenge 437 * @param code_challenge PKCE code challenge
431 * @return a new authorization code (caller must free) 438 * @return a new authorization code (caller must free)
@@ -433,8 +440,8 @@ OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
433char * 440char *
434OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, 441OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
435 const struct GNUNET_RECLAIM_Ticket *ticket, 442 const struct GNUNET_RECLAIM_Ticket *ticket,
436 struct GNUNET_RECLAIM_AttributeList *attrs, 443 const struct GNUNET_RECLAIM_AttributeList *attrs,
437 struct GNUNET_RECLAIM_AttestationList *attests, 444 const struct GNUNET_RECLAIM_PresentationList *presentations,
438 const char *nonce_str, 445 const char *nonce_str,
439 const char *code_challenge) 446 const char *code_challenge)
440{ 447{
@@ -447,7 +454,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
447 size_t payload_len; 454 size_t payload_len;
448 size_t code_payload_len; 455 size_t code_payload_len;
449 size_t attr_list_len = 0; 456 size_t attr_list_len = 0;
450 size_t attests_list_len = 0; 457 size_t pres_list_len = 0;
451 size_t code_challenge_len = 0; 458 size_t code_challenge_len = 0;
452 uint32_t nonce_len = 0; 459 uint32_t nonce_len = 0;
453 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 460 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
@@ -481,17 +488,17 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
481 // Get serialized attributes 488 // Get serialized attributes
482 payload_len += attr_list_len; 489 payload_len += attr_list_len;
483 } 490 }
484 if (NULL != attests) 491 if (NULL != presentations)
485 { 492 {
486 // Get length 493 // Get length
487 attests_list_len = 494 pres_list_len =
488 GNUNET_RECLAIM_attestation_list_serialize_get_size (attests); 495 GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
489 params.attest_list_len = htonl (attests_list_len); 496 params.pres_list_len = htonl (pres_list_len);
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "Length of serialized attestations: %lu\n", 498 "Length of serialized presentations: %lu\n",
492 attests_list_len); 499 pres_list_len);
493 // Get serialized attributes 500 // Get serialized attributes
494 payload_len += attests_list_len; 501 payload_len += pres_list_len;
495 } 502 }
496 503
497 // Get plaintext length 504 // Get plaintext length
@@ -510,8 +517,8 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
510 } 517 }
511 if (0 < attr_list_len) 518 if (0 < attr_list_len)
512 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp); 519 GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp);
513 if (0 < attests_list_len) 520 if (0 < pres_list_len)
514 GNUNET_RECLAIM_attestation_list_serialize (attests, tmp); 521 GNUNET_RECLAIM_presentation_list_serialize (presentations, tmp);
515 522
516 /** END **/ 523 /** END **/
517 524
@@ -564,7 +571,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
564 * if used in request. 571 * if used in request.
565 * @param ticket where to store the ticket 572 * @param ticket where to store the ticket
566 * @param attrs the attributes in the code 573 * @param attrs the attributes in the code
567 * @param attests the attestations in the code (if any) 574 * @param presentations credential presentation list
568 * @param nonce_str where to store the nonce (if contained) 575 * @param nonce_str where to store the nonce (if contained)
569 * @return GNUNET_OK if successful, else GNUNET_SYSERR 576 * @return GNUNET_OK if successful, else GNUNET_SYSERR
570 */ 577 */
@@ -574,14 +581,14 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
574 const char *code_verifier, 581 const char *code_verifier,
575 struct GNUNET_RECLAIM_Ticket *ticket, 582 struct GNUNET_RECLAIM_Ticket *ticket,
576 struct GNUNET_RECLAIM_AttributeList **attrs, 583 struct GNUNET_RECLAIM_AttributeList **attrs,
577 struct GNUNET_RECLAIM_AttestationList **attests, 584 struct GNUNET_RECLAIM_PresentationList **presentations,
578 char **nonce_str) 585 char **nonce_str)
579{ 586{
580 char *code_payload; 587 char *code_payload;
581 char *ptr; 588 char *ptr;
582 char *plaintext; 589 char *plaintext;
583 char *attrs_ser; 590 char *attrs_ser;
584 char *attests_ser; 591 char *presentations_ser;
585 char *expected_code_challenge; 592 char *expected_code_challenge;
586 char *code_challenge; 593 char *code_challenge;
587 char *code_verifier_hash; 594 char *code_verifier_hash;
@@ -589,7 +596,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
589 struct GNUNET_CRYPTO_EcdsaSignature *signature; 596 struct GNUNET_CRYPTO_EcdsaSignature *signature;
590 uint32_t code_challenge_len; 597 uint32_t code_challenge_len;
591 uint32_t attrs_ser_len; 598 uint32_t attrs_ser_len;
592 uint32_t attests_ser_len; 599 uint32_t pres_ser_len;
593 size_t plaintext_len; 600 size_t plaintext_len;
594 size_t code_payload_len; 601 size_t code_payload_len;
595 uint32_t nonce_len = 0; 602 uint32_t nonce_len = 0;
@@ -621,6 +628,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
621 628
622 // cmp code_challenge code_verifier 629 // cmp code_challenge code_verifier
623 code_challenge_len = ntohl (params->code_challenge_len); 630 code_challenge_len = ntohl (params->code_challenge_len);
631 code_challenge = ((char *) &params[1]);
624 if (0 != code_challenge_len) /* Only check if this code requires a CV */ 632 if (0 != code_challenge_len) /* Only check if this code requires a CV */
625 { 633 {
626 if (NULL == code_verifier) 634 if (NULL == code_verifier)
@@ -639,7 +647,6 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
639 // encode code verifier 647 // encode code verifier
640 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8, 648 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
641 &expected_code_challenge); 649 &expected_code_challenge);
642 code_challenge = ((char *) &params[1]);
643 GNUNET_free (code_verifier_hash); 650 GNUNET_free (code_verifier_hash);
644 if (0 != 651 if (0 !=
645 strncmp (expected_code_challenge, code_challenge, code_challenge_len)) 652 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
@@ -692,10 +699,11 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
692 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len; 699 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
693 attrs_ser_len = ntohl (params->attr_list_len); 700 attrs_ser_len = ntohl (params->attr_list_len);
694 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len); 701 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
695 attests_ser = ((char*) attrs_ser) + attrs_ser_len; 702 presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
696 attests_ser_len = ntohl (params->attest_list_len); 703 pres_ser_len = ntohl (params->pres_list_len);
697 *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser, 704 *presentations =
698 attests_ser_len); 705 GNUNET_RECLAIM_presentation_list_deserialize (presentations_ser,
706 pres_ser_len);
699 707
700 GNUNET_free (code_payload); 708 GNUNET_free (code_payload);
701 return GNUNET_OK; 709 return GNUNET_OK;
@@ -769,7 +777,7 @@ OIDC_access_token_parse (const char *token,
769 777
770/** 778/**
771 * Checks if a claim is implicitly requested through standard 779 * Checks if a claim is implicitly requested through standard
772 * scope(s) 780 * scope(s) or explicitly through non-standard scope.
773 * 781 *
774 * @param scopes the scopes which have been requested 782 * @param scopes the scopes which have been requested
775 * @param attr the attribute name to check 783 * @param attr the attribute name to check
@@ -832,6 +840,11 @@ OIDC_check_scopes_for_claim_request (const char*scopes,
832 } 840 }
833 } 841 }
834 842
843 } else if (0 == strcmp (attr, scope_variable))
844 {
845 /** attribute matches requested scope **/
846 GNUNET_free (scope_variables);
847 return GNUNET_YES;
835 } 848 }
836 scope_variable = strtok (NULL, delimiter); 849 scope_variable = strtok (NULL, delimiter);
837 } 850 }
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 @@
44 * @param aud_key the public of the audience 44 * @param aud_key the public of the audience
45 * @param sub_key the public key of the subject 45 * @param sub_key the public key of the subject
46 * @param attrs the attribute list 46 * @param attrs the attribute list
47 * @param presentations credential presentation list (may be empty)
47 * @param expiration_time the validity of the token 48 * @param expiration_time the validity of the token
48 * @param secret_key the key used to sign the JWT 49 * @param secret_key the key used to sign the JWT
49 * @return a new base64-encoded JWT string. 50 * @return a new base64-encoded JWT string.
@@ -51,8 +52,8 @@
51char* 52char*
52OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, 53OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
53 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 54 const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
54 struct GNUNET_RECLAIM_AttributeList *attrs, 55 const struct GNUNET_RECLAIM_AttributeList *attrs,
55 struct GNUNET_RECLAIM_AttestationList *attests, 56 const struct GNUNET_RECLAIM_PresentationList *presentations,
56 const struct GNUNET_TIME_Relative *expiration_time, 57 const struct GNUNET_TIME_Relative *expiration_time,
57 const char *nonce, 58 const char *nonce,
58 const char *secret_key); 59 const char *secret_key);
@@ -64,6 +65,7 @@ OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
64 * @param issuer the issuer of the ticket, used to sign the ticket and nonce 65 * @param issuer the issuer of the ticket, used to sign the ticket and nonce
65 * @param ticket the ticket to include in the code 66 * @param ticket the ticket to include in the code
66 * @param attrs list of attributes to share 67 * @param attrs list of attributes to share
68 * @param presentations credential presentation list
67 * @param nonce the nonce to include in the code 69 * @param nonce the nonce to include in the code
68 * @param code_challenge PKCE code challenge 70 * @param code_challenge PKCE code challenge
69 * @return a new authorization code (caller must free) 71 * @return a new authorization code (caller must free)
@@ -71,8 +73,8 @@ OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
71char* 73char*
72OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, 74OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
73 const struct GNUNET_RECLAIM_Ticket *ticket, 75 const struct GNUNET_RECLAIM_Ticket *ticket,
74 struct GNUNET_RECLAIM_AttributeList *attrs, 76 const struct GNUNET_RECLAIM_AttributeList *attrs,
75 struct GNUNET_RECLAIM_AttestationList *attests, 77 const struct GNUNET_RECLAIM_PresentationList *presentations,
76 const char *nonce, 78 const char *nonce,
77 const char *code_challenge); 79 const char *code_challenge);
78 80
@@ -86,6 +88,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
86 * @param code_verfier PKCE code verifier 88 * @param code_verfier PKCE code verifier
87 * @param ticket where to store the ticket 89 * @param ticket where to store the ticket
88 * @param attrs the attributes found in the code 90 * @param attrs the attributes found in the code
91 * @param presentations credential presentation list
89 * @param nonce where to store the nonce 92 * @param nonce where to store the nonce
90 * @return GNUNET_OK if successful, else GNUNET_SYSERR 93 * @return GNUNET_OK if successful, else GNUNET_SYSERR
91 */ 94 */
@@ -95,7 +98,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
95 const char *code_verifier, 98 const char *code_verifier,
96 struct GNUNET_RECLAIM_Ticket *ticket, 99 struct GNUNET_RECLAIM_Ticket *ticket,
97 struct GNUNET_RECLAIM_AttributeList **attrs, 100 struct GNUNET_RECLAIM_AttributeList **attrs,
98 struct GNUNET_RECLAIM_AttestationList **attests, 101 struct GNUNET_RECLAIM_PresentationList **presentations,
99 char **nonce); 102 char **nonce);
100 103
101/** 104/**
@@ -136,8 +139,8 @@ OIDC_access_token_parse (const char* token,
136 * @return GNUNET_YES if attribute is implcitly requested 139 * @return GNUNET_YES if attribute is implcitly requested
137 */ 140 */
138enum GNUNET_GenericReturnValue 141enum GNUNET_GenericReturnValue
139OIDC_check_scopes_for_claim_request (const char*scopes, 142OIDC_check_scopes_for_claim_request (const char *scopes,
140 const char*attr); 143 const char *attr);
141 144
142 145
143/** 146/**
@@ -145,12 +148,12 @@ OIDC_check_scopes_for_claim_request (const char*scopes,
145 * 148 *
146 * @param sub_key the subject (user) 149 * @param sub_key the subject (user)
147 * @param attrs user attribute list 150 * @param attrs user attribute list
148 * @param attests user attribute attestation list (may be empty) 151 * @param presentations credential presentation list
149 * @return Userinfo JSON 152 * @return Userinfo JSON
150 */ 153 */
151char * 154char *
152OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, 155OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
153 struct GNUNET_RECLAIM_AttributeList *attrs, 156 const struct GNUNET_RECLAIM_AttributeList *attrs,
154 struct GNUNET_RECLAIM_AttestationList *attests); 157 const struct GNUNET_RECLAIM_PresentationList *presentations);
155 158
156#endif 159#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)
51 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF: 51 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
52 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET: 52 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
53 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER: 53 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
54 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION: 54 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
55 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF: 55 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
56 return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 56 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
57 57
58 default: 58 default:
@@ -89,8 +89,8 @@ string_to_value (void *cls, uint32_t type, const char *s, void **data,
89 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF: 89 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
90 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER: 90 case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
91 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET: 91 case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
92 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION: 92 case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
93 case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF: 93 case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
94 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size); 94 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
95 95
96 default: 96 default:
@@ -110,8 +110,8 @@ static struct
110} name_map[] = { 110} name_map[] = {
111 { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE }, 111 { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE },
112 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF }, 112 { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
113 { "RECLAIM_ATTESTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION }, 113 { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
114 { "RECLAIM_ATTESTATION_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF }, 114 { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
115 { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER }, 115 { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
116 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT }, 116 { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
117 { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT }, 117 { "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 @@
19 */ 19 */
20 20
21/** 21/**
22 * @file reclaim-attribute/plugin_reclaim_attestation_gnuid.c 22 * @file reclaim/plugin_reclaim_credential_jwt.c
23 * @brief reclaim-attribute-plugin-gnuid attribute plugin to provide the API for 23 * @brief reclaim-credential-plugin-jwt attribute plugin to provide the API for
24 * fundamental 24 * JWT credentials.
25 * attribute types.
26 * 25 *
27 * @author Martin Schanzenbach 26 * @author Martin Schanzenbach
28 */ 27 */
@@ -33,10 +32,10 @@
33#include <jansson.h> 32#include <jansson.h>
34 33
35/** 34/**
36 * Convert the 'value' of an attestation to a string. 35 * Convert the 'value' of an credential to a string.
37 * 36 *
38 * @param cls closure, unused 37 * @param cls closure, unused
39 * @param type type of the attestation 38 * @param type type of the credential
40 * @param data value in binary encoding 39 * @param data value in binary encoding
41 * @param data_size number of bytes in @a data 40 * @param data_size number of bytes in @a data
42 * @return NULL on error, otherwise human-readable representation of the value 41 * @return NULL on error, otherwise human-readable representation of the value
@@ -49,7 +48,7 @@ jwt_value_to_string (void *cls,
49{ 48{
50 switch (type) 49 switch (type)
51 { 50 {
52 case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT: 51 case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
53 return GNUNET_strndup (data, data_size); 52 return GNUNET_strndup (data, data_size);
54 53
55 default: 54 default:
@@ -59,11 +58,11 @@ jwt_value_to_string (void *cls,
59 58
60 59
61/** 60/**
62 * Convert human-readable version of a 'value' of an attestation to the binary 61 * Convert human-readable version of a 'value' of an credential to the binary
63 * representation. 62 * representation.
64 * 63 *
65 * @param cls closure, unused 64 * @param cls closure, unused
66 * @param type type of the attestation 65 * @param type type of the credential
67 * @param s human-readable string 66 * @param s human-readable string
68 * @param data set to value in binary encoding (will be allocated) 67 * @param data set to value in binary encoding (will be allocated)
69 * @param data_size set to number of bytes in @a data 68 * @param data_size set to number of bytes in @a data
@@ -80,7 +79,7 @@ jwt_string_to_value (void *cls,
80 return GNUNET_SYSERR; 79 return GNUNET_SYSERR;
81 switch (type) 80 switch (type)
82 { 81 {
83 case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT: 82 case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
84 *data = GNUNET_strdup (s); 83 *data = GNUNET_strdup (s);
85 *data_size = strlen (s); 84 *data_size = strlen (s);
86 return GNUNET_OK; 85 return GNUNET_OK;
@@ -92,15 +91,15 @@ jwt_string_to_value (void *cls,
92 91
93 92
94/** 93/**
95 * Mapping of attestation type numbers to human-readable 94 * Mapping of credential type numbers to human-readable
96 * attestation type names. 95 * credential type names.
97 */ 96 */
98static struct 97static struct
99{ 98{
100 const char *name; 99 const char *name;
101 uint32_t number; 100 uint32_t number;
102} jwt_attest_name_map[] = { { "JWT", GNUNET_RECLAIM_ATTESTATION_TYPE_JWT }, 101} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT },
103 { NULL, UINT32_MAX } }; 102 { NULL, UINT32_MAX } };
104 103
105/** 104/**
106 * Convert a type name to the corresponding number. 105 * Convert a type name to the corresponding number.
@@ -115,10 +114,10 @@ jwt_typename_to_number (void *cls, const char *jwt_typename)
115 unsigned int i; 114 unsigned int i;
116 115
117 i = 0; 116 i = 0;
118 while ((NULL != jwt_attest_name_map[i].name) && 117 while ((NULL != jwt_cred_name_map[i].name) &&
119 (0 != strcasecmp (jwt_typename, jwt_attest_name_map[i].name))) 118 (0 != strcasecmp (jwt_typename, jwt_cred_name_map[i].name)))
120 i++; 119 i++;
121 return jwt_attest_name_map[i].number; 120 return jwt_cred_name_map[i].number;
122} 121}
123 122
124 123
@@ -135,11 +134,11 @@ jwt_number_to_typename (void *cls, uint32_t type)
135 unsigned int i; 134 unsigned int i;
136 135
137 i = 0; 136 i = 0;
138 while ((NULL != jwt_attest_name_map[i].name) && (type != 137 while ((NULL != jwt_cred_name_map[i].name) && (type !=
139 jwt_attest_name_map[i]. 138 jwt_cred_name_map[i].
140 number)) 139 number))
141 i++; 140 i++;
142 return jwt_attest_name_map[i].name; 141 return jwt_cred_name_map[i].name;
143} 142}
144 143
145 144
@@ -147,12 +146,12 @@ jwt_number_to_typename (void *cls, uint32_t type)
147 * Parse a JWT and return the respective claim value as Attribute 146 * Parse a JWT and return the respective claim value as Attribute
148 * 147 *
149 * @param cls the plugin 148 * @param cls the plugin
150 * @param attest the jwt attestation 149 * @param cred the jwt credential
151 * @return a GNUNET_RECLAIM_Attribute, containing the new value 150 * @return a GNUNET_RECLAIM_Attribute, containing the new value
152 */ 151 */
153struct GNUNET_RECLAIM_AttributeList * 152struct GNUNET_RECLAIM_AttributeList *
154jwt_parse_attributes (void *cls, 153jwt_parse_attributes (void *cls,
155 const struct GNUNET_RECLAIM_Attestation *attest) 154 const char *data)
156{ 155{
157 char *jwt_string; 156 char *jwt_string;
158 struct GNUNET_RECLAIM_AttributeList *attrs; 157 struct GNUNET_RECLAIM_AttributeList *attrs;
@@ -163,17 +162,14 @@ jwt_parse_attributes (void *cls,
163 json_t *json_val; 162 json_t *json_val;
164 json_error_t *json_err = NULL; 163 json_error_t *json_err = NULL;
165 164
166 /* GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", attest->data); (not OK: 'data' is not defined as 0-terminated text, but binary) */
167 if (GNUNET_RECLAIM_ATTESTATION_TYPE_JWT != attest->type)
168 return NULL;
169 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 165 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
170 166
171 jwt_string = GNUNET_strdup (attest->data); 167 jwt_string = GNUNET_strdup (data);
172 const char *jwt_body = strtok (jwt_string, delim); 168 const char *jwt_body = strtok (jwt_string, delim);
173 jwt_body = strtok (NULL, delim); 169 jwt_body = strtok (NULL, delim);
174 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), 170 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
175 (void **) &decoded_jwt); 171 (void **) &decoded_jwt);
176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", decoded_jwt); 172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt);
177 GNUNET_assert (NULL != decoded_jwt); 173 GNUNET_assert (NULL != decoded_jwt);
178 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err); 174 json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
179 const char *key; 175 const char *key;
@@ -204,15 +200,45 @@ jwt_parse_attributes (void *cls,
204 200
205 201
206/** 202/**
203 * Parse a JWT and return the respective claim value as Attribute
204 *
205 * @param cls the plugin
206 * @param cred the jwt credential
207 * @return a GNUNET_RECLAIM_Attribute, containing the new value
208 */
209struct GNUNET_RECLAIM_AttributeList *
210jwt_parse_attributes_c (void *cls,
211 const struct GNUNET_RECLAIM_Credential *cred)
212{
213 return jwt_parse_attributes (cls, cred->data);
214}
215
216
217/**
218 * Parse a JWT and return the respective claim value as Attribute
219 *
220 * @param cls the plugin
221 * @param cred the jwt credential
222 * @return a GNUNET_RECLAIM_Attribute, containing the new value
223 */
224struct GNUNET_RECLAIM_AttributeList *
225jwt_parse_attributes_p (void *cls,
226 const struct GNUNET_RECLAIM_Presentation *cred)
227{
228 return jwt_parse_attributes (cls, cred->data);
229}
230
231
232/**
207 * Parse a JWT and return the issuer 233 * Parse a JWT and return the issuer
208 * 234 *
209 * @param cls the plugin 235 * @param cls the plugin
210 * @param attest the jwt attestation 236 * @param cred the jwt credential
211 * @return a string, containing the isser 237 * @return a string, containing the isser
212 */ 238 */
213char * 239char *
214jwt_get_issuer (void *cls, 240jwt_get_issuer (void *cls,
215 const struct GNUNET_RECLAIM_Attestation *attest) 241 const char *data)
216{ 242{
217 const char *jwt_body; 243 const char *jwt_body;
218 char *jwt_string; 244 char *jwt_string;
@@ -224,9 +250,7 @@ jwt_get_issuer (void *cls,
224 json_t *json_val; 250 json_t *json_val;
225 json_error_t *json_err = NULL; 251 json_error_t *json_err = NULL;
226 252
227 if (GNUNET_RECLAIM_ATTESTATION_TYPE_JWT != attest->type) 253 jwt_string = GNUNET_strdup (data);
228 return NULL;
229 jwt_string = GNUNET_strdup (attest->data);
230 jwt_body = strtok (jwt_string, delim); 254 jwt_body = strtok (jwt_string, delim);
231 jwt_body = strtok (NULL, delim); 255 jwt_body = strtok (NULL, delim);
232 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), 256 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
@@ -242,15 +266,49 @@ jwt_get_issuer (void *cls,
242 266
243 267
244/** 268/**
269 * Parse a JWT and return the issuer
270 *
271 * @param cls the plugin
272 * @param cred the jwt credential
273 * @return a string, containing the isser
274 */
275char *
276jwt_get_issuer_c (void *cls,
277 const struct GNUNET_RECLAIM_Credential *cred)
278{
279 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
280 return NULL;
281 return jwt_get_issuer (cls, cred->data);
282}
283
284
285/**
286 * Parse a JWT and return the issuer
287 *
288 * @param cls the plugin
289 * @param cred the jwt credential
290 * @return a string, containing the isser
291 */
292char *
293jwt_get_issuer_p (void *cls,
294 const struct GNUNET_RECLAIM_Presentation *cred)
295{
296 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
297 return NULL;
298 return jwt_get_issuer (cls, cred->data);
299}
300
301
302/**
245 * Parse a JWT and return the expiration 303 * Parse a JWT and return the expiration
246 * 304 *
247 * @param cls the plugin 305 * @param cls the plugin
248 * @param attest the jwt attestation 306 * @param cred the jwt credential
249 * @return a string, containing the isser 307 * @return a string, containing the isser
250 */ 308 */
251int 309int
252jwt_get_expiration (void *cls, 310jwt_get_expiration (void *cls,
253 const struct GNUNET_RECLAIM_Attestation *attest, 311 const char *data,
254 struct GNUNET_TIME_Absolute *exp) 312 struct GNUNET_TIME_Absolute *exp)
255{ 313{
256 const char *jwt_body; 314 const char *jwt_body;
@@ -262,9 +320,7 @@ jwt_get_expiration (void *cls,
262 json_t *json_val; 320 json_t *json_val;
263 json_error_t *json_err = NULL; 321 json_error_t *json_err = NULL;
264 322
265 if (GNUNET_RECLAIM_ATTESTATION_TYPE_JWT != attest->type) 323 jwt_string = GNUNET_strdup (data);
266 return GNUNET_NO;
267 jwt_string = GNUNET_strdup (attest->data);
268 jwt_body = strtok (jwt_string, delim); 324 jwt_body = strtok (jwt_string, delim);
269 jwt_body = strtok (NULL, delim); 325 jwt_body = strtok (NULL, delim);
270 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body), 326 GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
@@ -280,24 +336,80 @@ jwt_get_expiration (void *cls,
280 336
281 337
282/** 338/**
339 * Parse a JWT and return the expiration
340 *
341 * @param cls the plugin
342 * @param cred the jwt credential
343 * @return a string, containing the isser
344 */
345int
346jwt_get_expiration_c (void *cls,
347 const struct GNUNET_RECLAIM_Credential *cred,
348 struct GNUNET_TIME_Absolute *exp)
349{
350 return jwt_get_expiration (cls, cred->data, exp);
351}
352
353
354/**
355 * Parse a JWT and return the expiration
356 *
357 * @param cls the plugin
358 * @param cred the jwt credential
359 * @return a string, containing the isser
360 */
361int
362jwt_get_expiration_p (void *cls,
363 const struct GNUNET_RECLAIM_Presentation *cred,
364 struct GNUNET_TIME_Absolute *exp)
365{
366 return jwt_get_expiration (cls, cred->data, exp);
367}
368
369
370int
371jwt_create_presentation (void *cls,
372 const struct GNUNET_RECLAIM_Credential *cred,
373 const struct GNUNET_RECLAIM_AttributeList *attrs,
374 struct GNUNET_RECLAIM_Presentation **pres)
375{
376 // FIXME sanity checks??
377 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
378 return GNUNET_NO;
379 *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT,
380 cred->data,
381 cred->data_size);
382 return GNUNET_OK;
383}
384
385
386/**
283 * Entry point for the plugin. 387 * Entry point for the plugin.
284 * 388 *
285 * @param cls NULL 389 * @param cls NULL
286 * @return the exported block API 390 * @return the exported block API
287 */ 391 */
288void * 392void *
289libgnunet_plugin_reclaim_attestation_jwt_init (void *cls) 393libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
290{ 394{
291 struct GNUNET_RECLAIM_AttestationPluginFunctions *api; 395 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
292 396
293 api = GNUNET_new (struct GNUNET_RECLAIM_AttestationPluginFunctions); 397 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
294 api->value_to_string = &jwt_value_to_string; 398 api->value_to_string = &jwt_value_to_string;
295 api->string_to_value = &jwt_string_to_value; 399 api->string_to_value = &jwt_string_to_value;
296 api->typename_to_number = &jwt_typename_to_number; 400 api->typename_to_number = &jwt_typename_to_number;
297 api->number_to_typename = &jwt_number_to_typename; 401 api->number_to_typename = &jwt_number_to_typename;
298 api->get_attributes = &jwt_parse_attributes; 402 api->get_attributes = &jwt_parse_attributes_c;
299 api->get_issuer = &jwt_get_issuer; 403 api->get_issuer = &jwt_get_issuer_c;
300 api->get_expiration = &jwt_get_expiration; 404 api->get_expiration = &jwt_get_expiration_c;
405 api->value_to_string_p = &jwt_value_to_string;
406 api->string_to_value_p = &jwt_string_to_value;
407 api->typename_to_number_p = &jwt_typename_to_number;
408 api->number_to_typename_p = &jwt_number_to_typename;
409 api->get_attributes_p = &jwt_parse_attributes_p;
410 api->get_issuer_p = &jwt_get_issuer_p;
411 api->get_expiration_p = &jwt_get_expiration_p;
412 api->create_presentation = &jwt_create_presentation;
301 return api; 413 return api;
302} 414}
303 415
@@ -309,13 +421,13 @@ libgnunet_plugin_reclaim_attestation_jwt_init (void *cls)
309 * @return NULL 421 * @return NULL
310 */ 422 */
311void * 423void *
312libgnunet_plugin_reclaim_attestation_jwt_done (void *cls) 424libgnunet_plugin_reclaim_credential_jwt_done (void *cls)
313{ 425{
314 struct GNUNET_RECLAIM_AttestationPluginFunctions *api = cls; 426 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
315 427
316 GNUNET_free (api); 428 GNUNET_free (api);
317 return NULL; 429 return NULL;
318} 430}
319 431
320 432
321/* end of plugin_reclaim_attestation_type_gnuid.c */ 433/* 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
393 393
394struct RequestHandle 394struct RequestHandle
395{ 395{
396 /**
397 * DLL
398 */
399 struct RequestHandle *next;
400
401 /**
402 * DLL
403 */
404 struct RequestHandle *prev;
396 405
397 /** 406 /**
398 * Selected ego 407 * Selected ego
@@ -430,10 +439,14 @@ struct RequestHandle
430 struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list; 439 struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list;
431 440
432 /** 441 /**
433 * Attestation list 442 * Credentials
434 */ 443 */
435 struct GNUNET_RECLAIM_AttestationList *attests_list; 444 struct GNUNET_RECLAIM_CredentialList *credentials;
436 445
446 /**
447 * Presentations
448 */
449 struct GNUNET_RECLAIM_PresentationList *presentations;
437 450
438 /** 451 /**
439 * IDENTITY Operation 452 * IDENTITY Operation
@@ -452,9 +465,9 @@ struct RequestHandle
452 struct GNUNET_RECLAIM_AttributeIterator *attr_it; 465 struct GNUNET_RECLAIM_AttributeIterator *attr_it;
453 466
454 /** 467 /**
455 * Attestation iterator 468 * Credential iterator
456 */ 469 */
457 struct GNUNET_RECLAIM_AttestationIterator *attest_it; 470 struct GNUNET_RECLAIM_CredentialIterator *cred_it;
458 471
459 472
460 /** 473 /**
@@ -528,6 +541,16 @@ struct RequestHandle
528 int public_client; 541 int public_client;
529}; 542};
530 543
544/**
545 * DLL
546 */
547static struct RequestHandle *requests_head;
548
549/**
550 * DLL
551 */
552static struct RequestHandle *requests_tail;
553
531 554
532/** 555/**
533 * Cleanup lookup handle 556 * Cleanup lookup handle
@@ -542,8 +565,8 @@ cleanup_handle (struct RequestHandle *handle)
542 GNUNET_SCHEDULER_cancel (handle->timeout_task); 565 GNUNET_SCHEDULER_cancel (handle->timeout_task);
543 if (NULL != handle->attr_it) 566 if (NULL != handle->attr_it)
544 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); 567 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
545 if (NULL != handle->attest_it) 568 if (NULL != handle->cred_it)
546 GNUNET_RECLAIM_get_attestations_stop (handle->attest_it); 569 GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
547 if (NULL != handle->ticket_it) 570 if (NULL != handle->ticket_it)
548 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); 571 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
549 if (NULL != handle->idp_op) 572 if (NULL != handle->idp_op)
@@ -571,20 +594,17 @@ cleanup_handle (struct RequestHandle *handle)
571 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list); 594 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
572 if (NULL!=handle->attr_userinfo_list) 595 if (NULL!=handle->attr_userinfo_list)
573 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list); 596 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
574 if (NULL!=handle->attests_list) 597 if (NULL!=handle->credentials)
575 GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); 598 GNUNET_RECLAIM_credential_list_destroy (handle->credentials);
576 599 if (NULL!=handle->presentations)
600 GNUNET_RECLAIM_presentation_list_destroy (handle->presentations);
601 GNUNET_CONTAINER_DLL_remove (requests_head,
602 requests_tail,
603 handle);
577 GNUNET_free (handle); 604 GNUNET_free (handle);
578} 605}
579 606
580 607
581static void
582cleanup_handle_delayed (void *cls)
583{
584 cleanup_handle (cls);
585}
586
587
588/** 608/**
589 * Task run on error, sends error message. Cleans up everything. 609 * Task run on error, sends error message. Cleans up everything.
590 * 610 *
@@ -613,7 +633,7 @@ do_error (void *cls)
613 MHD_HTTP_HEADER_CONTENT_TYPE, 633 MHD_HTTP_HEADER_CONTENT_TYPE,
614 "application/json"); 634 "application/json");
615 handle->proc (handle->proc_cls, resp, handle->response_code); 635 handle->proc (handle->proc_cls, resp, handle->response_code);
616 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 636 cleanup_handle (handle);
617 GNUNET_free (json_error); 637 GNUNET_free (json_error);
618} 638}
619 639
@@ -640,7 +660,7 @@ do_userinfo_error (void *cls)
640 resp = GNUNET_REST_create_response (""); 660 resp = GNUNET_REST_create_response ("");
641 MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer"); 661 MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
642 handle->proc (handle->proc_cls, resp, handle->response_code); 662 handle->proc (handle->proc_cls, resp, handle->response_code);
643 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 663 cleanup_handle (handle);
644 GNUNET_free (error); 664 GNUNET_free (error);
645} 665}
646 666
@@ -667,7 +687,7 @@ do_redirect_error (void *cls)
667 resp = GNUNET_REST_create_response (""); 687 resp = GNUNET_REST_create_response ("");
668 MHD_add_response_header (resp, "Location", redirect); 688 MHD_add_response_header (resp, "Location", redirect);
669 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 689 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
670 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 690 cleanup_handle (handle);
671 GNUNET_free (redirect); 691 GNUNET_free (redirect);
672} 692}
673 693
@@ -897,7 +917,7 @@ login_redirect (void *cls)
897 } 917 }
898 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 918 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
899 GNUNET_free (new_redirect); 919 GNUNET_free (new_redirect);
900 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 920 cleanup_handle (handle);
901} 921}
902 922
903 923
@@ -920,7 +940,9 @@ oidc_iteration_error (void *cls)
920 * parameter. Otherwise redirects with error 940 * parameter. Otherwise redirects with error
921 */ 941 */
922static void 942static void
923oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) 943oidc_ticket_issue_cb (void *cls,
944 const struct GNUNET_RECLAIM_Ticket *ticket,
945 const struct GNUNET_RECLAIM_PresentationList *pres)
924{ 946{
925 struct RequestHandle *handle = cls; 947 struct RequestHandle *handle = cls;
926 struct MHD_Response *resp; 948 struct MHD_Response *resp;
@@ -943,7 +965,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
943 code_string = OIDC_build_authz_code (&handle->priv_key, 965 code_string = OIDC_build_authz_code (&handle->priv_key,
944 &handle->ticket, 966 &handle->ticket,
945 handle->attr_idtoken_list, 967 handle->attr_idtoken_list,
946 handle->attests_list, 968 pres,
947 handle->oidc->nonce, 969 handle->oidc->nonce,
948 handle->oidc->code_challenge); 970 handle->oidc->code_challenge);
949 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) && 971 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)
974 resp = GNUNET_REST_create_response (""); 996 resp = GNUNET_REST_create_response ("");
975 MHD_add_response_header (resp, "Location", redirect_uri); 997 MHD_add_response_header (resp, "Location", redirect_uri);
976 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 998 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
977 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 999 cleanup_handle (handle);
978 GNUNET_free (redirect_uri); 1000 GNUNET_free (redirect_uri);
979 GNUNET_free (ticket_str); 1001 GNUNET_free (ticket_str);
980 GNUNET_free (code_string); 1002 GNUNET_free (code_string);
@@ -996,13 +1018,13 @@ attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
996 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 1018 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
997 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_a->attribute->name, 1019 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_a->attribute->name,
998 &le_a->attribute-> 1020 &le_a->attribute->
999 attestation, 1021 credential,
1000 le_a->attribute->type, 1022 le_a->attribute->type,
1001 le_a->attribute->data, 1023 le_a->attribute->data,
1002 le_a->attribute->data_size); 1024 le_a->attribute->data_size);
1003 le_m->attribute->id = le_a->attribute->id; 1025 le_m->attribute->id = le_a->attribute->id;
1004 le_m->attribute->flag = le_a->attribute->flag; 1026 le_m->attribute->flag = le_a->attribute->flag;
1005 le_m->attribute->attestation = le_a->attribute->attestation; 1027 le_m->attribute->credential = le_a->attribute->credential;
1006 GNUNET_CONTAINER_DLL_insert (merged_list->list_head, 1028 GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1007 merged_list->list_tail, 1029 merged_list->list_tail,
1008 le_m); 1030 le_m);
@@ -1021,13 +1043,13 @@ attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
1021 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 1043 le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1022 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_b->attribute->name, 1044 le_m->attribute = GNUNET_RECLAIM_attribute_new (le_b->attribute->name,
1023 &le_b->attribute-> 1045 &le_b->attribute->
1024 attestation, 1046 credential,
1025 le_b->attribute->type, 1047 le_b->attribute->type,
1026 le_b->attribute->data, 1048 le_b->attribute->data,
1027 le_b->attribute->data_size); 1049 le_b->attribute->data_size);
1028 le_m->attribute->id = le_b->attribute->id; 1050 le_m->attribute->id = le_b->attribute->id;
1029 le_m->attribute->flag = le_b->attribute->flag; 1051 le_m->attribute->flag = le_b->attribute->flag;
1030 le_m->attribute->attestation = le_b->attribute->attestation; 1052 le_m->attribute->credential = le_b->attribute->credential;
1031 GNUNET_CONTAINER_DLL_insert (merged_list->list_head, 1053 GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1032 merged_list->list_tail, 1054 merged_list->list_tail,
1033 le_m); 1055 le_m);
@@ -1037,14 +1059,19 @@ attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
1037 1059
1038 1060
1039static void 1061static void
1040oidc_attest_collect_finished_cb (void *cls) 1062oidc_cred_collect_finished_cb (void *cls)
1041{ 1063{
1042 struct RequestHandle *handle = cls; 1064 struct RequestHandle *handle = cls;
1043 struct GNUNET_RECLAIM_AttributeList *merged_list; 1065 struct GNUNET_RECLAIM_AttributeList *merged_list;
1066 struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1044 1067
1045 handle->attest_it = NULL; 1068 handle->cred_it = NULL;
1046 merged_list = attribute_list_merge (handle->attr_idtoken_list, 1069 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1047 handle->attr_userinfo_list); 1070 handle->attr_userinfo_list);
1071 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1073 "List Attibute in ticket to issue: %s\n",
1074 le_m->attribute->name);
1048 handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp, 1075 handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1049 &handle->priv_key, 1076 &handle->priv_key,
1050 &handle->oidc->client_pkey, 1077 &handle->oidc->client_pkey,
@@ -1059,40 +1086,40 @@ oidc_attest_collect_finished_cb (void *cls)
1059 * Collects all attributes for an ego if in scope parameter 1086 * Collects all attributes for an ego if in scope parameter
1060 */ 1087 */
1061static void 1088static void
1062oidc_attest_collect (void *cls, 1089oidc_cred_collect (void *cls,
1063 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 1090 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1064 const struct GNUNET_RECLAIM_Attestation *attest) 1091 const struct GNUNET_RECLAIM_Credential *cred)
1065{ 1092{
1066 struct RequestHandle *handle = cls; 1093 struct RequestHandle *handle = cls;
1067 struct GNUNET_RECLAIM_AttributeListEntry *le; 1094 struct GNUNET_RECLAIM_AttributeListEntry *le;
1068 struct GNUNET_RECLAIM_AttestationListEntry *ale; 1095 struct GNUNET_RECLAIM_CredentialListEntry *ale;
1069 1096
1070 for (ale = handle->attests_list->list_head; NULL != ale; ale = ale->next) 1097 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1071 { 1098 {
1072 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->attestation->id, 1099 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->credential->id,
1073 &attest->id)) 1100 &cred->id))
1074 continue; 1101 continue;
1075 /** Attestation already in list **/ 1102 /** Credential already in list **/
1076 GNUNET_RECLAIM_get_attestations_next (handle->attest_it); 1103 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
1077 return; 1104 return;
1078 } 1105 }
1079 1106
1080 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next) 1107 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1081 { 1108 {
1082 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation, 1109 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
1083 &attest->id)) 1110 &cred->id))
1084 continue; 1111 continue;
1085 /** Attestation matches for attribute, add **/ 1112 /** Credential matches for attribute, add **/
1086 ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); 1113 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
1087 ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name, 1114 ale->credential = GNUNET_RECLAIM_credential_new (cred->name,
1088 attest->type, 1115 cred->type,
1089 attest->data, 1116 cred->data,
1090 attest->data_size); 1117 cred->data_size);
1091 GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, 1118 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1092 handle->attests_list->list_tail, 1119 handle->credentials->list_tail,
1093 ale); 1120 ale);
1094 } 1121 }
1095 GNUNET_RECLAIM_get_attestations_next (handle->attest_it); 1122 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
1096} 1123}
1097 1124
1098 1125
@@ -1110,16 +1137,16 @@ oidc_attr_collect_finished_cb (void *cls)
1110 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); 1137 GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
1111 return; 1138 return;
1112 } 1139 }
1113 handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); 1140 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1114 handle->attest_it = 1141 handle->cred_it =
1115 GNUNET_RECLAIM_get_attestations_start (idp, 1142 GNUNET_RECLAIM_get_credentials_start (idp,
1116 &handle->priv_key, 1143 &handle->priv_key,
1117 &oidc_iteration_error, 1144 &oidc_iteration_error,
1118 handle, 1145 handle,
1119 &oidc_attest_collect, 1146 &oidc_cred_collect,
1120 handle, 1147 handle,
1121 &oidc_attest_collect_finished_cb, 1148 &oidc_cred_collect_finished_cb,
1122 handle); 1149 handle);
1123 1150
1124} 1151}
1125 1152
@@ -1136,7 +1163,7 @@ attr_in_claims_request (struct RequestHandle *handle,
1136 const char *key; 1163 const char *key;
1137 json_t *value; 1164 json_t *value;
1138 1165
1139 /** Check if attribute is requested through standard scope **/ 1166 /** Check if attribute is requested through a scope **/
1140 if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope, 1167 if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope,
1141 attr_name)) 1168 attr_name))
1142 return GNUNET_YES; 1169 return GNUNET_YES;
@@ -1193,13 +1220,13 @@ oidc_attr_collect (void *cls,
1193 { 1220 {
1194 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 1221 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1195 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, 1222 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
1196 &attr->attestation, 1223 &attr->credential,
1197 attr->type, 1224 attr->type,
1198 attr->data, 1225 attr->data,
1199 attr->data_size); 1226 attr->data_size);
1200 le->attribute->id = attr->id; 1227 le->attribute->id = attr->id;
1201 le->attribute->flag = attr->flag; 1228 le->attribute->flag = attr->flag;
1202 le->attribute->attestation = attr->attestation; 1229 le->attribute->credential = attr->credential;
1203 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head, 1230 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1204 handle->attr_idtoken_list->list_tail, 1231 handle->attr_idtoken_list->list_tail,
1205 le); 1232 le);
@@ -1208,13 +1235,13 @@ oidc_attr_collect (void *cls,
1208 { 1235 {
1209 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 1236 le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
1210 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, 1237 le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
1211 &attr->attestation, 1238 &attr->credential,
1212 attr->type, 1239 attr->type,
1213 attr->data, 1240 attr->data,
1214 attr->data_size); 1241 attr->data_size);
1215 le->attribute->id = attr->id; 1242 le->attribute->id = attr->id;
1216 le->attribute->flag = attr->flag; 1243 le->attribute->flag = attr->flag;
1217 le->attribute->attestation = attr->attestation; 1244 le->attribute->credential = attr->credential;
1218 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head, 1245 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1219 handle->attr_userinfo_list->list_tail, 1246 handle->attr_userinfo_list->list_tail,
1220 le); 1247 le);
@@ -1332,7 +1359,7 @@ build_redirect (void *cls)
1332 resp = GNUNET_REST_create_response (""); 1359 resp = GNUNET_REST_create_response ("");
1333 MHD_add_response_header (resp, "Location", redirect_uri); 1360 MHD_add_response_header (resp, "Location", redirect_uri);
1334 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); 1361 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1335 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 1362 cleanup_handle (handle);
1336 GNUNET_free (redirect_uri); 1363 GNUNET_free (redirect_uri);
1337 return; 1364 return;
1338 } 1365 }
@@ -1709,7 +1736,7 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1709 term_data); 1736 term_data);
1710 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); 1737 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1711 json_decref (root); 1738 json_decref (root);
1712 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 1739 cleanup_handle (handle);
1713 return; 1740 return;
1714 } 1741 }
1715 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity)); 1742 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
@@ -1739,7 +1766,7 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1739 GNUNET_free (cookie); 1766 GNUNET_free (cookie);
1740 GNUNET_free (header_val); 1767 GNUNET_free (header_val);
1741 json_decref (root); 1768 json_decref (root);
1742 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 1769 cleanup_handle (handle);
1743} 1770}
1744 1771
1745 1772
@@ -1963,10 +1990,9 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1963 const struct EgoEntry *ego_entry; 1990 const struct EgoEntry *ego_entry;
1964 struct GNUNET_TIME_Relative expiration_time; 1991 struct GNUNET_TIME_Relative expiration_time;
1965 struct GNUNET_RECLAIM_AttributeList *cl = NULL; 1992 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
1966 struct GNUNET_RECLAIM_AttestationList *al = NULL; 1993 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
1967 struct GNUNET_RECLAIM_Ticket ticket; 1994 struct GNUNET_RECLAIM_Ticket ticket;
1968 struct GNUNET_CRYPTO_EcdsaPublicKey cid; 1995 struct GNUNET_CRYPTO_EcdsaPublicKey cid;
1969 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
1970 struct GNUNET_HashCode cache_key; 1996 struct GNUNET_HashCode cache_key;
1971 struct MHD_Response *resp; 1997 struct MHD_Response *resp;
1972 char *grant_type; 1998 char *grant_type;
@@ -2038,7 +2064,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2038 GNUNET_SCHEDULER_add_now (&do_error, handle); 2064 GNUNET_SCHEDULER_add_now (&do_error, handle);
2039 return; 2065 return;
2040 } 2066 }
2041 privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
2042 2067
2043 // REQUIRED code verifier 2068 // REQUIRED code verifier
2044 code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY); 2069 code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
@@ -2051,7 +2076,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2051 2076
2052 // decode code 2077 // decode code
2053 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket, 2078 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2054 &cl, &al, &nonce)) 2079 &cl, &pl, &nonce))
2055 { 2080 {
2056 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); 2081 handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
2057 handle->edesc = GNUNET_strdup ("invalid code"); 2082 handle->edesc = GNUNET_strdup ("invalid code");
@@ -2091,7 +2116,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2091 id_token = OIDC_generate_id_token (&ticket.audience, 2116 id_token = OIDC_generate_id_token (&ticket.audience,
2092 &ticket.identity, 2117 &ticket.identity,
2093 cl, 2118 cl,
2094 al, 2119 pl,
2095 &expiration_time, 2120 &expiration_time,
2096 (NULL != nonce) ? nonce : NULL, 2121 (NULL != nonce) ? nonce : NULL,
2097 jwt_secret); 2122 jwt_secret);
@@ -2107,11 +2132,11 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2107 MHD_add_response_header (resp, "Content-Type", "application/json"); 2132 MHD_add_response_header (resp, "Content-Type", "application/json");
2108 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 2133 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2109 GNUNET_RECLAIM_attribute_list_destroy (cl); 2134 GNUNET_RECLAIM_attribute_list_destroy (cl);
2110 GNUNET_RECLAIM_attestation_list_destroy (al); 2135 GNUNET_RECLAIM_presentation_list_destroy (pl);
2111 GNUNET_free (access_token); 2136 GNUNET_free (access_token);
2112 GNUNET_free (json_response); 2137 GNUNET_free (json_response);
2113 GNUNET_free (id_token); 2138 GNUNET_free (id_token);
2114 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 2139 cleanup_handle (handle);
2115} 2140}
2116 2141
2117 2142
@@ -2122,22 +2147,21 @@ static void
2122consume_ticket (void *cls, 2147consume_ticket (void *cls,
2123 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 2148 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
2124 const struct GNUNET_RECLAIM_Attribute *attr, 2149 const struct GNUNET_RECLAIM_Attribute *attr,
2125 const struct GNUNET_RECLAIM_Attestation *attest) 2150 const struct GNUNET_RECLAIM_Presentation *pres)
2126{ 2151{
2127 struct RequestHandle *handle = cls; 2152 struct RequestHandle *handle = cls;
2128 struct GNUNET_RECLAIM_AttributeListEntry *ale; 2153 struct GNUNET_RECLAIM_AttributeListEntry *ale;
2129 struct GNUNET_RECLAIM_AttestationListEntry *atle; 2154 struct GNUNET_RECLAIM_PresentationListEntry *atle;
2130 struct MHD_Response *resp; 2155 struct MHD_Response *resp;
2131 char *result_str; 2156 char *result_str;
2132 handle->idp_op = NULL; 2157 handle->idp_op = NULL;
2133 2158
2134 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attr: %s\n", attr->name);
2135 if (NULL == identity) 2159 if (NULL == identity)
2136 { 2160 {
2137 result_str = OIDC_generate_userinfo (&handle->ticket.identity, 2161 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2138 handle->attr_userinfo_list, 2162 handle->attr_userinfo_list,
2139 handle->attests_list); 2163 handle->presentations);
2140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Userinfo: %s\n", result_str); 2164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2141 resp = GNUNET_REST_create_response (result_str); 2165 resp = GNUNET_REST_create_response (result_str);
2142 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 2166 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2143 GNUNET_free (result_str); 2167 GNUNET_free (result_str);
@@ -2146,33 +2170,35 @@ consume_ticket (void *cls,
2146 } 2170 }
2147 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 2171 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
2148 ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name, 2172 ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
2149 &attr->attestation, 2173 &attr->credential,
2150 attr->type, 2174 attr->type,
2151 attr->data, 2175 attr->data,
2152 attr->data_size); 2176 attr->data_size);
2153 ale->attribute->id = attr->id; 2177 ale->attribute->id = attr->id;
2154 ale->attribute->flag = attr->flag; 2178 ale->attribute->flag = attr->flag;
2155 ale->attribute->attestation = attr->attestation; 2179 ale->attribute->credential = attr->credential;
2156 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head, 2180 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2157 handle->attr_userinfo_list->list_tail, 2181 handle->attr_userinfo_list->list_tail,
2158 ale); 2182 ale);
2159 for (atle = handle->attests_list->list_head; NULL != atle; atle = atle->next) 2183 if (NULL == pres)
2184 return;
2185 for (atle = handle->presentations->list_head;
2186 NULL != atle; atle = atle->next)
2160 { 2187 {
2161 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->attestation->id, 2188 if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->presentation->credential_id,
2162 &attest->id)) 2189 &pres->credential_id))
2163 continue; 2190 continue;
2164 break; /** already in list **/ 2191 break; /** already in list **/
2165 } 2192 }
2166 if (NULL == atle) 2193 if (NULL == atle)
2167 { 2194 {
2168 /** Attestation matches for attribute, add **/ 2195 /** Credential matches for attribute, add **/
2169 atle = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); 2196 atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
2170 atle->attestation = GNUNET_RECLAIM_attestation_new (attest->name, 2197 atle->presentation = GNUNET_RECLAIM_presentation_new (pres->type,
2171 attest->type, 2198 pres->data,
2172 attest->data, 2199 pres->data_size);
2173 attest->data_size); 2200 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2174 GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, 2201 handle->presentations->list_tail,
2175 handle->attests_list->list_tail,
2176 atle); 2202 atle);
2177 } 2203 }
2178} 2204}
@@ -2271,8 +2297,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2271 privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego); 2297 privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2272 handle->attr_userinfo_list = 2298 handle->attr_userinfo_list =
2273 GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 2299 GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
2274 handle->attests_list = 2300 handle->presentations =
2275 GNUNET_new (struct GNUNET_RECLAIM_AttestationList); 2301 GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
2276 2302
2277 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp, 2303 handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2278 privkey, 2304 privkey,
@@ -2442,6 +2468,12 @@ oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2442 json_string ("openid")); 2468 json_string ("openid"));
2443 json_array_append_new (scopes, 2469 json_array_append_new (scopes,
2444 json_string ("profile")); 2470 json_string ("profile"));
2471 json_array_append_new (scopes,
2472 json_string ("email"));
2473 json_array_append_new (scopes,
2474 json_string ("address"));
2475 json_array_append_new (scopes,
2476 json_string ("phone"));
2445 json_object_set_new (oidc_config, 2477 json_object_set_new (oidc_config,
2446 "scopes_supported", 2478 "scopes_supported",
2447 scopes); 2479 scopes);
@@ -2533,14 +2565,17 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
2533 handle->proc = proc; 2565 handle->proc = proc;
2534 handle->rest_handle = rest_handle; 2566 handle->rest_handle = rest_handle;
2535 handle->url = GNUNET_strdup (rest_handle->url); 2567 handle->url = GNUNET_strdup (rest_handle->url);
2568 handle->timeout_task =
2569 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2570 GNUNET_CONTAINER_DLL_insert (requests_head,
2571 requests_tail,
2572 handle);
2536 if (handle->url[strlen (handle->url) - 1] == '/') 2573 if (handle->url[strlen (handle->url) - 1] == '/')
2537 handle->url[strlen (handle->url) - 1] = '\0'; 2574 handle->url[strlen (handle->url) - 1] = '\0';
2538 if (GNUNET_NO == 2575 if (GNUNET_NO ==
2539 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) 2576 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2540 return GNUNET_NO; 2577 return GNUNET_NO;
2541 2578
2542 handle->timeout_task =
2543 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2544 return GNUNET_YES; 2579 return GNUNET_YES;
2545} 2580}
2546 2581
@@ -2585,6 +2620,14 @@ libgnunet_plugin_rest_openid_connect_init (void *cls)
2585} 2620}
2586 2621
2587 2622
2623static int
2624cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2625{
2626 GNUNET_free (value);
2627 return GNUNET_YES;
2628}
2629
2630
2588/** 2631/**
2589 * Exit point from the plugin. 2632 * Exit point from the plugin.
2590 * 2633 *
@@ -2599,19 +2642,15 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
2599 struct EgoEntry *ego_entry; 2642 struct EgoEntry *ego_entry;
2600 2643
2601 plugin->cfg = NULL; 2644 plugin->cfg = NULL;
2602 2645 while (NULL != requests_head)
2603 struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it; 2646 cleanup_handle (requests_head);
2604 void *value = NULL; 2647 if (NULL != OIDC_cookie_jar_map)
2605 hashmap_it = 2648 {
2606 GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_cookie_jar_map); 2649 GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
2607 while (GNUNET_YES == 2650 &cleanup_hashmap,
2608 GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, 2651 NULL);
2609 value)) 2652 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2610 GNUNET_free (value); 2653 }
2611 GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
2612 GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2613
2614 GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
2615 GNUNET_free (allow_methods); 2654 GNUNET_free (allow_methods);
2616 if (NULL != gns_handle) 2655 if (NULL != gns_handle)
2617 GNUNET_GNS_disconnect (gns_handle); 2656 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 @@
48#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes" 48#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
49 49
50/** 50/**
51 * Attestation namespace 51 * Credential namespace
52 */ 52 */
53#define GNUNET_REST_API_NS_RECLAIM_ATTESTATION "/reclaim/attestation" 53#define GNUNET_REST_API_NS_RECLAIM_CREDENTIAL "/reclaim/credential"
54 54
55/** 55/**
56 * Ticket namespace 56 * Ticket namespace
@@ -154,6 +154,15 @@ struct EgoEntry
154 154
155struct RequestHandle 155struct RequestHandle
156{ 156{
157 /**
158 * DLL
159 */
160 struct RequestHandle *next;
161
162 /**
163 * DLL
164 */
165 struct RequestHandle *prev;
157 166
158 /** 167 /**
159 * Selected ego 168 * Selected ego
@@ -193,7 +202,7 @@ struct RequestHandle
193 /** 202 /**
194 * Attribute iterator 203 * Attribute iterator
195 */ 204 */
196 struct GNUNET_RECLAIM_AttestationIterator *attest_it; 205 struct GNUNET_RECLAIM_CredentialIterator *cred_it;
197 206
198 /** 207 /**
199 * Ticket iterator 208 * Ticket iterator
@@ -247,6 +256,17 @@ struct RequestHandle
247}; 256};
248 257
249/** 258/**
259 * DLL
260 */
261static struct RequestHandle *requests_head;
262
263/**
264 * DLL
265 */
266static struct RequestHandle *requests_tail;
267
268
269/**
250 * Cleanup lookup handle 270 * Cleanup lookup handle
251 * @param handle Handle to clean up 271 * @param handle Handle to clean up
252 */ 272 */
@@ -262,8 +282,8 @@ cleanup_handle (void *cls)
262 GNUNET_SCHEDULER_cancel (handle->timeout_task); 282 GNUNET_SCHEDULER_cancel (handle->timeout_task);
263 if (NULL != handle->attr_it) 283 if (NULL != handle->attr_it)
264 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); 284 GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
265 if (NULL != handle->attest_it) 285 if (NULL != handle->cred_it)
266 GNUNET_RECLAIM_get_attestations_stop (handle->attest_it); 286 GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
267 if (NULL != handle->ticket_it) 287 if (NULL != handle->ticket_it)
268 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); 288 GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
269 if (NULL != handle->url) 289 if (NULL != handle->url)
@@ -272,6 +292,9 @@ cleanup_handle (void *cls)
272 GNUNET_free (handle->emsg); 292 GNUNET_free (handle->emsg);
273 if (NULL != handle->attr_list) 293 if (NULL != handle->attr_list)
274 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list); 294 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
295 GNUNET_CONTAINER_DLL_remove (requests_head,
296 requests_tail,
297 handle);
275 GNUNET_free (handle); 298 GNUNET_free (handle);
276} 299}
277 300
@@ -296,7 +319,7 @@ do_error (void *cls)
296 resp = GNUNET_REST_create_response (json_error); 319 resp = GNUNET_REST_create_response (json_error);
297 MHD_add_response_header (resp, "Content-Type", "application/json"); 320 MHD_add_response_header (resp, "Content-Type", "application/json");
298 handle->proc (handle->proc_cls, resp, handle->response_code); 321 handle->proc (handle->proc_cls, resp, handle->response_code);
299 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 322 cleanup_handle (handle);
300 GNUNET_free (json_error); 323 GNUNET_free (json_error);
301} 324}
302 325
@@ -319,7 +342,7 @@ do_timeout (void *cls)
319static void 342static void
320collect_error_cb (void *cls) 343collect_error_cb (void *cls)
321{ 344{
322 do_error (cls); 345 GNUNET_SCHEDULER_add_now (&do_error, cls);
323} 346}
324 347
325 348
@@ -329,6 +352,7 @@ finished_cont (void *cls, int32_t success, const char *emsg)
329 struct RequestHandle *handle = cls; 352 struct RequestHandle *handle = cls;
330 struct MHD_Response *resp; 353 struct MHD_Response *resp;
331 354
355 handle->idp_op = NULL;
332 resp = GNUNET_REST_create_response (emsg); 356 resp = GNUNET_REST_create_response (emsg);
333 MHD_add_response_header (resp, "Content-Type", "application/json"); 357 MHD_add_response_header (resp, "Content-Type", "application/json");
334 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); 358 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
@@ -389,7 +413,7 @@ collect_finished_cb (void *cls)
389 413
390 // Done 414 // Done
391 handle->attr_it = NULL; 415 handle->attr_it = NULL;
392 handle->attest_it = NULL; 416 handle->cred_it = NULL;
393 handle->ticket_it = NULL; 417 handle->ticket_it = NULL;
394 GNUNET_SCHEDULER_add_now (&return_response, handle); 418 GNUNET_SCHEDULER_add_now (&return_response, handle);
395} 419}
@@ -436,7 +460,7 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
436 460
437 461
438static void 462static void
439add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, 463add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
440 const char *url, 464 const char *url,
441 void *cls) 465 void *cls)
442{ 466{
@@ -444,19 +468,19 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
444 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv; 468 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
445 const char *identity; 469 const char *identity;
446 struct EgoEntry *ego_entry; 470 struct EgoEntry *ego_entry;
447 struct GNUNET_RECLAIM_Attestation *attribute; 471 struct GNUNET_RECLAIM_Credential *attribute;
448 struct GNUNET_TIME_Relative exp; 472 struct GNUNET_TIME_Relative exp;
449 char term_data[handle->rest_handle->data_size + 1]; 473 char term_data[handle->rest_handle->data_size + 1];
450 json_t *data_json; 474 json_t *data_json;
451 json_error_t err; 475 json_error_t err;
452 struct GNUNET_JSON_Specification attrspec[] = 476 struct GNUNET_JSON_Specification attrspec[] =
453 { GNUNET_RECLAIM_JSON_spec_claim_attest (&attribute), 477 { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
454 GNUNET_JSON_spec_end () }; 478 GNUNET_JSON_spec_end () };
455 479
456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
457 "Adding an attestation for %s.\n", 481 "Adding an credential for %s.\n",
458 handle->url); 482 handle->url);
459 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION) >= strlen ( 483 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
460 handle->url)) 484 handle->url))
461 { 485 {
462 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); 486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
@@ -464,7 +488,7 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
464 return; 488 return;
465 } 489 }
466 identity = handle->url + strlen ( 490 identity = handle->url + strlen (
467 GNUNET_REST_API_NS_RECLAIM_ATTESTATION) + 1; 491 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
468 492
469 for (ego_entry = ego_head; NULL != ego_entry; 493 for (ego_entry = ego_head; NULL != ego_entry;
470 ego_entry = ego_entry->next) 494 ego_entry = ego_entry->next)
@@ -494,7 +518,7 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
494 if (NULL == attribute) 518 if (NULL == attribute)
495 { 519 {
496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 520 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
497 "Unable to parse attestation from %s\n", 521 "Unable to parse credential from %s\n",
498 term_data); 522 term_data);
499 GNUNET_SCHEDULER_add_now (&do_error, handle); 523 GNUNET_SCHEDULER_add_now (&do_error, handle);
500 return; 524 return;
@@ -505,7 +529,7 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
505 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id)) 529 if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
506 GNUNET_RECLAIM_id_generate (&attribute->id); 530 GNUNET_RECLAIM_id_generate (&attribute->id);
507 exp = GNUNET_TIME_UNIT_HOURS; 531 exp = GNUNET_TIME_UNIT_HOURS;
508 handle->idp_op = GNUNET_RECLAIM_attestation_store (idp, 532 handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
509 identity_priv, 533 identity_priv,
510 attribute, 534 attribute,
511 &exp, 535 &exp,
@@ -516,52 +540,52 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
516 540
517 541
518/** 542/**
519 * Collect all attestations for an ego 543 * Collect all credentials for an ego
520 * 544 *
521 */ 545 */
522static void 546static void
523attest_collect (void *cls, 547cred_collect (void *cls,
524 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 548 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
525 const struct GNUNET_RECLAIM_Attestation *attest) 549 const struct GNUNET_RECLAIM_Credential *cred)
526{ 550{
527 struct RequestHandle *handle = cls; 551 struct RequestHandle *handle = cls;
528 struct GNUNET_RECLAIM_AttributeList *attrs; 552 struct GNUNET_RECLAIM_AttributeList *attrs;
529 struct GNUNET_RECLAIM_AttributeListEntry *ale; 553 struct GNUNET_RECLAIM_AttributeListEntry *ale;
530 struct GNUNET_TIME_Absolute exp; 554 struct GNUNET_TIME_Absolute exp;
531 json_t *attr_obj; 555 json_t *attr_obj;
532 json_t *attest_obj; 556 json_t *cred_obj;
533 const char *type; 557 const char *type;
534 char *tmp_value; 558 char *tmp_value;
535 char *id_str; 559 char *id_str;
536 char *issuer; 560 char *issuer;
537 561
538 562
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation: %s\n", 563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential: %s\n",
540 attest->name); 564 cred->name);
541 attrs = GNUNET_RECLAIM_attestation_get_attributes (attest); 565 attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
542 issuer = GNUNET_RECLAIM_attestation_get_issuer (attest); 566 issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
543 tmp_value = GNUNET_RECLAIM_attestation_value_to_string (attest->type, 567 tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
544 attest->data, 568 cred->data,
545 attest->data_size); 569 cred->data_size);
546 attest_obj = json_object (); 570 cred_obj = json_object ();
547 json_object_set_new (attest_obj, "value", json_string (tmp_value)); 571 json_object_set_new (cred_obj, "value", json_string (tmp_value));
548 json_object_set_new (attest_obj, "name", json_string (attest->name)); 572 json_object_set_new (cred_obj, "name", json_string (cred->name));
549 type = GNUNET_RECLAIM_attestation_number_to_typename (attest->type); 573 type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
550 json_object_set_new (attest_obj, "type", json_string (type)); 574 json_object_set_new (cred_obj, "type", json_string (type));
551 if (NULL != issuer) 575 if (NULL != issuer)
552 { 576 {
553 json_object_set_new (attest_obj, "issuer", json_string (issuer)); 577 json_object_set_new (cred_obj, "issuer", json_string (issuer));
554 GNUNET_free (issuer); 578 GNUNET_free (issuer);
555 } 579 }
556 if (GNUNET_OK == GNUNET_RECLAIM_attestation_get_expiration (attest, 580 if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
557 &exp)) 581 &exp))
558 { 582 {
559 json_object_set_new (attest_obj, "expiration", json_integer ( 583 json_object_set_new (cred_obj, "expiration", json_integer (
560 exp.abs_value_us)); 584 exp.abs_value_us));
561 } 585 }
562 id_str = GNUNET_STRINGS_data_to_string_alloc (&attest->id, 586 id_str = GNUNET_STRINGS_data_to_string_alloc (&cred->id,
563 sizeof(attest->id)); 587 sizeof(cred->id));
564 json_object_set_new (attest_obj, "id", json_string (id_str)); 588 json_object_set_new (cred_obj, "id", json_string (id_str));
565 GNUNET_free (tmp_value); 589 GNUNET_free (tmp_value);
566 GNUNET_free (id_str); 590 GNUNET_free (id_str);
567 if (NULL != attrs) 591 if (NULL != attrs)
@@ -582,27 +606,27 @@ attest_collect (void *cls,
582 type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type); 606 type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type);
583 json_object_set_new (attr_obj, "type", json_string (type)); 607 json_object_set_new (attr_obj, "type", json_string (type));
584 json_object_set_new (attr_obj, "id", json_string ("")); 608 json_object_set_new (attr_obj, "id", json_string (""));
585 json_object_set_new (attr_obj, "attestation", json_string ("")); 609 json_object_set_new (attr_obj, "credential", json_string (""));
586 json_array_append_new (attr_arr, attr_obj); 610 json_array_append_new (attr_arr, attr_obj);
587 GNUNET_free (tmp_value); 611 GNUNET_free (tmp_value);
588 } 612 }
589 json_object_set_new (attest_obj, "attributes", attr_arr); 613 json_object_set_new (cred_obj, "attributes", attr_arr);
590 } 614 }
591 json_array_append_new (handle->resp_object, attest_obj); 615 json_array_append_new (handle->resp_object, cred_obj);
592 GNUNET_RECLAIM_attribute_list_destroy (attrs); 616 GNUNET_RECLAIM_attribute_list_destroy (attrs);
593 GNUNET_RECLAIM_get_attestations_next (handle->attest_it); 617 GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
594} 618}
595 619
596 620
597/** 621/**
598 * Lists attestation for identity request 622 * Lists credential for identity request
599 * 623 *
600 * @param con_handle the connection handle 624 * @param con_handle the connection handle
601 * @param url the url 625 * @param url the url
602 * @param cls the RequestHandle 626 * @param cls the RequestHandle
603 */ 627 */
604static void 628static void
605list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, 629list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
606 const char *url, 630 const char *url,
607 void *cls) 631 void *cls)
608{ 632{
@@ -612,9 +636,9 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
612 char *identity; 636 char *identity;
613 637
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615 "Getting attestations for %s.\n", 639 "Getting credentials for %s.\n",
616 handle->url); 640 handle->url);
617 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION) >= strlen ( 641 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
618 handle->url)) 642 handle->url))
619 { 643 {
620 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); 644 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
@@ -622,7 +646,7 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
622 return; 646 return;
623 } 647 }
624 identity = handle->url + strlen ( 648 identity = handle->url + strlen (
625 GNUNET_REST_API_NS_RECLAIM_ATTESTATION) + 1; 649 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
626 650
627 for (ego_entry = ego_head; NULL != ego_entry; 651 for (ego_entry = ego_head; NULL != ego_entry;
628 ego_entry = ego_entry->next) 652 ego_entry = ego_entry->next)
@@ -639,11 +663,11 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
639 return; 663 return;
640 } 664 }
641 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); 665 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
642 handle->attest_it = GNUNET_RECLAIM_get_attestations_start (idp, 666 handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
643 priv_key, 667 priv_key,
644 &collect_error_cb, 668 &collect_error_cb,
645 handle, 669 handle,
646 &attest_collect, 670 &cred_collect,
647 handle, 671 handle,
648 & 672 &
649 collect_finished_cb, 673 collect_finished_cb,
@@ -652,27 +676,27 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
652 676
653 677
654/** 678/**
655 * Deletes attestation from an identity 679 * Deletes credential from an identity
656 * 680 *
657 * @param con_handle the connection handle 681 * @param con_handle the connection handle
658 * @param url the url 682 * @param url the url
659 * @param cls the RequestHandle 683 * @param cls the RequestHandle
660 */ 684 */
661static void 685static void
662delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, 686delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
663 const char *url, 687 const char *url,
664 void *cls) 688 void *cls)
665{ 689{
666 struct RequestHandle *handle = cls; 690 struct RequestHandle *handle = cls;
667 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 691 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
668 struct GNUNET_RECLAIM_Attestation attr; 692 struct GNUNET_RECLAIM_Credential attr;
669 struct EgoEntry *ego_entry; 693 struct EgoEntry *ego_entry;
670 char *identity_id_str; 694 char *identity_id_str;
671 char *identity; 695 char *identity;
672 char *id; 696 char *id;
673 697
674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n"); 698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
675 if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION) >= strlen ( 699 if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
676 handle->url)) 700 handle->url))
677 { 701 {
678 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); 702 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
@@ -681,7 +705,7 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
681 } 705 }
682 identity_id_str = 706 identity_id_str =
683 strdup (handle->url + strlen ( 707 strdup (handle->url + strlen (
684 GNUNET_REST_API_NS_RECLAIM_ATTESTATION) + 1); 708 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
685 identity = strtok (identity_id_str, "/"); 709 identity = strtok (identity_id_str, "/");
686 id = strtok (NULL, "/"); 710 id = strtok (NULL, "/");
687 if ((NULL == identity) || (NULL == id)) 711 if ((NULL == identity) || (NULL == id))
@@ -706,10 +730,10 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
706 return; 730 return;
707 } 731 }
708 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); 732 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
709 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attestation)); 733 memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
710 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id)); 734 GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
711 attr.name = ""; 735 attr.name = "";
712 handle->idp_op = GNUNET_RECLAIM_attestation_delete (idp, 736 handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
713 priv_key, 737 priv_key,
714 &attr, 738 &attr,
715 &delete_finished_cb, 739 &delete_finished_cb,
@@ -787,7 +811,7 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
787 json_t *data_json; 811 json_t *data_json;
788 json_error_t err; 812 json_error_t err;
789 struct GNUNET_JSON_Specification attrspec[] = 813 struct GNUNET_JSON_Specification attrspec[] =
790 { GNUNET_RECLAIM_JSON_spec_claim (&attribute), GNUNET_JSON_spec_end () }; 814 { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
791 815
792 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
793 "Adding an attribute for %s.\n", 817 "Adding an attribute for %s.\n",
@@ -853,13 +877,13 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
853/** 877/**
854 * Parse a JWT and return the respective claim value as Attribute 878 * Parse a JWT and return the respective claim value as Attribute
855 * 879 *
856 * @param attest the jwt attestation 880 * @param cred the jwt credential
857 * @param claim the name of the claim in the JWT 881 * @param claim the name of the claim in the JWT
858 * 882 *
859 * @return a GNUNET_RECLAIM_Attribute, containing the new value 883 * @return a GNUNET_RECLAIM_Attribute, containing the new value
860 */ 884 */
861struct GNUNET_RECLAIM_Attribute * 885struct GNUNET_RECLAIM_Attribute *
862parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest, 886parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
863 const char *claim) 887 const char *claim)
864{ 888{
865 char *jwt_string; 889 char *jwt_string;
@@ -875,9 +899,9 @@ parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest,
875 json_t *json_val; 899 json_t *json_val;
876 json_error_t *json_err = NULL; 900 json_error_t *json_err = NULL;
877 901
878 jwt_string = GNUNET_RECLAIM_attestation_value_to_string (attest->type, 902 jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
879 attest->data, 903 cred->data,
880 attest->data_size); 904 cred->data_size);
881 char *jwt_body = strtok (jwt_string, delim); 905 char *jwt_body = strtok (jwt_string, delim);
882 jwt_body = strtok (NULL, delim); 906 jwt_body = strtok (NULL, delim);
883 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body), 907 GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
@@ -903,16 +927,16 @@ parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest,
903 "Error: Referenced Claim Name not Found", 927 "Error: Referenced Claim Name not Found",
904 (void **) &data, 928 (void **) &data,
905 &data_size); 929 &data_size);
906 attr = GNUNET_RECLAIM_attribute_new (claim, &attest->id, 930 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
907 type, data, data_size); 931 type, data, data_size);
908 attr->id = attest->id; 932 attr->id = cred->id;
909 attr->flag = 1; 933 attr->flag = 1;
910 } 934 }
911 else 935 else
912 { 936 {
913 attr = GNUNET_RECLAIM_attribute_new (claim, &attest->id, 937 attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
914 type, data, data_size); 938 type, data, data_size);
915 attr->id = attest->id; 939 attr->id = cred->id;
916 attr->flag = 1; 940 attr->flag = 1;
917 } 941 }
918 return attr; 942 return attr;
@@ -941,7 +965,7 @@ attr_collect (void *cls,
941 json_object_set_new (attr_obj, "value", json_string (tmp_value)); 965 json_object_set_new (attr_obj, "value", json_string (tmp_value));
942 json_object_set_new (attr_obj, "name", json_string (attr->name)); 966 json_object_set_new (attr_obj, "name", json_string (attr->name));
943 967
944 if (GNUNET_RECLAIM_id_is_zero (&attr->attestation)) 968 if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
945 json_object_set_new (attr_obj, "flag", json_string ("0")); 969 json_object_set_new (attr_obj, "flag", json_string ("0"));
946 else 970 else
947 json_object_set_new (attr_obj, "flag", json_string ("1")); 971 json_object_set_new (attr_obj, "flag", json_string ("1"));
@@ -950,9 +974,9 @@ attr_collect (void *cls,
950 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id, 974 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
951 sizeof(attr->id)); 975 sizeof(attr->id));
952 json_object_set_new (attr_obj, "id", json_string (id_str)); 976 json_object_set_new (attr_obj, "id", json_string (id_str));
953 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->attestation, 977 id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
954 sizeof(attr->attestation)); 978 sizeof(attr->credential));
955 json_object_set_new (attr_obj, "attestation", json_string (id_str)); 979 json_object_set_new (attr_obj, "credential", json_string (id_str));
956 json_array_append (handle->resp_object, attr_obj); 980 json_array_append (handle->resp_object, attr_obj);
957 json_decref (attr_obj); 981 json_decref (attr_obj);
958 GNUNET_free (tmp_value); 982 GNUNET_free (tmp_value);
@@ -1156,7 +1180,7 @@ static void
1156consume_cont (void *cls, 1180consume_cont (void *cls,
1157 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, 1181 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1158 const struct GNUNET_RECLAIM_Attribute *attr, 1182 const struct GNUNET_RECLAIM_Attribute *attr,
1159 const struct GNUNET_RECLAIM_Attestation *attest) 1183 const struct GNUNET_RECLAIM_Presentation *pres)
1160{ 1184{
1161 struct RequestHandle *handle = cls; 1185 struct RequestHandle *handle = cls;
1162 char *val_str; 1186 char *val_str;
@@ -1403,11 +1427,11 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1403 { MHD_HTTP_METHOD_DELETE, 1427 { MHD_HTTP_METHOD_DELETE,
1404 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont }, 1428 GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
1405 { MHD_HTTP_METHOD_GET, 1429 { MHD_HTTP_METHOD_GET,
1406 GNUNET_REST_API_NS_RECLAIM_ATTESTATION, &list_attestation_cont }, 1430 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
1407 { MHD_HTTP_METHOD_POST, 1431 { MHD_HTTP_METHOD_POST,
1408 GNUNET_REST_API_NS_RECLAIM_ATTESTATION, &add_attestation_cont }, 1432 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
1409 { MHD_HTTP_METHOD_DELETE, 1433 { MHD_HTTP_METHOD_DELETE,
1410 GNUNET_REST_API_NS_RECLAIM_ATTESTATION, &delete_attestation_cont }, 1434 GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
1411 { MHD_HTTP_METHOD_GET, 1435 { MHD_HTTP_METHOD_GET,
1412 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont }, 1436 GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
1413 { MHD_HTTP_METHOD_POST, 1437 { MHD_HTTP_METHOD_POST,
@@ -1422,12 +1446,16 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1422 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 1446 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1423 handle->proc_cls = proc_cls; 1447 handle->proc_cls = proc_cls;
1424 handle->proc = proc; 1448 handle->proc = proc;
1425 state = ID_REST_STATE_INIT;
1426 handle->rest_handle = rest_handle; 1449 handle->rest_handle = rest_handle;
1427 1450
1428 handle->url = GNUNET_strdup (rest_handle->url); 1451 handle->url = GNUNET_strdup (rest_handle->url);
1429 if (handle->url[strlen (handle->url) - 1] == '/') 1452 if (handle->url[strlen (handle->url) - 1] == '/')
1430 handle->url[strlen (handle->url) - 1] = '\0'; 1453 handle->url[strlen (handle->url) - 1] = '\0';
1454 handle->timeout_task =
1455 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1456 GNUNET_CONTAINER_DLL_insert (requests_head,
1457 requests_tail,
1458 handle);
1431 if (GNUNET_NO == 1459 if (GNUNET_NO ==
1432 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) 1460 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1433 { 1461 {
@@ -1435,8 +1463,6 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1435 return GNUNET_NO; 1463 return GNUNET_NO;
1436 } 1464 }
1437 1465
1438 handle->timeout_task =
1439 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
1440 return GNUNET_YES; 1466 return GNUNET_YES;
1441} 1467}
1442 1468
@@ -1470,6 +1496,7 @@ libgnunet_plugin_rest_reclaim_init (void *cls)
1470 MHD_HTTP_METHOD_DELETE, 1496 MHD_HTTP_METHOD_DELETE,
1471 MHD_HTTP_METHOD_OPTIONS); 1497 MHD_HTTP_METHOD_OPTIONS);
1472 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); 1498 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1499 state = ID_REST_STATE_INIT;
1473 idp = GNUNET_RECLAIM_connect (cfg); 1500 idp = GNUNET_RECLAIM_connect (cfg);
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475 _ ("Identity Provider REST API initialized\n")); 1502 _ ("Identity Provider REST API initialized\n"));
@@ -1488,10 +1515,13 @@ libgnunet_plugin_rest_reclaim_done (void *cls)
1488{ 1515{
1489 struct GNUNET_REST_Plugin *api = cls; 1516 struct GNUNET_REST_Plugin *api = cls;
1490 struct Plugin *plugin = api->cls; 1517 struct Plugin *plugin = api->cls;
1518 struct RequestHandle *request;
1491 struct EgoEntry *ego_entry; 1519 struct EgoEntry *ego_entry;
1492 struct EgoEntry *ego_tmp; 1520 struct EgoEntry *ego_tmp;
1493 1521
1494 plugin->cfg = NULL; 1522 plugin->cfg = NULL;
1523 while (NULL != (request = requests_head))
1524 do_error (request);
1495 if (NULL != idp) 1525 if (NULL != idp)
1496 GNUNET_RECLAIM_disconnect (idp); 1526 GNUNET_RECLAIM_disconnect (idp);
1497 if (NULL != identity_handle) 1527 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
139 uint16_t attr_len GNUNET_PACKED; 139 uint16_t attr_len GNUNET_PACKED;
140 140
141 /** 141 /**
142 * Length of serialized attestation data 142 * Length of serialized credential data
143 */ 143 */
144 uint16_t attestation_len GNUNET_PACKED; 144 uint16_t credential_len GNUNET_PACKED;
145 145
146 /** 146 /**
147 * always zero (for alignment) 147 * always zero (for alignment)
@@ -159,9 +159,9 @@ struct AttributeResultMessage
159}; 159};
160 160
161/** 161/**
162 * Attestation is returned from the idp. 162 * Credential is returned from the idp.
163 */ 163 */
164struct AttestationResultMessage 164struct CredentialResultMessage
165{ 165{
166 /** 166 /**
167 * Message header 167 * Message header
@@ -176,7 +176,7 @@ struct AttestationResultMessage
176 /** 176 /**
177 * Length of serialized attribute data 177 * Length of serialized attribute data
178 */ 178 */
179 uint16_t attestation_len GNUNET_PACKED; 179 uint16_t credential_len GNUNET_PACKED;
180 180
181 /** 181 /**
182 * always zero (for alignment) 182 * always zero (for alignment)
@@ -189,7 +189,7 @@ struct AttestationResultMessage
189 struct GNUNET_CRYPTO_EcdsaPublicKey identity; 189 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
190 190
191 /* followed by: 191 /* followed by:
192 * serialized attestation data 192 * serialized credential data
193 */ 193 */
194}; 194};
195 195
@@ -234,9 +234,9 @@ struct AttributeIterationNextMessage
234 234
235 235
236/** 236/**
237 * Start a attestation iteration for the given identity 237 * Start a credential iteration for the given identity
238 */ 238 */
239struct AttestationIterationStartMessage 239struct CredentialIterationStartMessage
240{ 240{
241 /** 241 /**
242 * Message 242 * Message
@@ -256,9 +256,9 @@ struct AttestationIterationStartMessage
256 256
257 257
258/** 258/**
259 * Ask for next result of attestation iteration for the given operation 259 * Ask for next result of credential iteration for the given operation
260 */ 260 */
261struct AttestationIterationNextMessage 261struct CredentialIterationNextMessage
262{ 262{
263 /** 263 /**
264 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT 264 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
@@ -273,9 +273,9 @@ struct AttestationIterationNextMessage
273 273
274 274
275/** 275/**
276 * Stop attestation iteration for the given operation 276 * Stop credential iteration for the given operation
277 */ 277 */
278struct AttestationIterationStopMessage 278struct CredentialIterationStopMessage
279{ 279{
280 /** 280 /**
281 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP 281 * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
@@ -463,9 +463,16 @@ struct TicketResultMessage
463 uint32_t id GNUNET_PACKED; 463 uint32_t id GNUNET_PACKED;
464 464
465 /** 465 /**
466 * Length of new presentations created
467 */
468 uint32_t presentations_len GNUNET_PACKED;
469
470 /**
466 * The new ticket 471 * The new ticket
467 */ 472 */
468 struct GNUNET_RECLAIM_Ticket ticket; 473 struct GNUNET_RECLAIM_Ticket ticket;
474
475 /* Followed by the serialized GNUNET_RECLAIM_PresentationList */
469}; 476};
470 477
471/** 478/**
@@ -520,9 +527,9 @@ struct ConsumeTicketResultMessage
520 uint16_t attrs_len GNUNET_PACKED; 527 uint16_t attrs_len GNUNET_PACKED;
521 528
522 /** 529 /**
523 * Length of attestation data 530 * Length of presentation data
524 */ 531 */
525 uint16_t attestations_len; 532 uint16_t presentations_len;
526 533
527 /** 534 /**
528 * always zero (for alignment) 535 * 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
77 GNUNET_RECLAIM_AttributeTicketResult atr_cb; 77 GNUNET_RECLAIM_AttributeTicketResult atr_cb;
78 78
79 /** 79 /**
80 * Attestation result callback 80 * Credential result callback
81 */ 81 */
82 GNUNET_RECLAIM_AttestationResult at_cb; 82 GNUNET_RECLAIM_CredentialResult at_cb;
83 83
84 /** 84 /**
85 * Revocation result callback 85 * Revocation result callback
@@ -92,6 +92,11 @@ struct GNUNET_RECLAIM_Operation
92 GNUNET_RECLAIM_TicketCallback tr_cb; 92 GNUNET_RECLAIM_TicketCallback tr_cb;
93 93
94 /** 94 /**
95 * Ticket issue result callback
96 */
97 GNUNET_RECLAIM_IssueTicketCallback ti_cb;
98
99 /**
95 * Envelope with the message for this queue entry. 100 * Envelope with the message for this queue entry.
96 */ 101 */
97 struct GNUNET_MQ_Envelope *env; 102 struct GNUNET_MQ_Envelope *env;
@@ -239,19 +244,19 @@ struct GNUNET_RECLAIM_AttributeIterator
239}; 244};
240 245
241/** 246/**
242 * Handle for a attestation iterator operation 247 * Handle for a credential iterator operation
243 */ 248 */
244struct GNUNET_RECLAIM_AttestationIterator 249struct GNUNET_RECLAIM_CredentialIterator
245{ 250{
246 /** 251 /**
247 * Kept in a DLL. 252 * Kept in a DLL.
248 */ 253 */
249 struct GNUNET_RECLAIM_AttestationIterator *next; 254 struct GNUNET_RECLAIM_CredentialIterator *next;
250 255
251 /** 256 /**
252 * Kept in a DLL. 257 * Kept in a DLL.
253 */ 258 */
254 struct GNUNET_RECLAIM_AttestationIterator *prev; 259 struct GNUNET_RECLAIM_CredentialIterator *prev;
255 260
256 /** 261 /**
257 * Main handle to access the service. 262 * Main handle to access the service.
@@ -271,7 +276,7 @@ struct GNUNET_RECLAIM_AttestationIterator
271 /** 276 /**
272 * The continuation to call with the results 277 * The continuation to call with the results
273 */ 278 */
274 GNUNET_RECLAIM_AttestationResult proc; 279 GNUNET_RECLAIM_CredentialResult proc;
275 280
276 /** 281 /**
277 * Closure for @e proc. 282 * Closure for @e proc.
@@ -349,12 +354,12 @@ struct GNUNET_RECLAIM_Handle
349 /** 354 /**
350 * Head of active iterations 355 * Head of active iterations
351 */ 356 */
352 struct GNUNET_RECLAIM_AttestationIterator *ait_head; 357 struct GNUNET_RECLAIM_CredentialIterator *ait_head;
353 358
354 /** 359 /**
355 * Tail of active iterations 360 * Tail of active iterations
356 */ 361 */
357 struct GNUNET_RECLAIM_AttestationIterator *ait_tail; 362 struct GNUNET_RECLAIM_CredentialIterator *ait_tail;
358 363
359 /** 364 /**
360 * Head of active iterations 365 * Head of active iterations
@@ -464,7 +469,7 @@ free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
464 * @param ait entry to free 469 * @param ait entry to free
465 */ 470 */
466static void 471static void
467free_ait (struct GNUNET_RECLAIM_AttestationIterator *ait) 472free_ait (struct GNUNET_RECLAIM_CredentialIterator *ait)
468{ 473{
469 struct GNUNET_RECLAIM_Handle *h = ait->h; 474 struct GNUNET_RECLAIM_Handle *h = ait->h;
470 475
@@ -561,13 +566,13 @@ check_consume_ticket_result (void *cls,
561{ 566{
562 size_t msg_len; 567 size_t msg_len;
563 size_t attrs_len; 568 size_t attrs_len;
564 size_t attests_len; 569 size_t pl_len;
565 570
566 msg_len = ntohs (msg->header.size); 571 msg_len = ntohs (msg->header.size);
567 attrs_len = ntohs (msg->attrs_len); 572 attrs_len = ntohs (msg->attrs_len);
568 attests_len = ntohs (msg->attestations_len); 573 pl_len = ntohs (msg->presentations_len);
569 if (msg_len != 574 if (msg_len !=
570 sizeof(struct ConsumeTicketResultMessage) + attrs_len + attests_len) 575 sizeof(struct ConsumeTicketResultMessage) + attrs_len + pl_len)
571 { 576 {
572 GNUNET_break (0); 577 GNUNET_break (0);
573 return GNUNET_SYSERR; 578 return GNUNET_SYSERR;
@@ -590,12 +595,12 @@ handle_consume_ticket_result (void *cls,
590 struct GNUNET_RECLAIM_Handle *h = cls; 595 struct GNUNET_RECLAIM_Handle *h = cls;
591 struct GNUNET_RECLAIM_Operation *op; 596 struct GNUNET_RECLAIM_Operation *op;
592 size_t attrs_len; 597 size_t attrs_len;
593 size_t attests_len; 598 size_t pl_len;
594 uint32_t r_id = ntohl (msg->id); 599 uint32_t r_id = ntohl (msg->id);
595 char *read_ptr; 600 char *read_ptr;
596 601
597 attrs_len = ntohs (msg->attrs_len); 602 attrs_len = ntohs (msg->attrs_len);
598 attests_len = ntohs (msg->attestations_len); 603 pl_len = ntohs (msg->presentations_len);
599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n"); 604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
600 605
601 606
@@ -608,13 +613,12 @@ handle_consume_ticket_result (void *cls,
608 { 613 {
609 struct GNUNET_RECLAIM_AttributeList *attrs; 614 struct GNUNET_RECLAIM_AttributeList *attrs;
610 struct GNUNET_RECLAIM_AttributeListEntry *le; 615 struct GNUNET_RECLAIM_AttributeListEntry *le;
611 struct GNUNET_RECLAIM_AttestationList *attests; 616 struct GNUNET_RECLAIM_PresentationList *pl;
612 struct GNUNET_RECLAIM_AttestationListEntry *ale; 617 struct GNUNET_RECLAIM_PresentationListEntry *ple;
613 attrs = 618 attrs =
614 GNUNET_RECLAIM_attribute_list_deserialize ((char *) &msg[1], attrs_len); 619 GNUNET_RECLAIM_attribute_list_deserialize ((char *) &msg[1], attrs_len);
615 read_ptr = ((char *) &msg[1]) + attrs_len; 620 read_ptr = ((char *) &msg[1]) + attrs_len;
616 attests = 621 pl = GNUNET_RECLAIM_presentation_list_deserialize (read_ptr, pl_len);
617 GNUNET_RECLAIM_attestation_list_deserialize (read_ptr, attests_len);
618 if (NULL != op->atr_cb) 622 if (NULL != op->atr_cb)
619 { 623 {
620 if (NULL == attrs) 624 if (NULL == attrs)
@@ -626,22 +630,22 @@ handle_consume_ticket_result (void *cls,
626 for (le = attrs->list_head; NULL != le; le = le->next) 630 for (le = attrs->list_head; NULL != le; le = le->next)
627 { 631 {
628 if (GNUNET_NO == 632 if (GNUNET_NO ==
629 GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation)) 633 GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
630 { 634 {
631 for (ale = attests->list_head; NULL != ale; ale = ale->next) 635 for (ple = pl->list_head; NULL != ple; ple = ple->next)
632 { 636 {
633 if (GNUNET_YES == 637 if (GNUNET_YES ==
634 GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation, 638 GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
635 &ale->attestation->id)) 639 &ple->presentation->credential_id))
636 { 640 {
637 op->atr_cb (op->cls, &msg->identity, 641 op->atr_cb (op->cls, &msg->identity,
638 le->attribute, ale->attestation); 642 le->attribute, ple->presentation);
639 break; 643 break;
640 } 644 }
641 645
642 } 646 }
643 } 647 }
644 else // No attestations 648 else // No credentials
645 { 649 {
646 op->atr_cb (op->cls, &msg->identity, 650 op->atr_cb (op->cls, &msg->identity,
647 le->attribute, NULL); 651 le->attribute, NULL);
@@ -649,10 +653,10 @@ handle_consume_ticket_result (void *cls,
649 } 653 }
650 if (NULL != attrs) 654 if (NULL != attrs)
651 GNUNET_RECLAIM_attribute_list_destroy (attrs); 655 GNUNET_RECLAIM_attribute_list_destroy (attrs);
652 if (NULL != attests) 656 if (NULL != pl)
653 GNUNET_RECLAIM_attestation_list_destroy (attests); 657 GNUNET_RECLAIM_presentation_list_destroy (pl);
654 attrs = NULL; 658 attrs = NULL;
655 attests = NULL; 659 pl = NULL;
656 } 660 }
657 op->atr_cb (op->cls, NULL, NULL, NULL); 661 op->atr_cb (op->cls, NULL, NULL, NULL);
658 } 662 }
@@ -747,7 +751,8 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
747 751
748 { 752 {
749 struct GNUNET_RECLAIM_Attribute *attr; 753 struct GNUNET_RECLAIM_Attribute *attr;
750 attr = GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len); 754 GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len,
755 &attr);
751 if (NULL != it) 756 if (NULL != it)
752 { 757 {
753 if (NULL != it->proc) 758 if (NULL != it->proc)
@@ -767,21 +772,21 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
767 772
768/** 773/**
769 * Handle an incoming message of type 774 * Handle an incoming message of type
770 * #GNUNET_MESSAGE_TYPE_RECLAIM_attestation_RESULT 775 * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
771 * 776 *
772 * @param cls 777 * @param cls
773 * @param msg the message we received 778 * @param msg the message we received
774 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 779 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
775 */ 780 */
776static int 781static int
777check_attestation_result (void *cls, const struct AttestationResultMessage *msg) 782check_credential_result (void *cls, const struct CredentialResultMessage *msg)
778{ 783{
779 size_t msg_len; 784 size_t msg_len;
780 size_t attest_len; 785 size_t cred_len;
781 786
782 msg_len = ntohs (msg->header.size); 787 msg_len = ntohs (msg->header.size);
783 attest_len = ntohs (msg->attestation_len); 788 cred_len = ntohs (msg->credential_len);
784 if (msg_len != sizeof(struct AttestationResultMessage) + attest_len) 789 if (msg_len != sizeof(struct CredentialResultMessage) + cred_len)
785 { 790 {
786 GNUNET_break (0); 791 GNUNET_break (0);
787 return GNUNET_SYSERR; 792 return GNUNET_SYSERR;
@@ -792,24 +797,24 @@ check_attestation_result (void *cls, const struct AttestationResultMessage *msg)
792 797
793/** 798/**
794 * Handle an incoming message of type 799 * Handle an incoming message of type
795 * #GNUNET_MESSAGE_TYPE_RECLAIM_attestation_RESULT 800 * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
796 * 801 *
797 * @param cls 802 * @param cls
798 * @param msg the message we received 803 * @param msg the message we received
799 */ 804 */
800static void 805static void
801handle_attestation_result (void *cls, const struct 806handle_credential_result (void *cls, const struct
802 AttestationResultMessage *msg) 807 CredentialResultMessage *msg)
803{ 808{
804 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy; 809 static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
805 struct GNUNET_RECLAIM_Handle *h = cls; 810 struct GNUNET_RECLAIM_Handle *h = cls;
806 struct GNUNET_RECLAIM_AttestationIterator *it; 811 struct GNUNET_RECLAIM_CredentialIterator *it;
807 struct GNUNET_RECLAIM_Operation *op; 812 struct GNUNET_RECLAIM_Operation *op;
808 size_t att_len; 813 size_t att_len;
809 uint32_t r_id = ntohl (msg->id); 814 uint32_t r_id = ntohl (msg->id);
810 815
811 att_len = ntohs (msg->attestation_len); 816 att_len = ntohs (msg->credential_len);
812 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attestation result.\n"); 817 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing credential result.\n");
813 818
814 819
815 for (it = h->ait_head; NULL != it; it = it->next) 820 for (it = h->ait_head; NULL != it; it = it->next)
@@ -847,8 +852,8 @@ handle_attestation_result (void *cls, const struct
847 } 852 }
848 853
849 { 854 {
850 struct GNUNET_RECLAIM_Attestation *att; 855 struct GNUNET_RECLAIM_Credential *att;
851 att = GNUNET_RECLAIM_attestation_deserialize ((char *) &msg[1], att_len); 856 att = GNUNET_RECLAIM_credential_deserialize ((char *) &msg[1], att_len);
852 857
853 if (NULL != it) 858 if (NULL != it)
854 { 859 {
@@ -866,6 +871,30 @@ handle_attestation_result (void *cls, const struct
866 GNUNET_assert (0); 871 GNUNET_assert (0);
867} 872}
868 873
874/**
875 * Handle an incoming message of type
876 * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
877 *
878 * @param cls
879 * @param msg the message we received
880 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
881 */
882static int
883check_ticket_result (void *cls, const struct TicketResultMessage *msg)
884{
885 size_t msg_len;
886 size_t pres_len;
887
888 msg_len = ntohs (msg->header.size);
889 pres_len = ntohs (msg->presentations_len);
890 if (msg_len != sizeof(struct TicketResultMessage) + pres_len)
891 {
892 GNUNET_break (0);
893 return GNUNET_SYSERR;
894 }
895 return GNUNET_OK;
896}
897
869 898
870/** 899/**
871 * Handle an incoming message of type 900 * Handle an incoming message of type
@@ -880,8 +909,10 @@ handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
880 struct GNUNET_RECLAIM_Handle *handle = cls; 909 struct GNUNET_RECLAIM_Handle *handle = cls;
881 struct GNUNET_RECLAIM_Operation *op; 910 struct GNUNET_RECLAIM_Operation *op;
882 struct GNUNET_RECLAIM_TicketIterator *it; 911 struct GNUNET_RECLAIM_TicketIterator *it;
912 struct GNUNET_RECLAIM_PresentationList *pres;
883 uint32_t r_id = ntohl (msg->id); 913 uint32_t r_id = ntohl (msg->id);
884 static const struct GNUNET_RECLAIM_Ticket ticket; 914 static const struct GNUNET_RECLAIM_Ticket ticket;
915 uint32_t pres_len = ntohs (msg->presentations_len);
885 916
886 for (op = handle->op_head; NULL != op; op = op->next) 917 for (op = handle->op_head; NULL != op; op = op->next)
887 if (op->r_id == r_id) 918 if (op->r_id == r_id)
@@ -893,18 +924,25 @@ handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
893 return; 924 return;
894 if (NULL != op) 925 if (NULL != op)
895 { 926 {
927 if (0 < pres_len)
928 pres = GNUNET_RECLAIM_presentation_list_deserialize ((char*)&msg[1],
929 pres_len);
896 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op); 930 GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
897 if (0 == 931 if (0 ==
898 memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket))) 932 memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
899 { 933 {
900 if (NULL != op->tr_cb) 934 if (NULL != op->ti_cb)
901 op->tr_cb (op->cls, NULL); 935 op->ti_cb (op->cls, NULL, NULL);
902 } 936 }
903 else 937 else
904 { 938 {
905 if (NULL != op->tr_cb) 939 if (NULL != op->ti_cb)
906 op->tr_cb (op->cls, &msg->ticket); 940 op->ti_cb (op->cls,
941 &msg->ticket,
942 (0 < pres_len) ? pres : NULL);
907 } 943 }
944 if (0 < pres_len)
945 GNUNET_RECLAIM_presentation_list_destroy (pres);
908 free_op (op); 946 free_op (op);
909 return; 947 return;
910 } 948 }
@@ -985,14 +1023,14 @@ reconnect (struct GNUNET_RECLAIM_Handle *h)
985 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT, 1023 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
986 struct AttributeResultMessage, 1024 struct AttributeResultMessage,
987 h), 1025 h),
988 GNUNET_MQ_hd_var_size (attestation_result, 1026 GNUNET_MQ_hd_var_size (credential_result,
989 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT, 1027 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT,
990 struct AttestationResultMessage, 1028 struct CredentialResultMessage,
1029 h),
1030 GNUNET_MQ_hd_var_size (ticket_result,
1031 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
1032 struct TicketResultMessage,
991 h), 1033 h),
992 GNUNET_MQ_hd_fixed_size (ticket_result,
993 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
994 struct TicketResultMessage,
995 h),
996 GNUNET_MQ_hd_var_size (consume_ticket_result, 1034 GNUNET_MQ_hd_var_size (consume_ticket_result,
997 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT, 1035 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
998 struct ConsumeTicketResultMessage, 1036 struct ConsumeTicketResultMessage,
@@ -1174,22 +1212,22 @@ GNUNET_RECLAIM_attribute_delete (
1174 1212
1175 1213
1176/** 1214/**
1177 * Store an attestation. If the attestation is already present, 1215 * Store an credential. If the credential is already present,
1178 * it is replaced with the new attestation. 1216 * it is replaced with the new credential.
1179 * 1217 *
1180 * @param h handle to the re:claimID service 1218 * @param h handle to the re:claimID service
1181 * @param pkey private key of the identity 1219 * @param pkey private key of the identity
1182 * @param attr the attestation value 1220 * @param attr the credential value
1183 * @param exp_interval the relative expiration interval for the attestation 1221 * @param exp_interval the relative expiration interval for the credential
1184 * @param cont continuation to call when done 1222 * @param cont continuation to call when done
1185 * @param cont_cls closure for @a cont 1223 * @param cont_cls closure for @a cont
1186 * @return handle to abort the request 1224 * @return handle to abort the request
1187 */ 1225 */
1188struct GNUNET_RECLAIM_Operation * 1226struct GNUNET_RECLAIM_Operation *
1189GNUNET_RECLAIM_attestation_store ( 1227GNUNET_RECLAIM_credential_store (
1190 struct GNUNET_RECLAIM_Handle *h, 1228 struct GNUNET_RECLAIM_Handle *h,
1191 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, 1229 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1192 const struct GNUNET_RECLAIM_Attestation *attr, 1230 const struct GNUNET_RECLAIM_Credential *attr,
1193 const struct GNUNET_TIME_Relative *exp_interval, 1231 const struct GNUNET_TIME_Relative *exp_interval,
1194 GNUNET_RECLAIM_ContinuationWithStatus cont, 1232 GNUNET_RECLAIM_ContinuationWithStatus cont,
1195 void *cont_cls) 1233 void *cont_cls)
@@ -1204,15 +1242,15 @@ GNUNET_RECLAIM_attestation_store (
1204 op->cls = cont_cls; 1242 op->cls = cont_cls;
1205 op->r_id = h->r_id_gen++; 1243 op->r_id = h->r_id_gen++;
1206 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); 1244 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1207 attr_len = GNUNET_RECLAIM_attestation_serialize_get_size (attr); 1245 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
1208 op->env = GNUNET_MQ_msg_extra (sam, 1246 op->env = GNUNET_MQ_msg_extra (sam,
1209 attr_len, 1247 attr_len,
1210 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE); 1248 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE);
1211 sam->identity = *pkey; 1249 sam->identity = *pkey;
1212 sam->id = htonl (op->r_id); 1250 sam->id = htonl (op->r_id);
1213 sam->exp = GNUNET_htonll (exp_interval->rel_value_us); 1251 sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1214 1252
1215 GNUNET_RECLAIM_attestation_serialize (attr, (char *) &sam[1]); 1253 GNUNET_RECLAIM_credential_serialize (attr, (char *) &sam[1]);
1216 1254
1217 sam->attr_len = htons (attr_len); 1255 sam->attr_len = htons (attr_len);
1218 if (NULL != h->mq) 1256 if (NULL != h->mq)
@@ -1222,21 +1260,21 @@ GNUNET_RECLAIM_attestation_store (
1222 1260
1223 1261
1224/** 1262/**
1225 * Delete an attestation. Tickets used to share this attestation are updated 1263 * Delete an credential. Tickets used to share this credential are updated
1226 * accordingly. 1264 * accordingly.
1227 * 1265 *
1228 * @param h handle to the re:claimID service 1266 * @param h handle to the re:claimID service
1229 * @param pkey Private key of the identity to add an attribute to 1267 * @param pkey Private key of the identity to add an attribute to
1230 * @param attr The attestation 1268 * @param attr The credential
1231 * @param cont Continuation to call when done 1269 * @param cont Continuation to call when done
1232 * @param cont_cls Closure for @a cont 1270 * @param cont_cls Closure for @a cont
1233 * @return handle Used to to abort the request 1271 * @return handle Used to to abort the request
1234 */ 1272 */
1235struct GNUNET_RECLAIM_Operation * 1273struct GNUNET_RECLAIM_Operation *
1236GNUNET_RECLAIM_attestation_delete ( 1274GNUNET_RECLAIM_credential_delete (
1237 struct GNUNET_RECLAIM_Handle *h, 1275 struct GNUNET_RECLAIM_Handle *h,
1238 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, 1276 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1239 const struct GNUNET_RECLAIM_Attestation *attr, 1277 const struct GNUNET_RECLAIM_Credential *attr,
1240 GNUNET_RECLAIM_ContinuationWithStatus cont, 1278 GNUNET_RECLAIM_ContinuationWithStatus cont,
1241 void *cont_cls) 1279 void *cont_cls)
1242{ 1280{
@@ -1250,13 +1288,13 @@ GNUNET_RECLAIM_attestation_delete (
1250 op->cls = cont_cls; 1288 op->cls = cont_cls;
1251 op->r_id = h->r_id_gen++; 1289 op->r_id = h->r_id_gen++;
1252 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); 1290 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1253 attr_len = GNUNET_RECLAIM_attestation_serialize_get_size (attr); 1291 attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
1254 op->env = GNUNET_MQ_msg_extra (dam, 1292 op->env = GNUNET_MQ_msg_extra (dam,
1255 attr_len, 1293 attr_len,
1256 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE); 1294 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE);
1257 dam->identity = *pkey; 1295 dam->identity = *pkey;
1258 dam->id = htonl (op->r_id); 1296 dam->id = htonl (op->r_id);
1259 GNUNET_RECLAIM_attestation_serialize (attr, (char *) &dam[1]); 1297 GNUNET_RECLAIM_credential_serialize (attr, (char *) &dam[1]);
1260 1298
1261 dam->attr_len = htons (attr_len); 1299 dam->attr_len = htons (attr_len);
1262 if (NULL != h->mq) 1300 if (NULL != h->mq)
@@ -1375,12 +1413,12 @@ GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1375 1413
1376 1414
1377/** 1415/**
1378 * List all attestations for a local identity. 1416 * List all credentials for a local identity.
1379 * This MUST lock the `struct GNUNET_RECLAIM_Handle` 1417 * This MUST lock the `struct GNUNET_RECLAIM_Handle`
1380 * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and 1418 * for any other calls than #GNUNET_RECLAIM_get_credentials_next() and
1381 * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once 1419 * #GNUNET_RECLAIM_get_credentials_stop. @a proc will be called once
1382 * immediately, and then again after 1420 * immediately, and then again after
1383 * #GNUNET_RECLAIM_get_attestations_next() is invoked. 1421 * #GNUNET_RECLAIM_get_credentials_next() is invoked.
1384 * 1422 *
1385 * On error (disconnect), @a error_cb will be invoked. 1423 * On error (disconnect), @a error_cb will be invoked.
1386 * On normal completion, @a finish_cb proc will be 1424 * On normal completion, @a finish_cb proc will be
@@ -1391,31 +1429,31 @@ GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1391 * @param error_cb Function to call on error (i.e. disconnect), 1429 * @param error_cb Function to call on error (i.e. disconnect),
1392 * the handle is afterwards invalid 1430 * the handle is afterwards invalid
1393 * @param error_cb_cls Closure for @a error_cb 1431 * @param error_cb_cls Closure for @a error_cb
1394 * @param proc Function to call on each attestation 1432 * @param proc Function to call on each credential
1395 * @param proc_cls Closure for @a proc 1433 * @param proc_cls Closure for @a proc
1396 * @param finish_cb Function to call on completion 1434 * @param finish_cb Function to call on completion
1397 * the handle is afterwards invalid 1435 * the handle is afterwards invalid
1398 * @param finish_cb_cls Closure for @a finish_cb 1436 * @param finish_cb_cls Closure for @a finish_cb
1399 * @return an iterator Handle to use for iteration 1437 * @return an iterator Handle to use for iteration
1400 */ 1438 */
1401struct GNUNET_RECLAIM_AttestationIterator * 1439struct GNUNET_RECLAIM_CredentialIterator *
1402GNUNET_RECLAIM_get_attestations_start ( 1440GNUNET_RECLAIM_get_credentials_start (
1403 struct GNUNET_RECLAIM_Handle *h, 1441 struct GNUNET_RECLAIM_Handle *h,
1404 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, 1442 const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1405 GNUNET_SCHEDULER_TaskCallback error_cb, 1443 GNUNET_SCHEDULER_TaskCallback error_cb,
1406 void *error_cb_cls, 1444 void *error_cb_cls,
1407 GNUNET_RECLAIM_AttestationResult proc, 1445 GNUNET_RECLAIM_CredentialResult proc,
1408 void *proc_cls, 1446 void *proc_cls,
1409 GNUNET_SCHEDULER_TaskCallback finish_cb, 1447 GNUNET_SCHEDULER_TaskCallback finish_cb,
1410 void *finish_cb_cls) 1448 void *finish_cb_cls)
1411{ 1449{
1412 struct GNUNET_RECLAIM_AttestationIterator *ait; 1450 struct GNUNET_RECLAIM_CredentialIterator *ait;
1413 struct GNUNET_MQ_Envelope *env; 1451 struct GNUNET_MQ_Envelope *env;
1414 struct AttestationIterationStartMessage *msg; 1452 struct CredentialIterationStartMessage *msg;
1415 uint32_t rid; 1453 uint32_t rid;
1416 1454
1417 rid = h->r_id_gen++; 1455 rid = h->r_id_gen++;
1418 ait = GNUNET_new (struct GNUNET_RECLAIM_AttestationIterator); 1456 ait = GNUNET_new (struct GNUNET_RECLAIM_CredentialIterator);
1419 ait->h = h; 1457 ait->h = h;
1420 ait->error_cb = error_cb; 1458 ait->error_cb = error_cb;
1421 ait->error_cb_cls = error_cb_cls; 1459 ait->error_cb_cls = error_cb_cls;
@@ -1428,7 +1466,7 @@ GNUNET_RECLAIM_get_attestations_start (
1428 GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait); 1466 GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
1429 env = 1467 env =
1430 GNUNET_MQ_msg (msg, 1468 GNUNET_MQ_msg (msg,
1431 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START); 1469 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START);
1432 msg->id = htonl (rid); 1470 msg->id = htonl (rid);
1433 msg->identity = *identity; 1471 msg->identity = *identity;
1434 if (NULL == h->mq) 1472 if (NULL == h->mq)
@@ -1440,21 +1478,21 @@ GNUNET_RECLAIM_get_attestations_start (
1440 1478
1441 1479
1442/** 1480/**
1443 * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start 1481 * Calls the record processor specified in #GNUNET_RECLAIM_get_credential_start
1444 * for the next record. 1482 * for the next record.
1445 * 1483 *
1446 * @param it the iterator 1484 * @param it the iterator
1447 */ 1485 */
1448void 1486void
1449GNUNET_RECLAIM_get_attestations_next (struct 1487GNUNET_RECLAIM_get_credentials_next (struct
1450 GNUNET_RECLAIM_AttestationIterator *ait) 1488 GNUNET_RECLAIM_CredentialIterator *ait)
1451{ 1489{
1452 struct GNUNET_RECLAIM_Handle *h = ait->h; 1490 struct GNUNET_RECLAIM_Handle *h = ait->h;
1453 struct AttestationIterationNextMessage *msg; 1491 struct CredentialIterationNextMessage *msg;
1454 struct GNUNET_MQ_Envelope *env; 1492 struct GNUNET_MQ_Envelope *env;
1455 1493
1456 env = 1494 env =
1457 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT); 1495 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT);
1458 msg->id = htonl (ait->r_id); 1496 msg->id = htonl (ait->r_id);
1459 GNUNET_MQ_send (h->mq, env); 1497 GNUNET_MQ_send (h->mq, env);
1460} 1498}
@@ -1468,18 +1506,18 @@ GNUNET_RECLAIM_get_attestations_next (struct
1468 * @param it the iterator 1506 * @param it the iterator
1469 */ 1507 */
1470void 1508void
1471GNUNET_RECLAIM_get_attestations_stop (struct 1509GNUNET_RECLAIM_get_credentials_stop (struct
1472 GNUNET_RECLAIM_AttestationIterator *ait) 1510 GNUNET_RECLAIM_CredentialIterator *ait)
1473{ 1511{
1474 struct GNUNET_RECLAIM_Handle *h = ait->h; 1512 struct GNUNET_RECLAIM_Handle *h = ait->h;
1475 struct GNUNET_MQ_Envelope *env; 1513 struct GNUNET_MQ_Envelope *env;
1476 struct AttestationIterationStopMessage *msg; 1514 struct CredentialIterationStopMessage *msg;
1477 1515
1478 if (NULL != h->mq) 1516 if (NULL != h->mq)
1479 { 1517 {
1480 env = 1518 env =
1481 GNUNET_MQ_msg (msg, 1519 GNUNET_MQ_msg (msg,
1482 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP); 1520 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP);
1483 msg->id = htonl (ait->r_id); 1521 msg->id = htonl (ait->r_id);
1484 GNUNET_MQ_send (h->mq, env); 1522 GNUNET_MQ_send (h->mq, env);
1485 } 1523 }
@@ -1506,7 +1544,7 @@ GNUNET_RECLAIM_ticket_issue (
1506 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, 1544 const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
1507 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, 1545 const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
1508 const struct GNUNET_RECLAIM_AttributeList *attrs, 1546 const struct GNUNET_RECLAIM_AttributeList *attrs,
1509 GNUNET_RECLAIM_TicketCallback cb, 1547 GNUNET_RECLAIM_IssueTicketCallback cb,
1510 void *cb_cls) 1548 void *cb_cls)
1511{ 1549{
1512 struct GNUNET_RECLAIM_Operation *op; 1550 struct GNUNET_RECLAIM_Operation *op;
@@ -1516,7 +1554,7 @@ GNUNET_RECLAIM_ticket_issue (
1516 fprintf (stderr, "Issuing ticket\n"); 1554 fprintf (stderr, "Issuing ticket\n");
1517 op = GNUNET_new (struct GNUNET_RECLAIM_Operation); 1555 op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1518 op->h = h; 1556 op->h = h;
1519 op->tr_cb = cb; 1557 op->ti_cb = cb;
1520 op->cls = cb_cls; 1558 op->cls = cb_cls;
1521 op->r_id = h->r_id_gen++; 1559 op->r_id = h->r_id_gen++;
1522 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); 1560 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
@@ -1573,7 +1611,7 @@ GNUNET_RECLAIM_ticket_consume (
1573 if (NULL != h->mq) 1611 if (NULL != h->mq)
1574 GNUNET_MQ_send_copy (h->mq, op->env); 1612 GNUNET_MQ_send_copy (h->mq, op->env);
1575 else 1613 else
1576 reconnect(h); 1614 reconnect (h);
1577 return op; 1615 return op;
1578} 1616}
1579 1617
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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim-attribute/reclaim_attestation.c
23 * @brief helper library to manage identity attribute attestations
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_reclaim_plugin.h"
29#include "reclaim_attestation.h"
30
31
32/**
33 * Handle for a plugin
34 */
35struct Plugin
36{
37 /**
38 * Name of the plugin
39 */
40 char *library_name;
41
42 /**
43 * Plugin API
44 */
45 struct GNUNET_RECLAIM_AttestationPluginFunctions *api;
46};
47
48
49/**
50 * Plugins
51 */
52static struct Plugin **attest_plugins;
53
54
55/**
56 * Number of plugins
57 */
58static unsigned int num_plugins;
59
60
61/**
62 * Init canary
63 */
64static int initialized;
65
66
67/**
68 * Add a plugin
69 *
70 * @param cls closure
71 * @param library_name name of the API library
72 * @param lib_ret the plugin API pointer
73 */
74static void
75add_plugin (void *cls, const char *library_name, void *lib_ret)
76{
77 struct GNUNET_RECLAIM_AttestationPluginFunctions *api = lib_ret;
78 struct Plugin *plugin;
79
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Loading attestation plugin `%s'\n",
82 library_name);
83 plugin = GNUNET_new (struct Plugin);
84 plugin->api = api;
85 plugin->library_name = GNUNET_strdup (library_name);
86 GNUNET_array_append (attest_plugins, num_plugins, plugin);
87}
88
89
90/**
91 * Load plugins
92 */
93static void
94init ()
95{
96 if (GNUNET_YES == initialized)
97 return;
98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attestation_",
100 NULL,
101 &add_plugin,
102 NULL);
103}
104
105
106/**
107 * Convert an attestation type name to the corresponding number
108 *
109 * @param typename name to convert
110 * @return corresponding number, UINT32_MAX on error
111 */
112uint32_t
113GNUNET_RECLAIM_attestation_typename_to_number (const char *typename)
114{
115 unsigned int i;
116 struct Plugin *plugin;
117 uint32_t ret;
118 init ();
119 for (i = 0; i < num_plugins; i++)
120 {
121 plugin = attest_plugins[i];
122 if (UINT32_MAX !=
123 (ret = plugin->api->typename_to_number (plugin->api->cls,
124 typename)))
125 return ret;
126 }
127 return UINT32_MAX;
128}
129
130
131/**
132 * Convert an attestation type number to the corresponding attestation type string
133 *
134 * @param type number of a type
135 * @return corresponding typestring, NULL on error
136 */
137const char *
138GNUNET_RECLAIM_attestation_number_to_typename (uint32_t type)
139{
140 unsigned int i;
141 struct Plugin *plugin;
142 const char *ret;
143
144 init ();
145 for (i = 0; i < num_plugins; i++)
146 {
147 plugin = attest_plugins[i];
148 if (NULL !=
149 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
150 return ret;
151 }
152 return NULL;
153}
154
155
156/**
157 * Convert human-readable version of a 'claim' of an attestation to the binary
158 * representation
159 *
160 * @param type type of the claim
161 * @param s human-readable string
162 * @param data set to value in binary encoding (will be allocated)
163 * @param data_size set to number of bytes in @a data
164 * @return #GNUNET_OK on success
165 */
166int
167GNUNET_RECLAIM_attestation_string_to_value (uint32_t type,
168 const char *s,
169 void **data,
170 size_t *data_size)
171{
172 unsigned int i;
173 struct Plugin *plugin;
174
175 init ();
176 for (i = 0; i < num_plugins; i++)
177 {
178 plugin = attest_plugins[i];
179 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
180 type,
181 s,
182 data,
183 data_size))
184 return GNUNET_OK;
185 }
186 return GNUNET_SYSERR;
187}
188
189
190/**
191 * Convert the 'claim' of an attestation to a string
192 *
193 * @param type the type of attestation
194 * @param data claim in binary encoding
195 * @param data_size number of bytes in @a data
196 * @return NULL on error, otherwise human-readable representation of the claim
197 */
198char *
199GNUNET_RECLAIM_attestation_value_to_string (uint32_t type,
200 const void *data,
201 size_t data_size)
202{
203 unsigned int i;
204 struct Plugin *plugin;
205 char *ret;
206
207 init ();
208 for (i = 0; i < num_plugins; i++)
209 {
210 plugin = attest_plugins[i];
211 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
212 type,
213 data,
214 data_size)))
215 return ret;
216 }
217 return NULL;
218}
219
220
221/**
222 * Create a new attestation.
223 *
224 * @param attr_name the attestation name
225 * @param type the attestation type
226 * @param data the attestation value
227 * @param data_size the attestation value size
228 * @return the new attestation
229 */
230struct GNUNET_RECLAIM_Attestation *
231GNUNET_RECLAIM_attestation_new (const char *attr_name,
232 uint32_t type,
233 const void *data,
234 size_t data_size)
235{
236 struct GNUNET_RECLAIM_Attestation *attr;
237 char *write_ptr;
238 char *attr_name_tmp = GNUNET_strdup (attr_name);
239
240 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
241
242 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attestation)
243 + strlen (attr_name_tmp) + 1 + data_size);
244 attr->type = type;
245 attr->data_size = data_size;
246 attr->flag = 0;
247 write_ptr = (char *) &attr[1];
248 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
249 attr->name = write_ptr;
250 write_ptr += strlen (attr->name) + 1;
251 GNUNET_memcpy (write_ptr, data, data_size);
252 attr->data = write_ptr;
253 GNUNET_free (attr_name_tmp);
254 return attr;
255}
256
257
258/**
259 * Get required size for serialization buffer
260 *
261 * @param attrs the attribute list to serialize
262 * @return the required buffer size
263 */
264size_t
265GNUNET_RECLAIM_attestation_list_serialize_get_size (
266 const struct GNUNET_RECLAIM_AttestationList *attestations)
267{
268 struct GNUNET_RECLAIM_AttestationListEntry *le;
269 size_t len = 0;
270
271 for (le = attestations->list_head; NULL != le; le = le->next)
272 {
273 GNUNET_assert (NULL != le->attestation);
274 len += GNUNET_RECLAIM_attestation_serialize_get_size (le->attestation);
275 len += sizeof(struct GNUNET_RECLAIM_AttestationListEntry);
276 }
277 return len;
278}
279
280
281/**
282 * Serialize an attribute list
283 *
284 * @param attrs the attribute list to serialize
285 * @param result the serialized attribute
286 * @return length of serialized data
287 */
288size_t
289GNUNET_RECLAIM_attestation_list_serialize (
290 const struct GNUNET_RECLAIM_AttestationList *attestations,
291 char *result)
292{
293 struct GNUNET_RECLAIM_AttestationListEntry *le;
294 size_t len;
295 size_t total_len;
296 char *write_ptr;
297 write_ptr = result;
298 total_len = 0;
299 for (le = attestations->list_head; NULL != le; le = le->next)
300 {
301 GNUNET_assert (NULL != le->attestation);
302 len = GNUNET_RECLAIM_attestation_serialize (le->attestation, write_ptr);
303 total_len += len;
304 write_ptr += len;
305 }
306 return total_len;
307}
308
309
310/**
311 * Deserialize an attestation list
312 *
313 * @param data the serialized attribute list
314 * @param data_size the length of the serialized data
315 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
316 */
317struct GNUNET_RECLAIM_AttestationList *
318GNUNET_RECLAIM_attestation_list_deserialize (const char *data, size_t data_size)
319{
320 struct GNUNET_RECLAIM_AttestationList *al;
321 struct GNUNET_RECLAIM_AttestationListEntry *ale;
322 size_t att_len;
323 const char *read_ptr;
324
325 al = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
326
327 if ((data_size < sizeof(struct
328 Attestation)
329 + sizeof(struct GNUNET_RECLAIM_AttestationListEntry)))
330 return al;
331
332 read_ptr = data;
333 while (((data + data_size) - read_ptr) >= sizeof(struct Attestation))
334 {
335 ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
336 ale->attestation =
337 GNUNET_RECLAIM_attestation_deserialize (read_ptr,
338 data_size - (read_ptr - data));
339 if (NULL == ale->attestation)
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
342 "Failed to deserialize malformed attestation.\n");
343 GNUNET_free (ale);
344 return al;
345 }
346 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
347 att_len = GNUNET_RECLAIM_attestation_serialize_get_size (ale->attestation);
348 read_ptr += att_len;
349 }
350 return al;
351}
352
353
354/**
355 * Make a (deep) copy of the attestation list
356 * @param attrs claim list to copy
357 * @return copied claim list
358 */
359struct GNUNET_RECLAIM_AttestationList *
360GNUNET_RECLAIM_attestation_list_dup (
361 const struct GNUNET_RECLAIM_AttestationList *al)
362{
363 struct GNUNET_RECLAIM_AttestationListEntry *ale;
364 struct GNUNET_RECLAIM_AttestationListEntry *result_ale;
365 struct GNUNET_RECLAIM_AttestationList *result;
366
367 result = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
368 for (ale = al->list_head; NULL != ale; ale = ale->next)
369 {
370 result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
371 GNUNET_assert (NULL != ale->attestation);
372 result_ale->attestation =
373 GNUNET_RECLAIM_attestation_new (ale->attestation->name,
374 ale->attestation->type,
375 ale->attestation->data,
376 ale->attestation->data_size);
377 result_ale->attestation->id = ale->attestation->id;
378 GNUNET_CONTAINER_DLL_insert (result->list_head,
379 result->list_tail,
380 result_ale);
381 }
382 return result;
383}
384
385
386/**
387 * Destroy attestation list
388 *
389 * @param attrs list to destroy
390 */
391void
392GNUNET_RECLAIM_attestation_list_destroy (
393 struct GNUNET_RECLAIM_AttestationList *al)
394{
395 struct GNUNET_RECLAIM_AttestationListEntry *ale;
396 struct GNUNET_RECLAIM_AttestationListEntry *tmp_ale;
397
398 for (ale = al->list_head; NULL != ale;)
399 {
400 if (NULL != ale->attestation)
401 GNUNET_free (ale->attestation);
402 tmp_ale = ale;
403 ale = ale->next;
404 GNUNET_free (tmp_ale);
405 }
406 GNUNET_free (al);
407}
408
409
410/**
411 * Get required size for serialization buffer
412 *
413 * @param attr the attestation to serialize
414 * @return the required buffer size
415 */
416size_t
417GNUNET_RECLAIM_attestation_serialize_get_size (
418 const struct GNUNET_RECLAIM_Attestation *attestation)
419{
420 return sizeof(struct Attestation) + strlen (attestation->name)
421 + attestation->data_size;
422}
423
424
425/**
426 * Serialize an attestation
427 *
428 * @param attr the attestation to serialize
429 * @param result the serialized attestation
430 * @return length of serialized data
431 */
432size_t
433GNUNET_RECLAIM_attestation_serialize (
434 const struct GNUNET_RECLAIM_Attestation *attestation,
435 char *result)
436{
437 size_t data_len_ser;
438 size_t name_len;
439 struct Attestation *atts;
440 char *write_ptr;
441
442 atts = (struct Attestation *) result;
443 atts->attestation_type = htons (attestation->type);
444 atts->attestation_flag = htonl (attestation->flag);
445 atts->attestation_id = attestation->id;
446 name_len = strlen (attestation->name);
447 atts->name_len = htons (name_len);
448 write_ptr = (char *) &atts[1];
449 GNUNET_memcpy (write_ptr, attestation->name, name_len);
450 write_ptr += name_len;
451 // TODO plugin-ize
452 // data_len_ser = plugin->serialize_attribute_value (attr,
453 // &attr_ser[1]);
454 data_len_ser = attestation->data_size;
455 GNUNET_memcpy (write_ptr, attestation->data, attestation->data_size);
456 atts->data_size = htons (data_len_ser);
457
458 return sizeof(struct Attestation) + strlen (attestation->name)
459 + attestation->data_size;
460}
461
462
463/**
464 * Deserialize an attestation
465 *
466 * @param data the serialized attestation
467 * @param data_size the length of the serialized data
468 *
469 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
470 */
471struct GNUNET_RECLAIM_Attestation *
472GNUNET_RECLAIM_attestation_deserialize (const char *data, size_t data_size)
473{
474 struct GNUNET_RECLAIM_Attestation *attestation;
475 struct Attestation *atts;
476 size_t data_len;
477 size_t name_len;
478 char *write_ptr;
479
480 if (data_size < sizeof(struct Attestation))
481 return NULL;
482
483 atts = (struct Attestation *) data;
484 data_len = ntohs (atts->data_size);
485 name_len = ntohs (atts->name_len);
486 if (data_size < sizeof(struct Attestation) + data_len + name_len)
487 {
488 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
489 "Buffer too small to deserialize\n");
490 return NULL;
491 }
492 attestation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attestation)
493 + data_len + name_len + 1);
494 attestation->type = ntohs (atts->attestation_type);
495 attestation->flag = ntohl (atts->attestation_flag);
496 attestation->id = atts->attestation_id;
497 attestation->data_size = data_len;
498
499 write_ptr = (char *) &attestation[1];
500 GNUNET_memcpy (write_ptr, &atts[1], name_len);
501 write_ptr[name_len] = '\0';
502 attestation->name = write_ptr;
503
504 write_ptr += name_len + 1;
505 GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
506 attestation->data_size);
507 attestation->data = write_ptr;
508 return attestation;
509}
510
511
512struct GNUNET_RECLAIM_AttributeList*
513GNUNET_RECLAIM_attestation_get_attributes (const struct
514 GNUNET_RECLAIM_Attestation *attest)
515{
516 unsigned int i;
517 struct Plugin *plugin;
518 struct GNUNET_RECLAIM_AttributeList *ret;
519 init ();
520 for (i = 0; i < num_plugins; i++)
521 {
522 plugin = attest_plugins[i];
523 if (NULL !=
524 (ret = plugin->api->get_attributes (plugin->api->cls,
525 attest)))
526 return ret;
527 }
528 return NULL;
529}
530
531
532char*
533GNUNET_RECLAIM_attestation_get_issuer (const struct
534 GNUNET_RECLAIM_Attestation *attest)
535{
536 unsigned int i;
537 struct Plugin *plugin;
538 char *ret;
539 init ();
540 for (i = 0; i < num_plugins; i++)
541 {
542 plugin = attest_plugins[i];
543 if (NULL !=
544 (ret = plugin->api->get_issuer (plugin->api->cls,
545 attest)))
546 return ret;
547 }
548 return NULL;
549}
550
551
552int
553GNUNET_RECLAIM_attestation_get_expiration (const struct
554 GNUNET_RECLAIM_Attestation *attest,
555 struct GNUNET_TIME_Absolute*exp)
556{
557 unsigned int i;
558 struct Plugin *plugin;
559 init ();
560 for (i = 0; i < num_plugins; i++)
561 {
562 plugin = attest_plugins[i];
563 if (GNUNET_OK != plugin->api->get_expiration (plugin->api->cls,
564 attest,
565 exp))
566 continue;
567 return GNUNET_OK;
568 }
569 return GNUNET_SYSERR;
570}
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,
222 * Create a new attribute. 222 * Create a new attribute.
223 * 223 *
224 * @param attr_name the attribute name 224 * @param attr_name the attribute name
225 * @param attestation attestation ID of the attribute (maybe NULL) 225 * @param credential credential ID of the attribute (maybe NULL)
226 * @param type the attribute type 226 * @param type the attribute type
227 * @param data the attribute value 227 * @param data the attribute value
228 * @param data_size the attribute value size 228 * @param data_size the attribute value size
@@ -231,7 +231,7 @@ GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
231struct GNUNET_RECLAIM_Attribute * 231struct GNUNET_RECLAIM_Attribute *
232GNUNET_RECLAIM_attribute_new (const char *attr_name, 232GNUNET_RECLAIM_attribute_new (const char *attr_name,
233 const struct 233 const struct
234 GNUNET_RECLAIM_Identifier *attestation, 234 GNUNET_RECLAIM_Identifier *credential,
235 uint32_t type, 235 uint32_t type,
236 const void *data, 236 const void *data,
237 size_t data_size) 237 size_t data_size)
@@ -244,8 +244,8 @@ GNUNET_RECLAIM_attribute_new (const char *attr_name,
244 244
245 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute) 245 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
246 + strlen (attr_name_tmp) + 1 + data_size); 246 + strlen (attr_name_tmp) + 1 + data_size);
247 if (NULL != attestation) 247 if (NULL != credential)
248 attr->attestation = *attestation; 248 attr->credential = *credential;
249 attr->type = type; 249 attr->type = type;
250 attr->data_size = data_size; 250 attr->data_size = data_size;
251 attr->flag = 0; 251 attr->flag = 0;
@@ -272,7 +272,7 @@ void
272GNUNET_RECLAIM_attribute_list_add ( 272GNUNET_RECLAIM_attribute_list_add (
273 struct GNUNET_RECLAIM_AttributeList *al, 273 struct GNUNET_RECLAIM_AttributeList *al,
274 const char *attr_name, 274 const char *attr_name,
275 const struct GNUNET_RECLAIM_Identifier *attestation, 275 const struct GNUNET_RECLAIM_Identifier *credential,
276 uint32_t type, 276 uint32_t type,
277 const void *data, 277 const void *data,
278 size_t data_size) 278 size_t data_size)
@@ -281,7 +281,7 @@ GNUNET_RECLAIM_attribute_list_add (
281 281
282 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 282 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
283 ale->attribute = 283 ale->attribute =
284 GNUNET_RECLAIM_attribute_new (attr_name, attestation, 284 GNUNET_RECLAIM_attribute_new (attr_name, credential,
285 type, data, data_size); 285 type, data, data_size);
286 GNUNET_CONTAINER_DLL_insert (al->list_head, 286 GNUNET_CONTAINER_DLL_insert (al->list_head,
287 al->list_tail, 287 al->list_tail,
@@ -306,7 +306,6 @@ GNUNET_RECLAIM_attribute_list_serialize_get_size (
306 { 306 {
307 GNUNET_assert (NULL != ale->attribute); 307 GNUNET_assert (NULL != ale->attribute);
308 len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute); 308 len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
309 len += sizeof(struct GNUNET_RECLAIM_AttributeListEntry);
310 } 309 }
311 return len; 310 return len;
312} 311}
@@ -355,27 +354,28 @@ GNUNET_RECLAIM_attribute_list_deserialize (const char *data, size_t data_size)
355 struct GNUNET_RECLAIM_AttributeListEntry *ale; 354 struct GNUNET_RECLAIM_AttributeListEntry *ale;
356 size_t attr_len; 355 size_t attr_len;
357 const char *read_ptr; 356 const char *read_ptr;
357 size_t left = data_size;
358 358
359 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); 359 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
360 if (data_size < sizeof(struct Attribute) + sizeof(struct 360 if (data_size < sizeof(struct Attribute))
361 GNUNET_RECLAIM_AttributeListEntry))
362 return al; 361 return al;
363 read_ptr = data; 362 read_ptr = data;
364 while (((data + data_size) - read_ptr) >= sizeof(struct Attribute)) 363 while (left >= sizeof(struct Attribute))
365 { 364 {
366 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); 365 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
367 ale->attribute = 366 attr_len =
368 GNUNET_RECLAIM_attribute_deserialize (read_ptr, 367 GNUNET_RECLAIM_attribute_deserialize (read_ptr,
369 data_size - (read_ptr - data)); 368 left,
370 if (NULL == ale->attribute) 369 &ale->attribute);
370 if (-1 == attr_len)
371 { 371 {
372 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 372 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
373 "Failed to deserialize malformed attribute.\n"); 373 "Failed to deserialize malformed attribute.\n");
374 GNUNET_free (ale); 374 GNUNET_free (ale);
375 return al; 375 return al;
376 } 376 }
377 left -= attr_len;
377 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale); 378 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
378 attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
379 read_ptr += attr_len; 379 read_ptr += attr_len;
380 } 380 }
381 return al; 381 return al;
@@ -403,7 +403,7 @@ GNUNET_RECLAIM_attribute_list_dup (
403 { 403 {
404 result_ale->attribute = 404 result_ale->attribute =
405 GNUNET_RECLAIM_attribute_new (ale->attribute->name, 405 GNUNET_RECLAIM_attribute_new (ale->attribute->name,
406 &ale->attribute->attestation, 406 &ale->attribute->credential,
407 ale->attribute->type, 407 ale->attribute->type,
408 ale->attribute->data, 408 ale->attribute->data,
409 ale->attribute->data_size); 409 ale->attribute->data_size);
@@ -478,7 +478,7 @@ GNUNET_RECLAIM_attribute_serialize (
478 attr_ser->attribute_type = htons (attr->type); 478 attr_ser->attribute_type = htons (attr->type);
479 attr_ser->attribute_flag = htonl (attr->flag); 479 attr_ser->attribute_flag = htonl (attr->flag);
480 attr_ser->attribute_id = attr->id; 480 attr_ser->attribute_id = attr->id;
481 attr_ser->attestation_id = attr->attestation; 481 attr_ser->credential_id = attr->credential;
482 name_len = strlen (attr->name); 482 name_len = strlen (attr->name);
483 attr_ser->name_len = htons (name_len); 483 attr_ser->name_len = htons (name_len);
484 write_ptr = (char *) &attr_ser[1]; 484 write_ptr = (char *) &attr_ser[1];
@@ -503,17 +503,18 @@ GNUNET_RECLAIM_attribute_serialize (
503 * 503 *
504 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller 504 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
505 */ 505 */
506struct GNUNET_RECLAIM_Attribute * 506ssize_t
507GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size) 507GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
508 struct GNUNET_RECLAIM_Attribute **attr)
508{ 509{
509 struct GNUNET_RECLAIM_Attribute *attr;
510 struct Attribute *attr_ser; 510 struct Attribute *attr_ser;
511 struct GNUNET_RECLAIM_Attribute *attribute;
511 size_t data_len; 512 size_t data_len;
512 size_t name_len; 513 size_t name_len;
513 char *write_ptr; 514 char *write_ptr;
514 515
515 if (data_size < sizeof(struct Attribute)) 516 if (data_size < sizeof(struct Attribute))
516 return NULL; 517 return -1;
517 518
518 attr_ser = (struct Attribute *) data; 519 attr_ser = (struct Attribute *) data;
519 data_len = ntohs (attr_ser->data_size); 520 data_len = ntohs (attr_ser->data_size);
@@ -522,25 +523,27 @@ GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size)
522 { 523 {
523 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 524 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
524 "Buffer too small to deserialize\n"); 525 "Buffer too small to deserialize\n");
525 return NULL; 526 return -1;
526 } 527 }
527 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute) 528 attribute = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
528 + data_len + name_len + 1); 529 + data_len + name_len + 1);
529 attr->type = ntohs (attr_ser->attribute_type); 530 attribute->type = ntohs (attr_ser->attribute_type);
530 attr->flag = ntohl (attr_ser->attribute_flag); 531 attribute->flag = ntohl (attr_ser->attribute_flag);
531 attr->id = attr_ser->attribute_id; 532 attribute->id = attr_ser->attribute_id;
532 attr->attestation = attr_ser->attestation_id; 533 attribute->credential = attr_ser->credential_id;
533 attr->data_size = data_len; 534 attribute->data_size = data_len;
534 535
535 write_ptr = (char *) &attr[1]; 536 write_ptr = (char *) &attribute[1];
536 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len); 537 GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
537 write_ptr[name_len] = '\0'; 538 write_ptr[name_len] = '\0';
538 attr->name = write_ptr; 539 attribute->name = write_ptr;
539 540
540 write_ptr += name_len + 1; 541 write_ptr += name_len + 1;
541 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size); 542 GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len,
542 attr->data = write_ptr; 543 attribute->data_size);
543 return attr; 544 *attr = attribute;
545 attribute->data = write_ptr;
546 return sizeof(struct Attribute) + data_len + name_len;
544} 547}
545 548
546 549
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 @@
28 28
29#include "gnunet_reclaim_service.h" 29#include "gnunet_reclaim_service.h"
30 30
31GNUNET_NETWORK_STRUCT_BEGIN
32
31/** 33/**
32 * Serialized claim 34 * Serialized claim
33 */ 35 */
@@ -36,12 +38,12 @@ struct Attribute
36 /** 38 /**
37 * Attribute type 39 * Attribute type
38 */ 40 */
39 uint32_t attribute_type; 41 uint32_t attribute_type GNUNET_PACKED;
40 42
41 /** 43 /**
42 * Attribute flag 44 * Attribute flag
43 */ 45 */
44 uint32_t attribute_flag; 46 uint32_t attribute_flag GNUNET_PACKED;
45 47
46 /** 48 /**
47 * Attribute ID 49 * Attribute ID
@@ -49,54 +51,23 @@ struct Attribute
49 struct GNUNET_RECLAIM_Identifier attribute_id; 51 struct GNUNET_RECLAIM_Identifier attribute_id;
50 52
51 /** 53 /**
52 * Attestation ID 54 * Credential ID
53 */ 55 */
54 struct GNUNET_RECLAIM_Identifier attestation_id; 56 struct GNUNET_RECLAIM_Identifier credential_id;
55 57
56 /** 58 /**
57 * Name length 59 * Name length
58 */ 60 */
59 uint32_t name_len; 61 uint32_t name_len GNUNET_PACKED;
60 62
61 /** 63 /**
62 * Data size 64 * Data size
63 */ 65 */
64 uint32_t data_size; 66 uint32_t data_size GNUNET_PACKED;
65 67
66 // followed by data_size Attribute value data 68 // followed by data_size Attribute value data
67}; 69};
68 70
69/** 71GNUNET_NETWORK_STRUCT_BEGIN
70 * Serialized attestation claim
71 */
72struct Attestation
73{
74 /**
75 * Attestation type
76 */
77 uint32_t attestation_type;
78
79 /**
80 * Attestation flag
81 */
82 uint32_t attestation_flag;
83
84 /**
85 * Attestation ID
86 */
87 struct GNUNET_RECLAIM_Identifier attestation_id;
88
89 /**
90 * Name length
91 */
92 uint32_t name_len;
93
94 /**
95 * Data size
96 */
97 uint32_t data_size;
98
99 // followed by data_size Attestation value data
100};
101 72
102#endif 73#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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/reclaim_credential.c
23 * @brief helper library to manage identity attribute credentials
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_reclaim_plugin.h"
29#include "reclaim_credential.h"
30
31
32/**
33 * Handle for a plugin
34 */
35struct Plugin
36{
37 /**
38 * Name of the plugin
39 */
40 char *library_name;
41
42 /**
43 * Plugin API
44 */
45 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
46};
47
48
49/**
50 * Plugins
51 */
52static struct Plugin **credential_plugins;
53
54
55/**
56 * Number of plugins
57 */
58static unsigned int num_plugins;
59
60
61/**
62 * Init canary
63 */
64static int initialized;
65
66
67/**
68 * Add a plugin
69 *
70 * @param cls closure
71 * @param library_name name of the API library
72 * @param lib_ret the plugin API pointer
73 */
74static void
75add_plugin (void *cls, const char *library_name, void *lib_ret)
76{
77 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = lib_ret;
78 struct Plugin *plugin;
79
80 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81 "Loading credential plugin `%s'\n",
82 library_name);
83 plugin = GNUNET_new (struct Plugin);
84 plugin->api = api;
85 plugin->library_name = GNUNET_strdup (library_name);
86 GNUNET_array_append (credential_plugins, num_plugins, plugin);
87}
88
89
90/**
91 * Load plugins
92 */
93static void
94init ()
95{
96 if (GNUNET_YES == initialized)
97 return;
98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_credential_",
100 NULL,
101 &add_plugin,
102 NULL);
103}
104
105
106/**
107 * Convert an credential type name to the corresponding number
108 *
109 * @param typename name to convert
110 * @return corresponding number, UINT32_MAX on error
111 */
112uint32_t
113GNUNET_RECLAIM_credential_typename_to_number (const char *typename)
114{
115 unsigned int i;
116 struct Plugin *plugin;
117 uint32_t ret;
118 init ();
119 for (i = 0; i < num_plugins; i++)
120 {
121 plugin = credential_plugins[i];
122 if (UINT32_MAX !=
123 (ret = plugin->api->typename_to_number (plugin->api->cls,
124 typename)))
125 return ret;
126 }
127 return UINT32_MAX;
128}
129
130
131/**
132 * Convert an credential type number to the corresponding credential type string
133 *
134 * @param type number of a type
135 * @return corresponding typestring, NULL on error
136 */
137const char *
138GNUNET_RECLAIM_credential_number_to_typename (uint32_t type)
139{
140 unsigned int i;
141 struct Plugin *plugin;
142 const char *ret;
143
144 init ();
145 for (i = 0; i < num_plugins; i++)
146 {
147 plugin = credential_plugins[i];
148 if (NULL !=
149 (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
150 return ret;
151 }
152 return NULL;
153}
154
155
156/**
157 * Convert human-readable version of a 'claim' of an credential to the binary
158 * representation
159 *
160 * @param type type of the claim
161 * @param s human-readable string
162 * @param data set to value in binary encoding (will be allocated)
163 * @param data_size set to number of bytes in @a data
164 * @return #GNUNET_OK on success
165 */
166int
167GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
168 const char *s,
169 void **data,
170 size_t *data_size)
171{
172 unsigned int i;
173 struct Plugin *plugin;
174
175 init ();
176 for (i = 0; i < num_plugins; i++)
177 {
178 plugin = credential_plugins[i];
179 if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
180 type,
181 s,
182 data,
183 data_size))
184 return GNUNET_OK;
185 }
186 return GNUNET_SYSERR;
187}
188
189
190/**
191 * Convert the 'claim' of an credential to a string
192 *
193 * @param type the type of credential
194 * @param data claim in binary encoding
195 * @param data_size number of bytes in @a data
196 * @return NULL on error, otherwise human-readable representation of the claim
197 */
198char *
199GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
200 const void *data,
201 size_t data_size)
202{
203 unsigned int i;
204 struct Plugin *plugin;
205 char *ret;
206
207 init ();
208 for (i = 0; i < num_plugins; i++)
209 {
210 plugin = credential_plugins[i];
211 if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
212 type,
213 data,
214 data_size)))
215 return ret;
216 }
217 return NULL;
218}
219
220
221/**
222 * Create a new credential.
223 *
224 * @param attr_name the credential name
225 * @param type the credential type
226 * @param data the credential value
227 * @param data_size the credential value size
228 * @return the new credential
229 */
230struct GNUNET_RECLAIM_Credential *
231GNUNET_RECLAIM_credential_new (const char *attr_name,
232 uint32_t type,
233 const void *data,
234 size_t data_size)
235{
236 struct GNUNET_RECLAIM_Credential *attr;
237 char *write_ptr;
238 char *attr_name_tmp = GNUNET_strdup (attr_name);
239
240 GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
241
242 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
243 + strlen (attr_name_tmp) + 1 + data_size);
244 attr->type = type;
245 attr->data_size = data_size;
246 attr->flag = 0;
247 write_ptr = (char *) &attr[1];
248 GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
249 attr->name = write_ptr;
250 write_ptr += strlen (attr->name) + 1;
251 GNUNET_memcpy (write_ptr, data, data_size);
252 attr->data = write_ptr;
253 GNUNET_free (attr_name_tmp);
254 return attr;
255}
256
257
258/**
259 * Get required size for serialization buffer
260 *
261 * @param attrs the attribute list to serialize
262 * @return the required buffer size
263 */
264size_t
265GNUNET_RECLAIM_credential_list_serialize_get_size (
266 const struct GNUNET_RECLAIM_CredentialList *credentials)
267{
268 struct GNUNET_RECLAIM_CredentialListEntry *le;
269 size_t len = 0;
270
271 for (le = credentials->list_head; NULL != le; le = le->next)
272 {
273 GNUNET_assert (NULL != le->credential);
274 len += GNUNET_RECLAIM_credential_serialize_get_size (le->credential);
275 len += sizeof(struct GNUNET_RECLAIM_CredentialListEntry);
276 }
277 return len;
278}
279
280
281/**
282 * Serialize an attribute list
283 *
284 * @param attrs the attribute list to serialize
285 * @param result the serialized attribute
286 * @return length of serialized data
287 */
288size_t
289GNUNET_RECLAIM_credential_list_serialize (
290 const struct GNUNET_RECLAIM_CredentialList *credentials,
291 char *result)
292{
293 struct GNUNET_RECLAIM_CredentialListEntry *le;
294 size_t len;
295 size_t total_len;
296 char *write_ptr;
297 write_ptr = result;
298 total_len = 0;
299 for (le = credentials->list_head; NULL != le; le = le->next)
300 {
301 GNUNET_assert (NULL != le->credential);
302 len = GNUNET_RECLAIM_credential_serialize (le->credential, write_ptr);
303 total_len += len;
304 write_ptr += len;
305 }
306 return total_len;
307}
308
309
310/**
311 * Deserialize an credential list
312 *
313 * @param data the serialized attribute list
314 * @param data_size the length of the serialized data
315 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
316 */
317struct GNUNET_RECLAIM_CredentialList *
318GNUNET_RECLAIM_credential_list_deserialize (const char *data, size_t data_size)
319{
320 struct GNUNET_RECLAIM_CredentialList *al;
321 struct GNUNET_RECLAIM_CredentialListEntry *ale;
322 size_t att_len;
323 const char *read_ptr;
324
325 al = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
326
327 if ((data_size < sizeof(struct
328 Credential)
329 + sizeof(struct GNUNET_RECLAIM_CredentialListEntry)))
330 return al;
331
332 read_ptr = data;
333 while (((data + data_size) - read_ptr) >= sizeof(struct Credential))
334 {
335 ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
336 ale->credential =
337 GNUNET_RECLAIM_credential_deserialize (read_ptr,
338 data_size - (read_ptr - data));
339 if (NULL == ale->credential)
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
342 "Failed to deserialize malformed credential.\n");
343 GNUNET_free (ale);
344 return al;
345 }
346 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
347 att_len = GNUNET_RECLAIM_credential_serialize_get_size (ale->credential);
348 read_ptr += att_len;
349 }
350 return al;
351}
352
353
354/**
355 * Make a (deep) copy of the credential list
356 * @param attrs claim list to copy
357 * @return copied claim list
358 */
359struct GNUNET_RECLAIM_CredentialList *
360GNUNET_RECLAIM_credential_list_dup (
361 const struct GNUNET_RECLAIM_CredentialList *al)
362{
363 struct GNUNET_RECLAIM_CredentialListEntry *ale;
364 struct GNUNET_RECLAIM_CredentialListEntry *result_ale;
365 struct GNUNET_RECLAIM_CredentialList *result;
366
367 result = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
368 for (ale = al->list_head; NULL != ale; ale = ale->next)
369 {
370 result_ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
371 GNUNET_assert (NULL != ale->credential);
372 result_ale->credential =
373 GNUNET_RECLAIM_credential_new (ale->credential->name,
374 ale->credential->type,
375 ale->credential->data,
376 ale->credential->data_size);
377 result_ale->credential->id = ale->credential->id;
378 GNUNET_CONTAINER_DLL_insert (result->list_head,
379 result->list_tail,
380 result_ale);
381 }
382 return result;
383}
384
385
386/**
387 * Destroy credential list
388 *
389 * @param attrs list to destroy
390 */
391void
392GNUNET_RECLAIM_credential_list_destroy (
393 struct GNUNET_RECLAIM_CredentialList *al)
394{
395 struct GNUNET_RECLAIM_CredentialListEntry *ale;
396 struct GNUNET_RECLAIM_CredentialListEntry *tmp_ale;
397
398 for (ale = al->list_head; NULL != ale;)
399 {
400 if (NULL != ale->credential)
401 GNUNET_free (ale->credential);
402 tmp_ale = ale;
403 ale = ale->next;
404 GNUNET_free (tmp_ale);
405 }
406 GNUNET_free (al);
407}
408
409
410/**
411 * Get required size for serialization buffer
412 *
413 * @param attr the credential to serialize
414 * @return the required buffer size
415 */
416size_t
417GNUNET_RECLAIM_credential_serialize_get_size (
418 const struct GNUNET_RECLAIM_Credential *credential)
419{
420 return sizeof(struct Credential) + strlen (credential->name)
421 + credential->data_size;
422}
423
424
425/**
426 * Serialize an credential
427 *
428 * @param attr the credential to serialize
429 * @param result the serialized credential
430 * @return length of serialized data
431 */
432size_t
433GNUNET_RECLAIM_credential_serialize (
434 const struct GNUNET_RECLAIM_Credential *credential,
435 char *result)
436{
437 size_t data_len_ser;
438 size_t name_len;
439 struct Credential *atts;
440 char *write_ptr;
441
442 atts = (struct Credential *) result;
443 atts->credential_type = htons (credential->type);
444 atts->credential_flag = htonl (credential->flag);
445 atts->credential_id = credential->id;
446 name_len = strlen (credential->name);
447 atts->name_len = htons (name_len);
448 write_ptr = (char *) &atts[1];
449 GNUNET_memcpy (write_ptr, credential->name, name_len);
450 write_ptr += name_len;
451 // TODO plugin-ize
452 // data_len_ser = plugin->serialize_attribute_value (attr,
453 // &attr_ser[1]);
454 data_len_ser = credential->data_size;
455 GNUNET_memcpy (write_ptr, credential->data, credential->data_size);
456 atts->data_size = htons (data_len_ser);
457
458 return sizeof(struct Credential) + strlen (credential->name)
459 + credential->data_size;
460}
461
462
463/**
464 * Deserialize an credential
465 *
466 * @param data the serialized credential
467 * @param data_size the length of the serialized data
468 *
469 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
470 */
471struct GNUNET_RECLAIM_Credential *
472GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size)
473{
474 struct GNUNET_RECLAIM_Credential *credential;
475 struct Credential *atts;
476 size_t data_len;
477 size_t name_len;
478 char *write_ptr;
479
480 if (data_size < sizeof(struct Credential))
481 return NULL;
482
483 atts = (struct Credential *) data;
484 data_len = ntohs (atts->data_size);
485 name_len = ntohs (atts->name_len);
486 if (data_size < sizeof(struct Credential) + data_len + name_len)
487 {
488 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
489 "Buffer too small to deserialize\n");
490 return NULL;
491 }
492 credential = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
493 + data_len + name_len + 1);
494 credential->type = ntohs (atts->credential_type);
495 credential->flag = ntohl (atts->credential_flag);
496 credential->id = atts->credential_id;
497 credential->data_size = data_len;
498
499 write_ptr = (char *) &credential[1];
500 GNUNET_memcpy (write_ptr, &atts[1], name_len);
501 write_ptr[name_len] = '\0';
502 credential->name = write_ptr;
503
504 write_ptr += name_len + 1;
505 GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
506 credential->data_size);
507 credential->data = write_ptr;
508 return credential;
509}
510
511
512struct GNUNET_RECLAIM_AttributeList*
513GNUNET_RECLAIM_credential_get_attributes (const struct
514 GNUNET_RECLAIM_Credential *credential)
515{
516 unsigned int i;
517 struct Plugin *plugin;
518 struct GNUNET_RECLAIM_AttributeList *ret;
519 init ();
520 for (i = 0; i < num_plugins; i++)
521 {
522 plugin = credential_plugins[i];
523 if (NULL !=
524 (ret = plugin->api->get_attributes (plugin->api->cls,
525 credential)))
526 return ret;
527 }
528 return NULL;
529}
530
531
532char*
533GNUNET_RECLAIM_credential_get_issuer (const struct
534 GNUNET_RECLAIM_Credential *credential)
535{
536 unsigned int i;
537 struct Plugin *plugin;
538 char *ret;
539 init ();
540 for (i = 0; i < num_plugins; i++)
541 {
542 plugin = credential_plugins[i];
543 if (NULL !=
544 (ret = plugin->api->get_issuer (plugin->api->cls,
545 credential)))
546 return ret;
547 }
548 return NULL;
549}
550
551
552int
553GNUNET_RECLAIM_credential_get_expiration (const struct
554 GNUNET_RECLAIM_Credential *credential,
555 struct GNUNET_TIME_Absolute*exp)
556{
557 unsigned int i;
558 struct Plugin *plugin;
559 init ();
560 for (i = 0; i < num_plugins; i++)
561 {
562 plugin = credential_plugins[i];
563 if (GNUNET_OK != plugin->api->get_expiration (plugin->api->cls,
564 credential,
565 exp))
566 continue;
567 return GNUNET_OK;
568 }
569 return GNUNET_SYSERR;
570}
571
572
573/**
574 * Convert an presentation type name to the corresponding number
575 *
576 * @param typename name to convert
577 * @return corresponding number, UINT32_MAX on error
578 */
579uint32_t
580GNUNET_RECLAIM_presentation_typename_to_number (const char *typename)
581{
582 unsigned int i;
583 struct Plugin *plugin;
584 uint32_t ret;
585 init ();
586 for (i = 0; i < num_plugins; i++)
587 {
588 plugin = credential_plugins[i];
589 if (UINT32_MAX !=
590 (ret = plugin->api->typename_to_number_p (plugin->api->cls,
591 typename)))
592 return ret;
593 }
594 return UINT32_MAX;
595}
596
597
598/**
599 * Convert an presentation type number to the corresponding presentation type string
600 *
601 * @param type number of a type
602 * @return corresponding typestring, NULL on error
603 */
604const char *
605GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type)
606{
607 unsigned int i;
608 struct Plugin *plugin;
609 const char *ret;
610
611 init ();
612 for (i = 0; i < num_plugins; i++)
613 {
614 plugin = credential_plugins[i];
615 if (NULL !=
616 (ret = plugin->api->number_to_typename_p (plugin->api->cls, type)))
617 return ret;
618 }
619 return NULL;
620}
621
622
623/**
624 * Convert human-readable version of a 'claim' of an presentation to the binary
625 * representation
626 *
627 * @param type type of the claim
628 * @param s human-readable string
629 * @param data set to value in binary encoding (will be allocated)
630 * @param data_size set to number of bytes in @a data
631 * @return #GNUNET_OK on success
632 */
633int
634GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
635 const char *s,
636 void **data,
637 size_t *data_size)
638{
639 unsigned int i;
640 struct Plugin *plugin;
641
642 init ();
643 for (i = 0; i < num_plugins; i++)
644 {
645 plugin = credential_plugins[i];
646 if (GNUNET_OK == plugin->api->string_to_value_p (plugin->api->cls,
647 type,
648 s,
649 data,
650 data_size))
651 return GNUNET_OK;
652 }
653 return GNUNET_SYSERR;
654}
655
656
657/**
658 * Convert the 'claim' of an presentation to a string
659 *
660 * @param type the type of presentation
661 * @param data claim in binary encoding
662 * @param data_size number of bytes in @a data
663 * @return NULL on error, otherwise human-readable representation of the claim
664 */
665char *
666GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
667 const void *data,
668 size_t data_size)
669{
670 unsigned int i;
671 struct Plugin *plugin;
672 char *ret;
673
674 init ();
675 for (i = 0; i < num_plugins; i++)
676 {
677 plugin = credential_plugins[i];
678 if (NULL != (ret = plugin->api->value_to_string_p (plugin->api->cls,
679 type,
680 data,
681 data_size)))
682 return ret;
683 }
684 return NULL;
685}
686
687
688struct GNUNET_RECLAIM_Presentation *
689GNUNET_RECLAIM_presentation_new (uint32_t type,
690 const void *data,
691 size_t data_size)
692{
693 struct GNUNET_RECLAIM_Presentation *attr;
694 char *write_ptr;
695
696 attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
697 + data_size);
698 attr->type = type;
699 attr->data_size = data_size;
700 write_ptr = (char *) &attr[1];
701 GNUNET_memcpy (write_ptr, data, data_size);
702 attr->data = write_ptr;
703 return attr;
704}
705
706
707/**
708 * Get required size for serialization buffer
709 *
710 * @param attrs the attribute list to serialize
711 * @return the required buffer size
712 */
713size_t
714GNUNET_RECLAIM_presentation_list_serialize_get_size (
715 const struct GNUNET_RECLAIM_PresentationList *presentations)
716{
717 struct GNUNET_RECLAIM_PresentationListEntry *le;
718 size_t len = 0;
719
720 for (le = presentations->list_head; NULL != le; le = le->next)
721 {
722 GNUNET_assert (NULL != le->presentation);
723 len += GNUNET_RECLAIM_presentation_serialize_get_size (le->presentation);
724 len += sizeof(struct GNUNET_RECLAIM_PresentationListEntry);
725 }
726 return len;
727}
728
729
730/**
731 * Serialize an attribute list
732 *
733 * @param attrs the attribute list to serialize
734 * @param result the serialized attribute
735 * @return length of serialized data
736 */
737size_t
738GNUNET_RECLAIM_presentation_list_serialize (
739 const struct GNUNET_RECLAIM_PresentationList *presentations,
740 char *result)
741{
742 struct GNUNET_RECLAIM_PresentationListEntry *le;
743 size_t len;
744 size_t total_len;
745 char *write_ptr;
746 write_ptr = result;
747 total_len = 0;
748 for (le = presentations->list_head; NULL != le; le = le->next)
749 {
750 GNUNET_assert (NULL != le->presentation);
751 len = GNUNET_RECLAIM_presentation_serialize (le->presentation, write_ptr);
752 total_len += len;
753 write_ptr += len;
754 }
755 return total_len;
756}
757
758
759/**
760 * Deserialize an presentation list
761 *
762 * @param data the serialized attribute list
763 * @param data_size the length of the serialized data
764 * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
765 */
766struct GNUNET_RECLAIM_PresentationList *
767GNUNET_RECLAIM_presentation_list_deserialize (const char *data, size_t
768 data_size)
769{
770 struct GNUNET_RECLAIM_PresentationList *al;
771 struct GNUNET_RECLAIM_PresentationListEntry *ale;
772 size_t att_len;
773 const char *read_ptr;
774
775 al = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
776
777 if ((data_size < sizeof(struct Presentation)
778 + sizeof(struct GNUNET_RECLAIM_PresentationListEntry)))
779 return al;
780
781 read_ptr = data;
782 while (((data + data_size) - read_ptr) >= sizeof(struct Presentation))
783 {
784 ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
785 ale->presentation =
786 GNUNET_RECLAIM_presentation_deserialize (read_ptr,
787 data_size - (read_ptr - data));
788 if (NULL == ale->presentation)
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
791 "Failed to deserialize malformed presentation.\n");
792 GNUNET_free (ale);
793 return al;
794 }
795 GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
796 att_len = GNUNET_RECLAIM_presentation_serialize_get_size (
797 ale->presentation);
798 read_ptr += att_len;
799 }
800 return al;
801}
802
803
804/**
805 * Make a (deep) copy of the presentation list
806 * @param attrs claim list to copy
807 * @return copied claim list
808 */
809struct GNUNET_RECLAIM_PresentationList *
810GNUNET_RECLAIM_presentation_list_dup (
811 const struct GNUNET_RECLAIM_PresentationList *al)
812{
813 struct GNUNET_RECLAIM_PresentationListEntry *ale;
814 struct GNUNET_RECLAIM_PresentationListEntry *result_ale;
815 struct GNUNET_RECLAIM_PresentationList *result;
816
817 result = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
818 for (ale = al->list_head; NULL != ale; ale = ale->next)
819 {
820 result_ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
821 GNUNET_assert (NULL != ale->presentation);
822 result_ale->presentation =
823 GNUNET_RECLAIM_presentation_new (ale->presentation->type,
824 ale->presentation->data,
825 ale->presentation->data_size);
826 result_ale->presentation->credential_id = ale->presentation->credential_id;
827 GNUNET_CONTAINER_DLL_insert (result->list_head,
828 result->list_tail,
829 result_ale);
830 }
831 return result;
832}
833
834
835/**
836 * Destroy presentation list
837 *
838 * @param attrs list to destroy
839 */
840void
841GNUNET_RECLAIM_presentation_list_destroy (
842 struct GNUNET_RECLAIM_PresentationList *al)
843{
844 struct GNUNET_RECLAIM_PresentationListEntry *ale;
845 struct GNUNET_RECLAIM_PresentationListEntry *tmp_ale;
846
847 for (ale = al->list_head; NULL != ale;)
848 {
849 if (NULL != ale->presentation)
850 GNUNET_free (ale->presentation);
851 tmp_ale = ale;
852 ale = ale->next;
853 GNUNET_free (tmp_ale);
854 }
855 GNUNET_free (al);
856}
857
858
859/**
860 * Get required size for serialization buffer
861 *
862 * @param attr the presentation to serialize
863 * @return the required buffer size
864 */
865size_t
866GNUNET_RECLAIM_presentation_serialize_get_size (
867 const struct GNUNET_RECLAIM_Presentation *presentation)
868{
869 return sizeof(struct Presentation) + presentation->data_size;
870}
871
872
873/**
874 * Serialize an presentation
875 *
876 * @param attr the presentation to serialize
877 * @param result the serialized presentation
878 * @return length of serialized data
879 */
880size_t
881GNUNET_RECLAIM_presentation_serialize (
882 const struct GNUNET_RECLAIM_Presentation *presentation,
883 char *result)
884{
885 struct Presentation *atts;
886 char *write_ptr;
887
888 atts = (struct Presentation *) result;
889 atts->presentation_type = htons (presentation->type);
890 atts->credential_id = presentation->credential_id;
891 write_ptr = (char *) &atts[1];
892 GNUNET_memcpy (write_ptr, presentation->data, presentation->data_size);
893 atts->data_size = htons (presentation->data_size);
894
895 return sizeof(struct Presentation) + presentation->data_size;
896}
897
898
899/**
900 * Deserialize an presentation
901 *
902 * @param data the serialized presentation
903 * @param data_size the length of the serialized data
904 *
905 * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
906 */
907struct GNUNET_RECLAIM_Presentation *
908GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size)
909{
910 struct GNUNET_RECLAIM_Presentation *presentation;
911 struct Presentation *atts;
912 size_t data_len;
913 char *write_ptr;
914
915 if (data_size < sizeof(struct Presentation))
916 return NULL;
917
918 atts = (struct Presentation *) data;
919 data_len = ntohs (atts->data_size);
920 if (data_size < sizeof(struct Presentation) + data_len)
921 {
922 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
923 "Buffer too small to deserialize\n");
924 return NULL;
925 }
926 presentation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
927 + data_len);
928 presentation->type = ntohs (atts->presentation_type);
929 presentation->credential_id = atts->credential_id;
930 presentation->data_size = data_len;
931
932 write_ptr = (char *) &presentation[1];
933 GNUNET_memcpy (write_ptr, &atts[1], data_len);
934 presentation->data = write_ptr;
935 return presentation;
936}
937
938
939struct GNUNET_RECLAIM_AttributeList*
940GNUNET_RECLAIM_presentation_get_attributes (const struct
941 GNUNET_RECLAIM_Presentation *
942 presentation)
943{
944 unsigned int i;
945 struct Plugin *plugin;
946 struct GNUNET_RECLAIM_AttributeList *ret;
947 init ();
948 for (i = 0; i < num_plugins; i++)
949 {
950 plugin = credential_plugins[i];
951 if (NULL !=
952 (ret = plugin->api->get_attributes_p (plugin->api->cls,
953 presentation)))
954 return ret;
955 }
956 return NULL;
957}
958
959
960char*
961GNUNET_RECLAIM_presentation_get_issuer (const struct
962 GNUNET_RECLAIM_Presentation *
963 presentation)
964{
965 unsigned int i;
966 struct Plugin *plugin;
967 char *ret;
968 init ();
969 for (i = 0; i < num_plugins; i++)
970 {
971 plugin = credential_plugins[i];
972 if (NULL !=
973 (ret = plugin->api->get_issuer_p (plugin->api->cls,
974 presentation)))
975 return ret;
976 }
977 return NULL;
978}
979
980
981int
982GNUNET_RECLAIM_presentation_get_expiration (const struct
983 GNUNET_RECLAIM_Presentation *
984 presentation,
985 struct GNUNET_TIME_Absolute*exp)
986{
987 unsigned int i;
988 struct Plugin *plugin;
989 init ();
990 for (i = 0; i < num_plugins; i++)
991 {
992 plugin = credential_plugins[i];
993 if (GNUNET_OK != plugin->api->get_expiration_p (plugin->api->cls,
994 presentation,
995 exp))
996 continue;
997 return GNUNET_OK;
998 }
999 return GNUNET_SYSERR;
1000}
1001
1002/**
1003 * Create a presentation from a credential and a lift of (selected)
1004 * attributes in the credential.
1005 * FIXME not yet implemented
1006 *
1007 * @param cred the credential to use
1008 * @param attrs the attributes to present from the credential
1009 * @return the credential presentation presenting the attributes according
1010 * to the presentation mechanism of the credential
1011 * or NULL on error.
1012 */
1013int
1014GNUNET_RECLAIM_credential_get_presentation (
1015 const struct GNUNET_RECLAIM_Credential *cred,
1016 const struct GNUNET_RECLAIM_AttributeList *attrs,
1017 struct GNUNET_RECLAIM_Presentation **pres)
1018{
1019 unsigned int i;
1020 struct Plugin *plugin;
1021 init ();
1022 for (i = 0; i < num_plugins; i++)
1023 {
1024 plugin = credential_plugins[i];
1025 if (GNUNET_OK != plugin->api->create_presentation (plugin->api->cls,
1026 cred,
1027 attrs,
1028 pres))
1029 continue;
1030 (*pres)->credential_id = cred->id;
1031 return GNUNET_OK;
1032 }
1033 return GNUNET_SYSERR;
1034}
1035
1036
1037
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 @@
19 */ 19 */
20/** 20/**
21 * @author Martin Schanzenbach 21 * @author Martin Schanzenbach
22 * @file reclaim-attribute/reclaim_attestation.h 22 * @file reclaim/reclaim_credential.h
23 * @brief GNUnet reclaim identity attribute attestations 23 * @brief GNUnet reclaim identity attribute credentials
24 * 24 *
25 */ 25 */
26#ifndef RECLAIM_ATTESTATION_H 26#ifndef RECLAIM_CREDENTIAL_H
27#define RECLAIM_ATTESTATION_H 27#define RECLAIM_CREDENTIAL_H
28 28
29#include "gnunet_reclaim_service.h" 29#include "gnunet_reclaim_service.h"
30 30
31/** 31/**
32 * Serialized attestation claim 32 * Serialized credential claim
33 */ 33 */
34struct Attestation 34struct Credential
35{ 35{
36 /** 36 /**
37 * Attestation type 37 * Credential type
38 */ 38 */
39 uint32_t attestation_type; 39 uint32_t credential_type;
40 40
41 /** 41 /**
42 * Attestation flag 42 * Credential flag
43 */ 43 */
44 uint32_t attestation_flag; 44 uint32_t credential_flag;
45 45
46 /** 46 /**
47 * Attestation ID 47 * Credential ID
48 */ 48 */
49 struct GNUNET_RECLAIM_Identifier attestation_id; 49 struct GNUNET_RECLAIM_Identifier credential_id;
50 50
51 /** 51 /**
52 * Name length 52 * Name length
@@ -58,7 +58,42 @@ struct Attestation
58 */ 58 */
59 uint32_t data_size; 59 uint32_t data_size;
60 60
61 // followed by data_size Attestation value data 61 // followed by data_size Credential value data
62}; 62};
63 63
64
65/**
66 * Serialized presentation claim
67 */
68struct Presentation
69{
70 /**
71 * Presentation type
72 */
73 uint32_t presentation_type;
74
75 /**
76 * Presentation flag
77 */
78 uint32_t presentation_flag;
79
80 /**
81 * Credential ID
82 */
83 struct GNUNET_RECLAIM_Identifier credential_id;
84
85 /**
86 * Name length
87 */
88 uint32_t name_len;
89
90 /**
91 * Data size
92 */
93 uint32_t data_size;
94
95 // followed by data_size Presentation value data
96};
97
98
64#endif 99#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 @@
1#include "platform.h"
2#include "gnunet_common.h"
3#include "gnunet_reclaim_lib.h"
4#include "gnunet_container_lib.h"
5
6int
7main (int argc, char *argv[])
8{
9 struct GNUNET_RECLAIM_AttributeList *al;
10 struct GNUNET_RECLAIM_AttributeList *al_two;
11 struct GNUNET_RECLAIM_AttributeListEntry *ale;
12 struct GNUNET_RECLAIM_Attribute *attr;
13 char attrname[100];
14 char attrdata[100];
15 size_t ser_len_claimed;
16 size_t ser_len_actual;
17 ssize_t deser_len;
18 char *ser_data;
19 int count = 0;
20
21 al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
22 for (int i = 0; i < 12; i++)
23 {
24 memset (attrname, 0, 100);
25 memset (attrdata, 0, 100);
26 sprintf (attrname, "attr%d", i);
27 sprintf (attrdata, "%d", i);
28 ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
29 ale->attribute = GNUNET_RECLAIM_attribute_new (attrname,
30 &GNUNET_RECLAIM_ID_ZERO,
31 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
32 attrdata,
33 strlen (attrdata));
34 GNUNET_CONTAINER_DLL_insert (al->list_head,
35 al->list_tail,
36 ale);
37 }
38 ser_len_claimed = GNUNET_RECLAIM_attribute_list_serialize_get_size (al);
39 ser_data = GNUNET_malloc (ser_len_claimed);
40 ser_len_actual = GNUNET_RECLAIM_attribute_list_serialize (al,
41 ser_data);
42 GNUNET_assert (ser_len_claimed == ser_len_actual);
43 al_two = GNUNET_RECLAIM_attribute_list_deserialize (ser_data,
44 ser_len_actual);
45 for (ale = al_two->list_head; NULL != ale; ale = ale->next)
46 count++;
47 GNUNET_assert (12 == count);
48 //GNUNET_assert (-1 != deser_len);
49 GNUNET_free (ser_data);
50 GNUNET_RECLAIM_attribute_list_destroy (al);
51}
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
208 * Connection 208 * Connection
209 */ 209 */
210 struct MhdConnectionHandle *con_handle; 210 struct MhdConnectionHandle *con_handle;
211
212 /**
213 * State
214 */
215 int socket_with_mhd;
211}; 216};
212 217
213/** 218/**
@@ -310,7 +315,13 @@ cleanup_ar (struct AcceptedRequest *ar)
310 { 315 {
311 cleanup_handle (ar->con_handle); 316 cleanup_handle (ar->con_handle);
312 } 317 }
313 GNUNET_NETWORK_socket_free_memory_only_ (ar->sock); 318 if (GNUNET_YES == ar->socket_with_mhd)
319 {
320 GNUNET_NETWORK_socket_free_memory_only_ (ar->sock);
321 } else {
322 GNUNET_NETWORK_socket_close (ar->sock);
323 }
324 ar->sock = NULL;
314 GNUNET_CONTAINER_DLL_remove (req_list_head, 325 GNUNET_CONTAINER_DLL_remove (req_list_head,
315 req_list_tail, 326 req_list_tail,
316 ar); 327 ar);
@@ -529,7 +540,7 @@ create_response (void *cls,
529 MHD_suspend_connection (con_handle->con); 540 MHD_suspend_connection (con_handle->con);
530 return MHD_YES; 541 return MHD_YES;
531 } 542 }
532 MHD_resume_connection (con_handle->con); 543 //MHD_resume_connection (con_handle->con);
533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 544 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
534 "Queueing response from plugin with MHD\n"); 545 "Queueing response from plugin with MHD\n");
535 // Handle Preflights for extensions 546 // Handle Preflights for extensions
@@ -767,7 +778,7 @@ mhd_completed_cb (void *cls,
767 cleanup_handle (ar->con_handle); 778 cleanup_handle (ar->con_handle);
768 ar->con_handle = NULL; 779 ar->con_handle = NULL;
769 } 780 }
770 schedule_httpd (); 781 ar->socket_with_mhd = GNUNET_YES;
771 *con_cls = NULL; 782 *con_cls = NULL;
772} 783}
773 784
@@ -882,6 +893,7 @@ do_accept (void *cls)
882 else 893 else
883 GNUNET_assert (0); 894 GNUNET_assert (0);
884 ar = GNUNET_new (struct AcceptedRequest); 895 ar = GNUNET_new (struct AcceptedRequest);
896 ar->socket_with_mhd = GNUNET_YES;
885 ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL); 897 ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
886 if (NULL == ar->sock) 898 if (NULL == ar->sock)
887 { 899 {
@@ -925,7 +937,7 @@ do_shutdown (void *cls)
925 GNUNET_CONTAINER_DLL_remove (plugins_head, 937 GNUNET_CONTAINER_DLL_remove (plugins_head,
926 plugins_tail, 938 plugins_tail,
927 ple); 939 ple);
928 GNUNET_PLUGIN_unload (ple->libname, NULL); 940 GNUNET_PLUGIN_unload (ple->libname, ple->plugin);
929 GNUNET_free (ple->libname); 941 GNUNET_free (ple->libname);
930 GNUNET_free (ple); 942 GNUNET_free (ple);
931 } 943 }
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;
45struct RequestHandle 45struct RequestHandle
46{ 46{
47 /** 47 /**
48 * DLL
49 */
50 struct RequestHandle *next;
51
52 /**
53 * DLL
54 */
55 struct RequestHandle *prev;
56
57 /**
48 * Handle to rest request 58 * Handle to rest request
49 */ 59 */
50 struct GNUNET_REST_RequestHandle *rest_handle; 60 struct GNUNET_REST_RequestHandle *rest_handle;
@@ -70,6 +80,17 @@ struct RequestHandle
70 char *url; 80 char *url;
71}; 81};
72 82
83/**
84 * DLL
85 */
86static struct RequestHandle *requests_head;
87
88/**
89 * DLL
90 */
91static struct RequestHandle *requests_tail;
92
93
73 94
74/** 95/**
75 * Cleanup request handle. 96 * Cleanup request handle.
@@ -82,6 +103,9 @@ cleanup_handle (struct RequestHandle *handle)
82 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); 103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
83 if (NULL != handle->url) 104 if (NULL != handle->url)
84 GNUNET_free (handle->url); 105 GNUNET_free (handle->url);
106 GNUNET_CONTAINER_DLL_remove (requests_head,
107 requests_tail,
108 handle);
85 GNUNET_free (handle); 109 GNUNET_free (handle);
86} 110}
87 111
@@ -367,7 +391,9 @@ rest_config_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
367 handle->url = GNUNET_strdup (conndata_handle->url); 391 handle->url = GNUNET_strdup (conndata_handle->url);
368 if (handle->url[strlen (handle->url) - 1] == '/') 392 if (handle->url[strlen (handle->url) - 1] == '/')
369 handle->url[strlen (handle->url) - 1] = '\0'; 393 handle->url[strlen (handle->url) - 1] = '\0';
370 394 GNUNET_CONTAINER_DLL_insert (requests_head,
395 requests_tail,
396 handle);
371 if (GNUNET_NO == 397 if (GNUNET_NO ==
372 GNUNET_REST_handle_request (conndata_handle, handlers, &err, handle)) 398 GNUNET_REST_handle_request (conndata_handle, handlers, &err, handle))
373 { 399 {
@@ -392,15 +418,13 @@ libgnunet_plugin_rest_config_init (void *cls)
392 cfg = cls; 418 cfg = cls;
393 struct GNUNET_REST_Plugin *api; 419 struct GNUNET_REST_Plugin *api;
394 420
395 if (NULL != plugin.cfg)
396 return NULL; /* can only initialize once! */
397 memset (&plugin, 0, sizeof(struct Plugin)); 421 memset (&plugin, 0, sizeof(struct Plugin));
398 plugin.cfg = cfg; 422 plugin.cfg = cfg;
399 api = GNUNET_new (struct GNUNET_REST_Plugin); 423 api = GNUNET_new (struct GNUNET_REST_Plugin);
400 api->cls = &plugin; 424 api->cls = &plugin;
401 api->name = GNUNET_REST_API_NS_CONFIG; 425 api->name = GNUNET_REST_API_NS_CONFIG;
402 api->process_request = &rest_config_process_request; 426 api->process_request = &rest_config_process_request;
403 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("CONFIG REST API initialized\n")); 427 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("CONFIG REST API initialized\n"));
404 return api; 428 return api;
405} 429}
406 430
@@ -415,8 +439,11 @@ void *
415libgnunet_plugin_rest_config_done (void *cls) 439libgnunet_plugin_rest_config_done (void *cls)
416{ 440{
417 struct GNUNET_REST_Plugin *api = cls; 441 struct GNUNET_REST_Plugin *api = cls;
418 struct Plugin *plugin = api->cls; 442 struct Plugin *plugin;
419 443
444 while (NULL != requests_head)
445 cleanup_handle (requests_head);
446 plugin = api->cls;
420 plugin->cfg = NULL; 447 plugin->cfg = NULL;
421 GNUNET_free (api); 448 GNUNET_free (api);
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONFIG REST plugin is finished\n"); 449 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;
46struct RequestHandle 46struct RequestHandle
47{ 47{
48 /** 48 /**
49 * DLL
50 */
51 struct RequestHandle *next;
52
53 /**
54 * DLL
55 */
56 struct RequestHandle *prev;
57
58 /**
49 * Handle to rest request 59 * Handle to rest request
50 */ 60 */
51 struct GNUNET_REST_RequestHandle *rest_handle; 61 struct GNUNET_REST_RequestHandle *rest_handle;
@@ -66,6 +76,15 @@ struct RequestHandle
66 int response_code; 76 int response_code;
67}; 77};
68 78
79/**
80 * DLL
81 */
82static struct RequestHandle *requests_head;
83
84/**
85 * DLL
86 */
87static struct RequestHandle *requests_tail;
69 88
70/** 89/**
71 * Cleanup request handle. 90 * Cleanup request handle.
@@ -77,6 +96,9 @@ cleanup_handle (struct RequestHandle *handle)
77{ 96{
78 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 97 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
79 "Cleaning up\n"); 98 "Cleaning up\n");
99 GNUNET_CONTAINER_DLL_remove (requests_head,
100 requests_tail,
101 handle);
80 GNUNET_free (handle); 102 GNUNET_free (handle);
81} 103}
82 104
@@ -153,7 +175,9 @@ rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
153 handle->proc_cls = proc_cls; 175 handle->proc_cls = proc_cls;
154 handle->proc = proc; 176 handle->proc = proc;
155 handle->rest_handle = conndata_handle; 177 handle->rest_handle = conndata_handle;
156 178 GNUNET_CONTAINER_DLL_insert (requests_head,
179 requests_tail,
180 handle);
157 return GNUNET_REST_handle_request (conndata_handle, 181 return GNUNET_REST_handle_request (conndata_handle,
158 handlers, 182 handlers,
159 &err, 183 &err,
@@ -201,6 +225,8 @@ libgnunet_plugin_rest_copying_done (void *cls)
201 struct GNUNET_REST_Plugin *api = cls; 225 struct GNUNET_REST_Plugin *api = cls;
202 struct Plugin *plugin = api->cls; 226 struct Plugin *plugin = api->cls;
203 227
228 while (NULL != requests_head)
229 cleanup_handle (requests_head);
204 plugin->cfg = NULL; 230 plugin->cfg = NULL;
205 GNUNET_free (api); 231 GNUNET_free (api);
206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 232 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
2gnunet-revocation 2gnunet-revocation
3test_revocation 3test_revocation
4test_local_revocation.py 4test_local_revocation.py
5gnunet-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 = \
78gnunet_service_revocation_LDADD = \ 78gnunet_service_revocation_LDADD = \
79 libgnunetrevocation.la \ 79 libgnunetrevocation.la \
80 $(top_builddir)/src/core/libgnunetcore.la \ 80 $(top_builddir)/src/core/libgnunetcore.la \
81 $(top_builddir)/src/set/libgnunetset.la \ 81 $(top_builddir)/src/setu/libgnunetsetu.la \
82 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 82 $(top_builddir)/src/statistics/libgnunetstatistics.la \
83 $(top_builddir)/src/util/libgnunetutil.la \ 83 $(top_builddir)/src/util/libgnunetutil.la \
84 -lm \ 84 -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 @@
45#include "gnunet_statistics_service.h" 45#include "gnunet_statistics_service.h"
46#include "gnunet_core_service.h" 46#include "gnunet_core_service.h"
47#include "gnunet_revocation_service.h" 47#include "gnunet_revocation_service.h"
48#include "gnunet_set_service.h" 48#include "gnunet_setu_service.h"
49#include "revocation.h" 49#include "revocation.h"
50#include <gcrypt.h> 50#include <gcrypt.h>
51 51
@@ -73,14 +73,14 @@ struct PeerEntry
73 /** 73 /**
74 * Handle to active set union operation (over revocation sets). 74 * Handle to active set union operation (over revocation sets).
75 */ 75 */
76 struct GNUNET_SET_OperationHandle *so; 76 struct GNUNET_SETU_OperationHandle *so;
77}; 77};
78 78
79 79
80/** 80/**
81 * Set from all revocations known to us. 81 * Set from all revocations known to us.
82 */ 82 */
83static struct GNUNET_SET_Handle *revocation_set; 83static struct GNUNET_SETU_Handle *revocation_set;
84 84
85/** 85/**
86 * Hash map with all revoked keys, maps the hash of the public key 86 * Hash map with all revoked keys, maps the hash of the public key
@@ -121,7 +121,7 @@ static struct GNUNET_DISK_FileHandle *revocation_db;
121/** 121/**
122 * Handle for us listening to incoming revocation set union requests. 122 * Handle for us listening to incoming revocation set union requests.
123 */ 123 */
124static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle; 124static struct GNUNET_SETU_ListenHandle *revocation_union_listen_handle;
125 125
126/** 126/**
127 * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. 127 * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits.
@@ -302,7 +302,7 @@ publicize_rm (const struct RevokeMessage *rm)
302{ 302{
303 struct RevokeMessage *cp; 303 struct RevokeMessage *cp;
304 struct GNUNET_HashCode hc; 304 struct GNUNET_HashCode hc;
305 struct GNUNET_SET_Element e; 305 struct GNUNET_SETU_Element e;
306 306
307 GNUNET_CRYPTO_hash (&rm->proof_of_work.key, 307 GNUNET_CRYPTO_hash (&rm->proof_of_work.key,
308 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), 308 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
@@ -350,10 +350,10 @@ publicize_rm (const struct RevokeMessage *rm)
350 e.element_type = GNUNET_BLOCK_TYPE_REVOCATION; 350 e.element_type = GNUNET_BLOCK_TYPE_REVOCATION;
351 e.data = rm; 351 e.data = rm;
352 if (GNUNET_OK != 352 if (GNUNET_OK !=
353 GNUNET_SET_add_element (revocation_set, 353 GNUNET_SETU_add_element (revocation_set,
354 &e, 354 &e,
355 NULL, 355 NULL,
356 NULL)) 356 NULL))
357 { 357 {
358 GNUNET_break (0); 358 GNUNET_break (0);
359 return GNUNET_OK; 359 return GNUNET_OK;
@@ -426,22 +426,22 @@ handle_p2p_revoke (void *cls,
426 * validate and then add to our revocation list (and set). 426 * validate and then add to our revocation list (and set).
427 * 427 *
428 * @param cls closure 428 * @param cls closure
429 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK 429 * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
430 * @param current_size current set size 430 * @param current_size current set size
431 * @param status see `enum GNUNET_SET_Status` 431 * @param status see `enum GNUNET_SETU_Status`
432 */ 432 */
433static void 433static void
434add_revocation (void *cls, 434add_revocation (void *cls,
435 const struct GNUNET_SET_Element *element, 435 const struct GNUNET_SETU_Element *element,
436 uint64_t current_size, 436 uint64_t current_size,
437 enum GNUNET_SET_Status status) 437 enum GNUNET_SETU_Status status)
438{ 438{
439 struct PeerEntry *peer_entry = cls; 439 struct PeerEntry *peer_entry = cls;
440 const struct RevokeMessage *rm; 440 const struct RevokeMessage *rm;
441 441
442 switch (status) 442 switch (status)
443 { 443 {
444 case GNUNET_SET_STATUS_OK: 444 case GNUNET_SETU_STATUS_ADD_LOCAL:
445 if (element->size != sizeof(struct RevokeMessage)) 445 if (element->size != sizeof(struct RevokeMessage))
446 { 446 {
447 GNUNET_break_op (0); 447 GNUNET_break_op (0);
@@ -464,8 +464,7 @@ add_revocation (void *cls,
464 "# revocation messages received via set union"), 464 "# revocation messages received via set union"),
465 1, GNUNET_NO); 465 1, GNUNET_NO);
466 break; 466 break;
467 467 case GNUNET_SETU_STATUS_FAILURE:
468 case GNUNET_SET_STATUS_FAILURE:
469 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 468 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
470 _ ("Error computing revocation set union with %s\n"), 469 _ ("Error computing revocation set union with %s\n"),
471 GNUNET_i2s (&peer_entry->id)); 470 GNUNET_i2s (&peer_entry->id));
@@ -475,11 +474,7 @@ add_revocation (void *cls,
475 1, 474 1,
476 GNUNET_NO); 475 GNUNET_NO);
477 break; 476 break;
478 477 case GNUNET_SETU_STATUS_DONE:
479 case GNUNET_SET_STATUS_HALF_DONE:
480 break;
481
482 case GNUNET_SET_STATUS_DONE:
483 peer_entry->so = NULL; 478 peer_entry->so = NULL;
484 GNUNET_STATISTICS_update (stats, 479 GNUNET_STATISTICS_update (stats,
485 gettext_noop ( 480 gettext_noop (
@@ -487,7 +482,6 @@ add_revocation (void *cls,
487 1, 482 1,
488 GNUNET_NO); 483 GNUNET_NO);
489 break; 484 break;
490
491 default: 485 default:
492 GNUNET_break (0); 486 GNUNET_break (0);
493 break; 487 break;
@@ -511,16 +505,15 @@ transmit_task_cb (void *cls)
511 GNUNET_i2s (&peer_entry->id)); 505 GNUNET_i2s (&peer_entry->id));
512 peer_entry->transmit_task = NULL; 506 peer_entry->transmit_task = NULL;
513 GNUNET_assert (NULL == peer_entry->so); 507 GNUNET_assert (NULL == peer_entry->so);
514 peer_entry->so = GNUNET_SET_prepare (&peer_entry->id, 508 peer_entry->so = GNUNET_SETU_prepare (&peer_entry->id,
515 &revocation_set_union_app_id, 509 &revocation_set_union_app_id,
516 NULL, 510 NULL,
517 GNUNET_SET_RESULT_ADDED, 511 (struct GNUNET_SETU_Option[]) { { 0 } },
518 (struct GNUNET_SET_Option[]) { { 0 } }, 512 &add_revocation,
519 &add_revocation, 513 peer_entry);
520 peer_entry);
521 if (GNUNET_OK != 514 if (GNUNET_OK !=
522 GNUNET_SET_commit (peer_entry->so, 515 GNUNET_SETU_commit (peer_entry->so,
523 revocation_set)) 516 revocation_set))
524 { 517 {
525 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 518 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
526 _ ("SET service crashed, terminating revocation service\n")); 519 _ ("SET service crashed, terminating revocation service\n"));
@@ -626,7 +619,7 @@ handle_core_disconnect (void *cls,
626 } 619 }
627 if (NULL != peer_entry->so) 620 if (NULL != peer_entry->so)
628 { 621 {
629 GNUNET_SET_operation_cancel (peer_entry->so); 622 GNUNET_SETU_operation_cancel (peer_entry->so);
630 peer_entry->so = NULL; 623 peer_entry->so = NULL;
631 } 624 }
632 GNUNET_free (peer_entry); 625 GNUNET_free (peer_entry);
@@ -665,12 +658,12 @@ shutdown_task (void *cls)
665{ 658{
666 if (NULL != revocation_set) 659 if (NULL != revocation_set)
667 { 660 {
668 GNUNET_SET_destroy (revocation_set); 661 GNUNET_SETU_destroy (revocation_set);
669 revocation_set = NULL; 662 revocation_set = NULL;
670 } 663 }
671 if (NULL != revocation_union_listen_handle) 664 if (NULL != revocation_union_listen_handle)
672 { 665 {
673 GNUNET_SET_listen_cancel (revocation_union_listen_handle); 666 GNUNET_SETU_listen_cancel (revocation_union_listen_handle);
674 revocation_union_listen_handle = NULL; 667 revocation_union_listen_handle = NULL;
675 } 668 }
676 if (NULL != core_api) 669 if (NULL != core_api)
@@ -729,7 +722,7 @@ core_init (void *cls,
729 * @param other_peer the other peer 722 * @param other_peer the other peer
730 * @param context_msg message with application specific information from 723 * @param context_msg message with application specific information from
731 * the other peer 724 * the other peer
732 * @param request request from the other peer (never NULL), use GNUNET_SET_accept() 725 * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
733 * to accept it, otherwise the request will be refused 726 * to accept it, otherwise the request will be refused
734 * Note that we can't just return value from the listen callback, 727 * Note that we can't just return value from the listen callback,
735 * as it is also necessary to specify the set we want to do the 728 * as it is also necessary to specify the set we want to do the
@@ -740,7 +733,7 @@ static void
740handle_revocation_union_request (void *cls, 733handle_revocation_union_request (void *cls,
741 const struct GNUNET_PeerIdentity *other_peer, 734 const struct GNUNET_PeerIdentity *other_peer,
742 const struct GNUNET_MessageHeader *context_msg, 735 const struct GNUNET_MessageHeader *context_msg,
743 struct GNUNET_SET_Request *request) 736 struct GNUNET_SETU_Request *request)
744{ 737{
745 struct PeerEntry *peer_entry; 738 struct PeerEntry *peer_entry;
746 739
@@ -763,14 +756,13 @@ handle_revocation_union_request (void *cls,
763 GNUNET_break_op (0); 756 GNUNET_break_op (0);
764 return; 757 return;
765 } 758 }
766 peer_entry->so = GNUNET_SET_accept (request, 759 peer_entry->so = GNUNET_SETU_accept (request,
767 GNUNET_SET_RESULT_ADDED, 760 (struct GNUNET_SETU_Option[]) { { 0 } },
768 (struct GNUNET_SET_Option[]) { { 0 } }, 761 &add_revocation,
769 &add_revocation, 762 peer_entry);
770 peer_entry);
771 if (GNUNET_OK != 763 if (GNUNET_OK !=
772 GNUNET_SET_commit (peer_entry->so, 764 GNUNET_SETU_commit (peer_entry->so,
773 revocation_set)) 765 revocation_set))
774 { 766 {
775 GNUNET_break (0); 767 GNUNET_break (0);
776 GNUNET_SCHEDULER_shutdown (); 768 GNUNET_SCHEDULER_shutdown ();
@@ -858,14 +850,12 @@ run (void *cls,
858 return; 850 return;
859 } 851 }
860 852
861 revocation_set = GNUNET_SET_create (cfg, 853 revocation_set = GNUNET_SETU_create (cfg);
862 GNUNET_SET_OPERATION_UNION);
863 revocation_union_listen_handle 854 revocation_union_listen_handle
864 = GNUNET_SET_listen (cfg, 855 = GNUNET_SETU_listen (cfg,
865 GNUNET_SET_OPERATION_UNION, 856 &revocation_set_union_app_id,
866 &revocation_set_union_app_id, 857 &handle_revocation_union_request,
867 &handle_revocation_union_request, 858 NULL);
868 NULL);
869 revocation_db = GNUNET_DISK_file_open (fn, 859 revocation_db = GNUNET_DISK_file_open (fn,
870 GNUNET_DISK_OPEN_READWRITE 860 GNUNET_DISK_OPEN_READWRITE
871 | GNUNET_DISK_OPEN_CREATE, 861 | 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
103 103
104}; 104};
105 105
106static struct GNUNET_CRYPTO_PowSalt salt = { "GnsRevocationPow" };
107
106/** 108/**
107 * Generic error handler, called with the appropriate 109 * Generic error handler, called with the appropriate
108 * error code and the same closure specified at the creation of 110 * 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,
483 { 485 {
484 pow_val = GNUNET_ntohll (pow->pow[i]); 486 pow_val = GNUNET_ntohll (pow->pow[i]);
485 GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t)); 487 GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t));
486 GNUNET_CRYPTO_pow_hash ("GnsRevocationPow", 488 GNUNET_CRYPTO_pow_hash (&salt,
487 buf, 489 buf,
488 sizeof(buf), 490 sizeof(buf),
489 &result); 491 &result);
@@ -644,7 +646,7 @@ GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
644 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2], 646 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
645 &pc->pow->key, 647 &pc->pow->key,
646 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); 648 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
647 GNUNET_CRYPTO_pow_hash ("GnsRevocationPow", 649 GNUNET_CRYPTO_pow_hash (&salt,
648 buf, 650 buf,
649 sizeof(buf), 651 sizeof(buf),
650 &result); 652 &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 = \
39gnunet_service_scalarproduct_alice_LDADD = \ 39gnunet_service_scalarproduct_alice_LDADD = \
40 $(top_builddir)/src/util/libgnunetutil.la \ 40 $(top_builddir)/src/util/libgnunetutil.la \
41 $(top_builddir)/src/cadet/libgnunetcadet.la \ 41 $(top_builddir)/src/cadet/libgnunetcadet.la \
42 $(top_builddir)/src/set/libgnunetset.la \ 42 $(top_builddir)/src/seti/libgnunetseti.la \
43 $(LIBGCRYPT_LIBS) \ 43 $(LIBGCRYPT_LIBS) \
44 -lgcrypt \ 44 -lgcrypt \
45 $(GN_LIBINTL) 45 $(GN_LIBINTL)
@@ -50,7 +50,7 @@ gnunet_service_scalarproduct_bob_SOURCES = \
50gnunet_service_scalarproduct_bob_LDADD = \ 50gnunet_service_scalarproduct_bob_LDADD = \
51 $(top_builddir)/src/util/libgnunetutil.la \ 51 $(top_builddir)/src/util/libgnunetutil.la \
52 $(top_builddir)/src/cadet/libgnunetcadet.la \ 52 $(top_builddir)/src/cadet/libgnunetcadet.la \
53 $(top_builddir)/src/set/libgnunetset.la \ 53 $(top_builddir)/src/seti/libgnunetseti.la \
54 $(LIBGCRYPT_LIBS) \ 54 $(LIBGCRYPT_LIBS) \
55 -lgcrypt \ 55 -lgcrypt \
56 $(GN_LIBINTL) 56 $(GN_LIBINTL)
@@ -61,7 +61,7 @@ gnunet_service_scalarproduct_ecc_alice_SOURCES = \
61gnunet_service_scalarproduct_ecc_alice_LDADD = \ 61gnunet_service_scalarproduct_ecc_alice_LDADD = \
62 $(top_builddir)/src/util/libgnunetutil.la \ 62 $(top_builddir)/src/util/libgnunetutil.la \
63 $(top_builddir)/src/cadet/libgnunetcadet.la \ 63 $(top_builddir)/src/cadet/libgnunetcadet.la \
64 $(top_builddir)/src/set/libgnunetset.la \ 64 $(top_builddir)/src/seti/libgnunetseti.la \
65 $(LIBGCRYPT_LIBS) \ 65 $(LIBGCRYPT_LIBS) \
66 -lgcrypt \ 66 -lgcrypt \
67 $(GN_LIBINTL) 67 $(GN_LIBINTL)
@@ -72,7 +72,7 @@ gnunet_service_scalarproduct_ecc_bob_SOURCES = \
72gnunet_service_scalarproduct_ecc_bob_LDADD = \ 72gnunet_service_scalarproduct_ecc_bob_LDADD = \
73 $(top_builddir)/src/util/libgnunetutil.la \ 73 $(top_builddir)/src/util/libgnunetutil.la \
74 $(top_builddir)/src/cadet/libgnunetcadet.la \ 74 $(top_builddir)/src/cadet/libgnunetcadet.la \
75 $(top_builddir)/src/set/libgnunetset.la \ 75 $(top_builddir)/src/seti/libgnunetseti.la \
76 $(LIBGCRYPT_LIBS) \ 76 $(LIBGCRYPT_LIBS) \
77 -lgcrypt \ 77 -lgcrypt \
78 $(GN_LIBINTL) 78 $(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 @@
32#include "gnunet_applications.h" 32#include "gnunet_applications.h"
33#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
34#include "gnunet_scalarproduct_service.h" 34#include "gnunet_scalarproduct_service.h"
35#include "gnunet_set_service.h" 35#include "gnunet_seti_service.h"
36#include "scalarproduct.h" 36#include "scalarproduct.h"
37#include "gnunet-service-scalarproduct-ecc.h" 37#include "gnunet-service-scalarproduct-ecc.h"
38 38
@@ -114,18 +114,18 @@ struct AliceServiceSession
114 * Set of elements for which will conduction an intersection. 114 * Set of elements for which will conduction an intersection.
115 * the resulting elements are then used for computing the scalar product. 115 * the resulting elements are then used for computing the scalar product.
116 */ 116 */
117 struct GNUNET_SET_Handle *intersection_set; 117 struct GNUNET_SETI_Handle *intersection_set;
118 118
119 /** 119 /**
120 * Set of elements for which will conduction an intersection. 120 * Set of elements for which will conduction an intersection.
121 * the resulting elements are then used for computing the scalar product. 121 * the resulting elements are then used for computing the scalar product.
122 */ 122 */
123 struct GNUNET_SET_OperationHandle *intersection_op; 123 struct GNUNET_SETI_OperationHandle *intersection_op;
124 124
125 /** 125 /**
126 * Handle to Alice's Intersection operation listening for Bob 126 * Handle to Alice's Intersection operation listening for Bob
127 */ 127 */
128 struct GNUNET_SET_ListenHandle *intersection_listen; 128 struct GNUNET_SETI_ListenHandle *intersection_listen;
129 129
130 /** 130 /**
131 * channel-handle associated with our cadet handle 131 * channel-handle associated with our cadet handle
@@ -256,18 +256,18 @@ destroy_service_session (struct AliceServiceSession *s)
256 } 256 }
257 if (NULL != s->intersection_listen) 257 if (NULL != s->intersection_listen)
258 { 258 {
259 GNUNET_SET_listen_cancel (s->intersection_listen); 259 GNUNET_SETI_listen_cancel (s->intersection_listen);
260 s->intersection_listen = NULL; 260 s->intersection_listen = NULL;
261 } 261 }
262 if (NULL != s->intersection_op) 262 if (NULL != s->intersection_op)
263 { 263 {
264 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection, op still ongoing!\n"); 264 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection, op still ongoing!\n");
265 GNUNET_SET_operation_cancel (s->intersection_op); 265 GNUNET_SETI_operation_cancel (s->intersection_op);
266 s->intersection_op = NULL; 266 s->intersection_op = NULL;
267 } 267 }
268 if (NULL != s->intersection_set) 268 if (NULL != s->intersection_set)
269 { 269 {
270 GNUNET_SET_destroy (s->intersection_set); 270 GNUNET_SETI_destroy (s->intersection_set);
271 s->intersection_set = NULL; 271 s->intersection_set = NULL;
272 } 272 }
273 if (NULL != s->sorted_elements) 273 if (NULL != s->sorted_elements)
@@ -649,22 +649,22 @@ send_alices_cryptodata_message (struct AliceServiceSession *s)
649 * to indicate that the set intersection operation is done. 649 * to indicate that the set intersection operation is done.
650 * 650 *
651 * @param cls closure with the `struct AliceServiceSession` 651 * @param cls closure with the `struct AliceServiceSession`
652 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK 652 * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
653 * @param current_size current set size 653 * @param current_size current set size
654 * @param status what has happened with the set intersection? 654 * @param status what has happened with the set intersection?
655 */ 655 */
656static void 656static void
657cb_intersection_element_removed (void *cls, 657cb_intersection_element_removed (void *cls,
658 const struct GNUNET_SET_Element *element, 658 const struct GNUNET_SETI_Element *element,
659 uint64_t current_size, 659 uint64_t current_size,
660 enum GNUNET_SET_Status status) 660 enum GNUNET_SETI_Status status)
661{ 661{
662 struct AliceServiceSession *s = cls; 662 struct AliceServiceSession *s = cls;
663 struct GNUNET_SCALARPRODUCT_Element *se; 663 struct GNUNET_SCALARPRODUCT_Element *se;
664 664
665 switch (status) 665 switch (status)
666 { 666 {
667 case GNUNET_SET_STATUS_OK: 667 case GNUNET_SETI_STATUS_DEL_LOCAL:
668 /* this element has been removed from the set */ 668 /* this element has been removed from the set */
669 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements, 669 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
670 element->data); 670 element->data);
@@ -680,34 +680,27 @@ cb_intersection_element_removed (void *cls,
680 se)); 680 se));
681 GNUNET_free (se); 681 GNUNET_free (se);
682 return; 682 return;
683 683 case GNUNET_SETI_STATUS_DONE:
684 case GNUNET_SET_STATUS_DONE:
685 s->intersection_op = NULL; 684 s->intersection_op = NULL;
686 if (NULL != s->intersection_set) 685 if (NULL != s->intersection_set)
687 { 686 {
688 GNUNET_SET_destroy (s->intersection_set); 687 GNUNET_SETI_destroy (s->intersection_set);
689 s->intersection_set = NULL; 688 s->intersection_set = NULL;
690 } 689 }
691 send_alices_cryptodata_message (s); 690 send_alices_cryptodata_message (s);
692 return; 691 return;
693 692 case GNUNET_SETI_STATUS_FAILURE:
694 case GNUNET_SET_STATUS_HALF_DONE:
695 /* unexpected for intersection */
696 GNUNET_break (0);
697 return;
698
699 case GNUNET_SET_STATUS_FAILURE:
700 /* unhandled status code */ 693 /* unhandled status code */
701 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n"); 694 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
702 if (NULL != s->intersection_listen) 695 if (NULL != s->intersection_listen)
703 { 696 {
704 GNUNET_SET_listen_cancel (s->intersection_listen); 697 GNUNET_SETI_listen_cancel (s->intersection_listen);
705 s->intersection_listen = NULL; 698 s->intersection_listen = NULL;
706 } 699 }
707 s->intersection_op = NULL; 700 s->intersection_op = NULL;
708 if (NULL != s->intersection_set) 701 if (NULL != s->intersection_set)
709 { 702 {
710 GNUNET_SET_destroy (s->intersection_set); 703 GNUNET_SETI_destroy (s->intersection_set);
711 s->intersection_set = NULL; 704 s->intersection_set = NULL;
712 } 705 }
713 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 706 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -729,7 +722,7 @@ cb_intersection_element_removed (void *cls,
729 * @param other_peer the other peer 722 * @param other_peer the other peer
730 * @param context_msg message with application specific information from 723 * @param context_msg message with application specific information from
731 * the other peer 724 * the other peer
732 * @param request request from the other peer (never NULL), use GNUNET_SET_accept() 725 * @param request request from the other peer (never NULL), use GNUNET_SETI_accept()
733 * to accept it, otherwise the request will be refused 726 * to accept it, otherwise the request will be refused
734 * Note that we can't just return value from the listen callback, 727 * Note that we can't just return value from the listen callback,
735 * as it is also necessary to specify the set we want to do the 728 * as it is also necessary to specify the set we want to do the
@@ -740,7 +733,7 @@ static void
740cb_intersection_request_alice (void *cls, 733cb_intersection_request_alice (void *cls,
741 const struct GNUNET_PeerIdentity *other_peer, 734 const struct GNUNET_PeerIdentity *other_peer,
742 const struct GNUNET_MessageHeader *context_msg, 735 const struct GNUNET_MessageHeader *context_msg,
743 struct GNUNET_SET_Request *request) 736 struct GNUNET_SETI_Request *request)
744{ 737{
745 struct AliceServiceSession *s = cls; 738 struct AliceServiceSession *s = cls;
746 739
@@ -752,11 +745,11 @@ cb_intersection_request_alice (void *cls,
752 GNUNET_break_op (0); 745 GNUNET_break_op (0);
753 return; 746 return;
754 } 747 }
755 s->intersection_op = GNUNET_SET_accept (request, 748 s->intersection_op = GNUNET_SETI_accept (request,
756 GNUNET_SET_RESULT_REMOVED, 749 (struct
757 (struct GNUNET_SET_Option[]){ { 0 } }, 750 GNUNET_SETI_Option[]){ { 0 } },
758 &cb_intersection_element_removed, 751 &cb_intersection_element_removed,
759 s); 752 s);
760 if (NULL == s->intersection_op) 753 if (NULL == s->intersection_op)
761 { 754 {
762 GNUNET_break (0); 755 GNUNET_break (0);
@@ -764,7 +757,7 @@ cb_intersection_request_alice (void *cls,
764 prepare_client_end_notification (s); 757 prepare_client_end_notification (s);
765 return; 758 return;
766 } 759 }
767 if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set)) 760 if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
768 { 761 {
769 GNUNET_break (0); 762 GNUNET_break (0);
770 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 763 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -812,11 +805,10 @@ client_request_complete_alice (struct AliceServiceSession *s)
812 return; 805 return;
813 } 806 }
814 s->cadet_mq = GNUNET_CADET_get_mq (s->channel); 807 s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
815 s->intersection_listen = GNUNET_SET_listen (cfg, 808 s->intersection_listen = GNUNET_SETI_listen (cfg,
816 GNUNET_SET_OPERATION_INTERSECTION, 809 &set_sid,
817 &set_sid, 810 &cb_intersection_request_alice,
818 &cb_intersection_request_alice, 811 s);
819 s);
820 if (NULL == s->intersection_listen) 812 if (NULL == s->intersection_listen)
821 { 813 {
822 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 814 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -883,7 +875,7 @@ handle_alice_client_message_multipart (
883 struct AliceServiceSession *s = cls; 875 struct AliceServiceSession *s = cls;
884 uint32_t contained_count; 876 uint32_t contained_count;
885 const struct GNUNET_SCALARPRODUCT_Element *elements; 877 const struct GNUNET_SCALARPRODUCT_Element *elements;
886 struct GNUNET_SET_Element set_elem; 878 struct GNUNET_SETI_Element set_elem;
887 struct GNUNET_SCALARPRODUCT_Element *elem; 879 struct GNUNET_SCALARPRODUCT_Element *elem;
888 880
889 contained_count = ntohl (msg->element_count_contained); 881 contained_count = ntohl (msg->element_count_contained);
@@ -908,7 +900,7 @@ handle_alice_client_message_multipart (
908 set_elem.data = &elem->key; 900 set_elem.data = &elem->key;
909 set_elem.size = sizeof(elem->key); 901 set_elem.size = sizeof(elem->key);
910 set_elem.element_type = 0; 902 set_elem.element_type = 0;
911 GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL); 903 GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
912 s->used_element_count++; 904 s->used_element_count++;
913 } 905 }
914 GNUNET_SERVICE_client_continue (s->client); 906 GNUNET_SERVICE_client_continue (s->client);
@@ -978,7 +970,7 @@ handle_alice_client_message (void *cls,
978 uint32_t contained_count; 970 uint32_t contained_count;
979 uint32_t total_count; 971 uint32_t total_count;
980 const struct GNUNET_SCALARPRODUCT_Element *elements; 972 const struct GNUNET_SCALARPRODUCT_Element *elements;
981 struct GNUNET_SET_Element set_elem; 973 struct GNUNET_SETI_Element set_elem;
982 struct GNUNET_SCALARPRODUCT_Element *elem; 974 struct GNUNET_SCALARPRODUCT_Element *elem;
983 975
984 total_count = ntohl (msg->element_count_total); 976 total_count = ntohl (msg->element_count_total);
@@ -991,8 +983,7 @@ handle_alice_client_message (void *cls,
991 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1]; 983 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
992 s->intersected_elements = 984 s->intersected_elements =
993 GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES); 985 GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES);
994 s->intersection_set = 986 s->intersection_set = GNUNET_SETI_create (cfg);
995 GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
996 for (uint32_t i = 0; i < contained_count; i++) 987 for (uint32_t i = 0; i < contained_count; i++)
997 { 988 {
998 if (0 == GNUNET_ntohll (elements[i].value)) 989 if (0 == GNUNET_ntohll (elements[i].value))
@@ -1015,7 +1006,7 @@ handle_alice_client_message (void *cls,
1015 set_elem.data = &elem->key; 1006 set_elem.data = &elem->key;
1016 set_elem.size = sizeof(elem->key); 1007 set_elem.size = sizeof(elem->key);
1017 set_elem.element_type = 0; 1008 set_elem.element_type = 0;
1018 GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL); 1009 GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
1019 s->used_element_count++; 1010 s->used_element_count++;
1020 } 1011 }
1021 GNUNET_SERVICE_client_continue (s->client); 1012 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 @@
32#include "gnunet_applications.h" 32#include "gnunet_applications.h"
33#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
34#include "gnunet_scalarproduct_service.h" 34#include "gnunet_scalarproduct_service.h"
35#include "gnunet_set_service.h" 35#include "gnunet_seti_service.h"
36#include "scalarproduct.h" 36#include "scalarproduct.h"
37#include "gnunet-service-scalarproduct-ecc.h" 37#include "gnunet-service-scalarproduct-ecc.h"
38 38
@@ -83,13 +83,13 @@ struct BobServiceSession
83 * Set of elements for which we will be conducting an intersection. 83 * Set of elements for which we will be conducting an intersection.
84 * The resulting elements are then used for computing the scalar product. 84 * The resulting elements are then used for computing the scalar product.
85 */ 85 */
86 struct GNUNET_SET_Handle *intersection_set; 86 struct GNUNET_SETI_Handle *intersection_set;
87 87
88 /** 88 /**
89 * Set of elements for which will conduction an intersection. 89 * Set of elements for which will conduction an intersection.
90 * the resulting elements are then used for computing the scalar product. 90 * the resulting elements are then used for computing the scalar product.
91 */ 91 */
92 struct GNUNET_SET_OperationHandle *intersection_op; 92 struct GNUNET_SETI_OperationHandle *intersection_op;
93 93
94 /** 94 /**
95 * Our open port. 95 * Our open port.
@@ -235,12 +235,12 @@ destroy_service_session (struct BobServiceSession *s)
235 } 235 }
236 if (NULL != s->intersection_op) 236 if (NULL != s->intersection_op)
237 { 237 {
238 GNUNET_SET_operation_cancel (s->intersection_op); 238 GNUNET_SETI_operation_cancel (s->intersection_op);
239 s->intersection_op = NULL; 239 s->intersection_op = NULL;
240 } 240 }
241 if (NULL != s->intersection_set) 241 if (NULL != s->intersection_set)
242 { 242 {
243 GNUNET_SET_destroy (s->intersection_set); 243 GNUNET_SETI_destroy (s->intersection_set);
244 s->intersection_set = NULL; 244 s->intersection_set = NULL;
245 } 245 }
246 if (NULL != s->sorted_elements) 246 if (NULL != s->sorted_elements)
@@ -578,22 +578,22 @@ handle_alices_cryptodata_message (void *cls,
578 * that needs to be removed from the result set. 578 * that needs to be removed from the result set.
579 * 579 *
580 * @param cls closure with the `struct BobServiceSession` 580 * @param cls closure with the `struct BobServiceSession`
581 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK 581 * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
582 * @param current_size current set size 582 * @param current_size current set size
583 * @param status what has happened with the set intersection? 583 * @param status what has happened with the set intersection?
584 */ 584 */
585static void 585static void
586cb_intersection_element_removed (void *cls, 586cb_intersection_element_removed (void *cls,
587 const struct GNUNET_SET_Element *element, 587 const struct GNUNET_SETI_Element *element,
588 uint64_t current_size, 588 uint64_t current_size,
589 enum GNUNET_SET_Status status) 589 enum GNUNET_SETI_Status status)
590{ 590{
591 struct BobServiceSession *s = cls; 591 struct BobServiceSession *s = cls;
592 struct GNUNET_SCALARPRODUCT_Element *se; 592 struct GNUNET_SCALARPRODUCT_Element *se;
593 593
594 switch (status) 594 switch (status)
595 { 595 {
596 case GNUNET_SET_STATUS_OK: 596 case GNUNET_SETI_STATUS_DEL_LOCAL:
597 /* this element has been removed from the set */ 597 /* this element has been removed from the set */
598 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements, 598 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
599 element->data); 599 element->data);
@@ -609,8 +609,7 @@ cb_intersection_element_removed (void *cls,
609 se)); 609 se));
610 GNUNET_free (se); 610 GNUNET_free (se);
611 return; 611 return;
612 612 case GNUNET_SETI_STATUS_DONE:
613 case GNUNET_SET_STATUS_DONE:
614 s->intersection_op = NULL; 613 s->intersection_op = NULL;
615 GNUNET_break (NULL == s->intersection_set); 614 GNUNET_break (NULL == s->intersection_set);
616 GNUNET_CADET_receive_done (s->channel); 615 GNUNET_CADET_receive_done (s->channel);
@@ -625,20 +624,14 @@ cb_intersection_element_removed (void *cls,
625 transmit_bobs_cryptodata_message (s); 624 transmit_bobs_cryptodata_message (s);
626 } 625 }
627 return; 626 return;
628 627 case GNUNET_SETI_STATUS_FAILURE:
629 case GNUNET_SET_STATUS_HALF_DONE:
630 /* unexpected for intersection */
631 GNUNET_break (0);
632 return;
633
634 case GNUNET_SET_STATUS_FAILURE:
635 /* unhandled status code */ 628 /* unhandled status code */
636 LOG (GNUNET_ERROR_TYPE_DEBUG, 629 LOG (GNUNET_ERROR_TYPE_DEBUG,
637 "Set intersection failed!\n"); 630 "Set intersection failed!\n");
638 s->intersection_op = NULL; 631 s->intersection_op = NULL;
639 if (NULL != s->intersection_set) 632 if (NULL != s->intersection_set)
640 { 633 {
641 GNUNET_SET_destroy (s->intersection_set); 634 GNUNET_SETI_destroy (s->intersection_set);
642 s->intersection_set = NULL; 635 s->intersection_set = NULL;
643 } 636 }
644 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 637 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -672,23 +665,22 @@ start_intersection (struct BobServiceSession *s)
672 (unsigned int) s->total); 665 (unsigned int) s->total);
673 666
674 s->intersection_op 667 s->intersection_op
675 = GNUNET_SET_prepare (&s->peer, 668 = GNUNET_SETI_prepare (&s->peer,
676 &set_sid, 669 &set_sid,
677 NULL, 670 NULL,
678 GNUNET_SET_RESULT_REMOVED, 671 (struct GNUNET_SETI_Option[]) { { 0 } },
679 (struct GNUNET_SET_Option[]) { { 0 } }, 672 &cb_intersection_element_removed,
680 &cb_intersection_element_removed, 673 s);
681 s);
682 if (GNUNET_OK != 674 if (GNUNET_OK !=
683 GNUNET_SET_commit (s->intersection_op, 675 GNUNET_SETI_commit (s->intersection_op,
684 s->intersection_set)) 676 s->intersection_set))
685 { 677 {
686 GNUNET_break (0); 678 GNUNET_break (0);
687 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 679 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
688 prepare_client_end_notification (s); 680 prepare_client_end_notification (s);
689 return; 681 return;
690 } 682 }
691 GNUNET_SET_destroy (s->intersection_set); 683 GNUNET_SETI_destroy (s->intersection_set);
692 s->intersection_set = NULL; 684 s->intersection_set = NULL;
693} 685}
694 686
@@ -797,7 +789,7 @@ handle_bob_client_message_multipart (void *cls,
797 struct BobServiceSession *s = cls; 789 struct BobServiceSession *s = cls;
798 uint32_t contained_count; 790 uint32_t contained_count;
799 const struct GNUNET_SCALARPRODUCT_Element *elements; 791 const struct GNUNET_SCALARPRODUCT_Element *elements;
800 struct GNUNET_SET_Element set_elem; 792 struct GNUNET_SETI_Element set_elem;
801 struct GNUNET_SCALARPRODUCT_Element *elem; 793 struct GNUNET_SCALARPRODUCT_Element *elem;
802 794
803 contained_count = ntohl (msg->element_count_contained); 795 contained_count = ntohl (msg->element_count_contained);
@@ -821,9 +813,9 @@ handle_bob_client_message_multipart (void *cls,
821 set_elem.data = &elem->key; 813 set_elem.data = &elem->key;
822 set_elem.size = sizeof(elem->key); 814 set_elem.size = sizeof(elem->key);
823 set_elem.element_type = 0; 815 set_elem.element_type = 0;
824 GNUNET_SET_add_element (s->intersection_set, 816 GNUNET_SETI_add_element (s->intersection_set,
825 &set_elem, 817 &set_elem,
826 NULL, NULL); 818 NULL, NULL);
827 } 819 }
828 s->client_received_element_count += contained_count; 820 s->client_received_element_count += contained_count;
829 GNUNET_SERVICE_client_continue (s->client); 821 GNUNET_SERVICE_client_continue (s->client);
@@ -913,7 +905,7 @@ handle_bob_client_message (void *cls,
913 uint32_t contained_count; 905 uint32_t contained_count;
914 uint32_t total_count; 906 uint32_t total_count;
915 const struct GNUNET_SCALARPRODUCT_Element *elements; 907 const struct GNUNET_SCALARPRODUCT_Element *elements;
916 struct GNUNET_SET_Element set_elem; 908 struct GNUNET_SETI_Element set_elem;
917 struct GNUNET_SCALARPRODUCT_Element *elem; 909 struct GNUNET_SCALARPRODUCT_Element *elem;
918 910
919 total_count = ntohl (msg->element_count_total); 911 total_count = ntohl (msg->element_count_total);
@@ -927,9 +919,7 @@ handle_bob_client_message (void *cls,
927 s->intersected_elements 919 s->intersected_elements
928 = GNUNET_CONTAINER_multihashmap_create (s->total, 920 = GNUNET_CONTAINER_multihashmap_create (s->total,
929 GNUNET_YES); 921 GNUNET_YES);
930 s->intersection_set 922 s->intersection_set = GNUNET_SETI_create (cfg);
931 = GNUNET_SET_create (cfg,
932 GNUNET_SET_OPERATION_INTERSECTION);
933 for (uint32_t i = 0; i < contained_count; i++) 923 for (uint32_t i = 0; i < contained_count; i++)
934 { 924 {
935 if (0 == GNUNET_ntohll (elements[i].value)) 925 if (0 == GNUNET_ntohll (elements[i].value))
@@ -951,9 +941,9 @@ handle_bob_client_message (void *cls,
951 set_elem.data = &elem->key; 941 set_elem.data = &elem->key;
952 set_elem.size = sizeof(elem->key); 942 set_elem.size = sizeof(elem->key);
953 set_elem.element_type = 0; 943 set_elem.element_type = 0;
954 GNUNET_SET_add_element (s->intersection_set, 944 GNUNET_SETI_add_element (s->intersection_set,
955 &set_elem, 945 &set_elem,
956 NULL, NULL); 946 NULL, NULL);
957 s->used_element_count++; 947 s->used_element_count++;
958 } 948 }
959 GNUNET_SERVICE_client_continue (s->client); 949 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 @@
32#include "gnunet_applications.h" 32#include "gnunet_applications.h"
33#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
34#include "gnunet_scalarproduct_service.h" 34#include "gnunet_scalarproduct_service.h"
35#include "gnunet_set_service.h" 35#include "gnunet_seti_service.h"
36#include "scalarproduct.h" 36#include "scalarproduct.h"
37#include "gnunet-service-scalarproduct.h" 37#include "gnunet-service-scalarproduct.h"
38 38
@@ -99,18 +99,18 @@ struct AliceServiceSession
99 * Set of elements for which will conduction an intersection. 99 * Set of elements for which will conduction an intersection.
100 * the resulting elements are then used for computing the scalar product. 100 * the resulting elements are then used for computing the scalar product.
101 */ 101 */
102 struct GNUNET_SET_Handle *intersection_set; 102 struct GNUNET_SETI_Handle *intersection_set;
103 103
104 /** 104 /**
105 * Set of elements for which will conduction an intersection. 105 * Set of elements for which will conduction an intersection.
106 * the resulting elements are then used for computing the scalar product. 106 * the resulting elements are then used for computing the scalar product.
107 */ 107 */
108 struct GNUNET_SET_OperationHandle *intersection_op; 108 struct GNUNET_SETI_OperationHandle *intersection_op;
109 109
110 /** 110 /**
111 * Handle to Alice's Intersection operation listening for Bob 111 * Handle to Alice's Intersection operation listening for Bob
112 */ 112 */
113 struct GNUNET_SET_ListenHandle *intersection_listen; 113 struct GNUNET_SETI_ListenHandle *intersection_listen;
114 114
115 /** 115 /**
116 * channel-handle associated with our cadet handle 116 * channel-handle associated with our cadet handle
@@ -265,17 +265,17 @@ destroy_service_session (struct AliceServiceSession *s)
265 } 265 }
266 if (NULL != s->intersection_listen) 266 if (NULL != s->intersection_listen)
267 { 267 {
268 GNUNET_SET_listen_cancel (s->intersection_listen); 268 GNUNET_SETI_listen_cancel (s->intersection_listen);
269 s->intersection_listen = NULL; 269 s->intersection_listen = NULL;
270 } 270 }
271 if (NULL != s->intersection_op) 271 if (NULL != s->intersection_op)
272 { 272 {
273 GNUNET_SET_operation_cancel (s->intersection_op); 273 GNUNET_SETI_operation_cancel (s->intersection_op);
274 s->intersection_op = NULL; 274 s->intersection_op = NULL;
275 } 275 }
276 if (NULL != s->intersection_set) 276 if (NULL != s->intersection_set)
277 { 277 {
278 GNUNET_SET_destroy (s->intersection_set); 278 GNUNET_SETI_destroy (s->intersection_set);
279 s->intersection_set = NULL; 279 s->intersection_set = NULL;
280 } 280 }
281 if (NULL != s->sorted_elements) 281 if (NULL != s->sorted_elements)
@@ -894,22 +894,22 @@ send_alices_cryptodata_message (struct AliceServiceSession *s)
894 * to indicate that the set intersection operation is done. 894 * to indicate that the set intersection operation is done.
895 * 895 *
896 * @param cls closure with the `struct AliceServiceSession` 896 * @param cls closure with the `struct AliceServiceSession`
897 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK 897 * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
898 * @param current_size current set size 898 * @param current_size current set size
899 * @param status what has happened with the set intersection? 899 * @param status what has happened with the set intersection?
900 */ 900 */
901static void 901static void
902cb_intersection_element_removed (void *cls, 902cb_intersection_element_removed (void *cls,
903 const struct GNUNET_SET_Element *element, 903 const struct GNUNET_SETI_Element *element,
904 uint64_t current_size, 904 uint64_t current_size,
905 enum GNUNET_SET_Status status) 905 enum GNUNET_SETI_Status status)
906{ 906{
907 struct AliceServiceSession *s = cls; 907 struct AliceServiceSession *s = cls;
908 struct GNUNET_SCALARPRODUCT_Element *se; 908 struct GNUNET_SCALARPRODUCT_Element *se;
909 909
910 switch (status) 910 switch (status)
911 { 911 {
912 case GNUNET_SET_STATUS_OK: 912 case GNUNET_SETI_STATUS_DEL_LOCAL:
913 /* this element has been removed from the set */ 913 /* this element has been removed from the set */
914 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements, 914 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
915 element->data); 915 element->data);
@@ -926,33 +926,27 @@ cb_intersection_element_removed (void *cls,
926 GNUNET_free (se); 926 GNUNET_free (se);
927 return; 927 return;
928 928
929 case GNUNET_SET_STATUS_DONE: 929 case GNUNET_SETI_STATUS_DONE:
930 s->intersection_op = NULL; 930 s->intersection_op = NULL;
931 if (NULL != s->intersection_set) 931 if (NULL != s->intersection_set)
932 { 932 {
933 GNUNET_SET_destroy (s->intersection_set); 933 GNUNET_SETI_destroy (s->intersection_set);
934 s->intersection_set = NULL; 934 s->intersection_set = NULL;
935 } 935 }
936 send_alices_cryptodata_message (s); 936 send_alices_cryptodata_message (s);
937 return; 937 return;
938 938 case GNUNET_SETI_STATUS_FAILURE:
939 case GNUNET_SET_STATUS_HALF_DONE:
940 /* unexpected for intersection */
941 GNUNET_break (0);
942 return;
943
944 case GNUNET_SET_STATUS_FAILURE:
945 /* unhandled status code */ 939 /* unhandled status code */
946 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n"); 940 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
947 if (NULL != s->intersection_listen) 941 if (NULL != s->intersection_listen)
948 { 942 {
949 GNUNET_SET_listen_cancel (s->intersection_listen); 943 GNUNET_SETI_listen_cancel (s->intersection_listen);
950 s->intersection_listen = NULL; 944 s->intersection_listen = NULL;
951 } 945 }
952 s->intersection_op = NULL; 946 s->intersection_op = NULL;
953 if (NULL != s->intersection_set) 947 if (NULL != s->intersection_set)
954 { 948 {
955 GNUNET_SET_destroy (s->intersection_set); 949 GNUNET_SETI_destroy (s->intersection_set);
956 s->intersection_set = NULL; 950 s->intersection_set = NULL;
957 } 951 }
958 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 952 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -974,7 +968,7 @@ cb_intersection_element_removed (void *cls,
974 * @param other_peer the other peer 968 * @param other_peer the other peer
975 * @param context_msg message with application specific information from 969 * @param context_msg message with application specific information from
976 * the other peer 970 * the other peer
977 * @param request request from the other peer (never NULL), use GNUNET_SET_accept() 971 * @param request request from the other peer (never NULL), use GNUNET_SETI_accept()
978 * to accept it, otherwise the request will be refused 972 * to accept it, otherwise the request will be refused
979 * Note that we can't just return value from the listen callback, 973 * Note that we can't just return value from the listen callback,
980 * as it is also necessary to specify the set we want to do the 974 * as it is also necessary to specify the set we want to do the
@@ -985,7 +979,7 @@ static void
985cb_intersection_request_alice (void *cls, 979cb_intersection_request_alice (void *cls,
986 const struct GNUNET_PeerIdentity *other_peer, 980 const struct GNUNET_PeerIdentity *other_peer,
987 const struct GNUNET_MessageHeader *context_msg, 981 const struct GNUNET_MessageHeader *context_msg,
988 struct GNUNET_SET_Request *request) 982 struct GNUNET_SETI_Request *request)
989{ 983{
990 struct AliceServiceSession *s = cls; 984 struct AliceServiceSession *s = cls;
991 985
@@ -994,11 +988,11 @@ cb_intersection_request_alice (void *cls,
994 GNUNET_break_op (0); 988 GNUNET_break_op (0);
995 return; 989 return;
996 } 990 }
997 s->intersection_op = GNUNET_SET_accept (request, 991 s->intersection_op = GNUNET_SETI_accept (request,
998 GNUNET_SET_RESULT_REMOVED, 992 (struct
999 (struct GNUNET_SET_Option[]){ { 0 } }, 993 GNUNET_SETI_Option[]){ { 0 } },
1000 &cb_intersection_element_removed, 994 &cb_intersection_element_removed,
1001 s); 995 s);
1002 if (NULL == s->intersection_op) 996 if (NULL == s->intersection_op)
1003 { 997 {
1004 GNUNET_break (0); 998 GNUNET_break (0);
@@ -1006,7 +1000,7 @@ cb_intersection_request_alice (void *cls,
1006 prepare_client_end_notification (s); 1000 prepare_client_end_notification (s);
1007 return; 1001 return;
1008 } 1002 }
1009 if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set)) 1003 if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
1010 { 1004 {
1011 GNUNET_break (0); 1005 GNUNET_break (0);
1012 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 1006 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -1055,11 +1049,10 @@ client_request_complete_alice (struct AliceServiceSession *s)
1055 return; 1049 return;
1056 } 1050 }
1057 s->cadet_mq = GNUNET_CADET_get_mq (s->channel); 1051 s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
1058 s->intersection_listen = GNUNET_SET_listen (cfg, 1052 s->intersection_listen = GNUNET_SETI_listen (cfg,
1059 GNUNET_SET_OPERATION_INTERSECTION, 1053 &s->session_id,
1060 &s->session_id, 1054 &cb_intersection_request_alice,
1061 &cb_intersection_request_alice, 1055 s);
1062 s);
1063 if (NULL == s->intersection_listen) 1056 if (NULL == s->intersection_listen)
1064 { 1057 {
1065 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 1058 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -1125,7 +1118,7 @@ handle_alice_client_message_multipart (
1125 struct AliceServiceSession *s = cls; 1118 struct AliceServiceSession *s = cls;
1126 uint32_t contained_count; 1119 uint32_t contained_count;
1127 const struct GNUNET_SCALARPRODUCT_Element *elements; 1120 const struct GNUNET_SCALARPRODUCT_Element *elements;
1128 struct GNUNET_SET_Element set_elem; 1121 struct GNUNET_SETI_Element set_elem;
1129 struct GNUNET_SCALARPRODUCT_Element *elem; 1122 struct GNUNET_SCALARPRODUCT_Element *elem;
1130 1123
1131 contained_count = ntohl (msg->element_count_contained); 1124 contained_count = ntohl (msg->element_count_contained);
@@ -1150,7 +1143,7 @@ handle_alice_client_message_multipart (
1150 set_elem.data = &elem->key; 1143 set_elem.data = &elem->key;
1151 set_elem.size = sizeof(elem->key); 1144 set_elem.size = sizeof(elem->key);
1152 set_elem.element_type = 0; 1145 set_elem.element_type = 0;
1153 GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL); 1146 GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
1154 s->used_element_count++; 1147 s->used_element_count++;
1155 } 1148 }
1156 GNUNET_SERVICE_client_continue (s->client); 1149 GNUNET_SERVICE_client_continue (s->client);
@@ -1217,7 +1210,7 @@ handle_alice_client_message (void *cls,
1217 uint32_t contained_count; 1210 uint32_t contained_count;
1218 uint32_t total_count; 1211 uint32_t total_count;
1219 const struct GNUNET_SCALARPRODUCT_Element *elements; 1212 const struct GNUNET_SCALARPRODUCT_Element *elements;
1220 struct GNUNET_SET_Element set_elem; 1213 struct GNUNET_SETI_Element set_elem;
1221 struct GNUNET_SCALARPRODUCT_Element *elem; 1214 struct GNUNET_SCALARPRODUCT_Element *elem;
1222 1215
1223 total_count = ntohl (msg->element_count_total); 1216 total_count = ntohl (msg->element_count_total);
@@ -1230,8 +1223,7 @@ handle_alice_client_message (void *cls,
1230 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1]; 1223 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1231 s->intersected_elements = 1224 s->intersected_elements =
1232 GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES); 1225 GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES);
1233 s->intersection_set = 1226 s->intersection_set = GNUNET_SETI_create (cfg);
1234 GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
1235 1227
1236 for (uint32_t i = 0; i < contained_count; i++) 1228 for (uint32_t i = 0; i < contained_count; i++)
1237 { 1229 {
@@ -1255,7 +1247,10 @@ handle_alice_client_message (void *cls,
1255 set_elem.data = &elem->key; 1247 set_elem.data = &elem->key;
1256 set_elem.size = sizeof(elem->key); 1248 set_elem.size = sizeof(elem->key);
1257 set_elem.element_type = 0; 1249 set_elem.element_type = 0;
1258 GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL); 1250 GNUNET_SETI_add_element (s->intersection_set,
1251 &set_elem,
1252 NULL,
1253 NULL);
1259 s->used_element_count++; 1254 s->used_element_count++;
1260 } 1255 }
1261 GNUNET_SERVICE_client_continue (s->client); 1256 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 @@
32#include "gnunet_applications.h" 32#include "gnunet_applications.h"
33#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
34#include "gnunet_scalarproduct_service.h" 34#include "gnunet_scalarproduct_service.h"
35#include "gnunet_set_service.h" 35#include "gnunet_seti_service.h"
36#include "scalarproduct.h" 36#include "scalarproduct.h"
37#include "gnunet-service-scalarproduct.h" 37#include "gnunet-service-scalarproduct.h"
38 38
@@ -88,13 +88,13 @@ struct BobServiceSession
88 * Set of elements for which we will be conducting an intersection. 88 * Set of elements for which we will be conducting an intersection.
89 * The resulting elements are then used for computing the scalar product. 89 * The resulting elements are then used for computing the scalar product.
90 */ 90 */
91 struct GNUNET_SET_Handle *intersection_set; 91 struct GNUNET_SETI_Handle *intersection_set;
92 92
93 /** 93 /**
94 * Set of elements for which will conduction an intersection. 94 * Set of elements for which will conduction an intersection.
95 * the resulting elements are then used for computing the scalar product. 95 * the resulting elements are then used for computing the scalar product.
96 */ 96 */
97 struct GNUNET_SET_OperationHandle *intersection_op; 97 struct GNUNET_SETI_OperationHandle *intersection_op;
98 98
99 /** 99 /**
100 * CADET port we are listening on. 100 * CADET port we are listening on.
@@ -277,12 +277,12 @@ destroy_service_session (struct BobServiceSession *s)
277 } 277 }
278 if (NULL != s->intersection_op) 278 if (NULL != s->intersection_op)
279 { 279 {
280 GNUNET_SET_operation_cancel (s->intersection_op); 280 GNUNET_SETI_operation_cancel (s->intersection_op);
281 s->intersection_op = NULL; 281 s->intersection_op = NULL;
282 } 282 }
283 if (NULL != s->intersection_set) 283 if (NULL != s->intersection_set)
284 { 284 {
285 GNUNET_SET_destroy (s->intersection_set); 285 GNUNET_SETI_destroy (s->intersection_set);
286 s->intersection_set = NULL; 286 s->intersection_set = NULL;
287 } 287 }
288 if (NULL != s->e_a) 288 if (NULL != s->e_a)
@@ -888,22 +888,22 @@ handle_alices_cryptodata_message (void *cls,
888 * that needs to be removed from the result set. 888 * that needs to be removed from the result set.
889 * 889 *
890 * @param cls closure with the `struct BobServiceSession` 890 * @param cls closure with the `struct BobServiceSession`
891 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK 891 * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
892 * @param current_size current set size 892 * @param current_size current set size
893 * @param status what has happened with the set intersection? 893 * @param status what has happened with the set intersection?
894 */ 894 */
895static void 895static void
896cb_intersection_element_removed (void *cls, 896cb_intersection_element_removed (void *cls,
897 const struct GNUNET_SET_Element *element, 897 const struct GNUNET_SETI_Element *element,
898 uint64_t current_size, 898 uint64_t current_size,
899 enum GNUNET_SET_Status status) 899 enum GNUNET_SETI_Status status)
900{ 900{
901 struct BobServiceSession *s = cls; 901 struct BobServiceSession *s = cls;
902 struct GNUNET_SCALARPRODUCT_Element *se; 902 struct GNUNET_SCALARPRODUCT_Element *se;
903 903
904 switch (status) 904 switch (status)
905 { 905 {
906 case GNUNET_SET_STATUS_OK: 906 case GNUNET_SETI_STATUS_DEL_LOCAL:
907 /* this element has been removed from the set */ 907 /* this element has been removed from the set */
908 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements, 908 se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
909 element->data); 909 element->data);
@@ -919,8 +919,7 @@ cb_intersection_element_removed (void *cls,
919 se)); 919 se));
920 GNUNET_free (se); 920 GNUNET_free (se);
921 return; 921 return;
922 922 case GNUNET_SETI_STATUS_DONE:
923 case GNUNET_SET_STATUS_DONE:
924 s->intersection_op = NULL; 923 s->intersection_op = NULL;
925 GNUNET_break (NULL == s->intersection_set); 924 GNUNET_break (NULL == s->intersection_set);
926 GNUNET_CADET_receive_done (s->channel); 925 GNUNET_CADET_receive_done (s->channel);
@@ -935,26 +934,19 @@ cb_intersection_element_removed (void *cls,
935 transmit_cryptographic_reply (s); 934 transmit_cryptographic_reply (s);
936 } 935 }
937 return; 936 return;
938 937 case GNUNET_SETI_STATUS_FAILURE:
939 case GNUNET_SET_STATUS_HALF_DONE:
940 /* unexpected for intersection */
941 GNUNET_break (0);
942 return;
943
944 case GNUNET_SET_STATUS_FAILURE:
945 /* unhandled status code */ 938 /* unhandled status code */
946 LOG (GNUNET_ERROR_TYPE_DEBUG, 939 LOG (GNUNET_ERROR_TYPE_DEBUG,
947 "Set intersection failed!\n"); 940 "Set intersection failed!\n");
948 s->intersection_op = NULL; 941 s->intersection_op = NULL;
949 if (NULL != s->intersection_set) 942 if (NULL != s->intersection_set)
950 { 943 {
951 GNUNET_SET_destroy (s->intersection_set); 944 GNUNET_SETI_destroy (s->intersection_set);
952 s->intersection_set = NULL; 945 s->intersection_set = NULL;
953 } 946 }
954 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 947 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
955 prepare_client_end_notification (s); 948 prepare_client_end_notification (s);
956 return; 949 return;
957
958 default: 950 default:
959 GNUNET_break (0); 951 GNUNET_break (0);
960 return; 952 return;
@@ -977,23 +969,22 @@ start_intersection (struct BobServiceSession *s)
977 (unsigned int) s->total); 969 (unsigned int) s->total);
978 970
979 s->intersection_op 971 s->intersection_op
980 = GNUNET_SET_prepare (&s->peer, 972 = GNUNET_SETI_prepare (&s->peer,
981 &s->session_id, 973 &s->session_id,
982 NULL, 974 NULL,
983 GNUNET_SET_RESULT_REMOVED, 975 (struct GNUNET_SETI_Option[]) { { 0 } },
984 (struct GNUNET_SET_Option[]) { { 0 } }, 976 &cb_intersection_element_removed,
985 &cb_intersection_element_removed, 977 s);
986 s);
987 if (GNUNET_OK != 978 if (GNUNET_OK !=
988 GNUNET_SET_commit (s->intersection_op, 979 GNUNET_SETI_commit (s->intersection_op,
989 s->intersection_set)) 980 s->intersection_set))
990 { 981 {
991 GNUNET_break (0); 982 GNUNET_break (0);
992 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; 983 s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
993 prepare_client_end_notification (s); 984 prepare_client_end_notification (s);
994 return; 985 return;
995 } 986 }
996 GNUNET_SET_destroy (s->intersection_set); 987 GNUNET_SETI_destroy (s->intersection_set);
997 s->intersection_set = NULL; 988 s->intersection_set = NULL;
998} 989}
999 990
@@ -1096,7 +1087,7 @@ handle_bob_client_message_multipart (void *cls,
1096 struct BobServiceSession *s = cls; 1087 struct BobServiceSession *s = cls;
1097 uint32_t contained_count; 1088 uint32_t contained_count;
1098 const struct GNUNET_SCALARPRODUCT_Element *elements; 1089 const struct GNUNET_SCALARPRODUCT_Element *elements;
1099 struct GNUNET_SET_Element set_elem; 1090 struct GNUNET_SETI_Element set_elem;
1100 struct GNUNET_SCALARPRODUCT_Element *elem; 1091 struct GNUNET_SCALARPRODUCT_Element *elem;
1101 1092
1102 contained_count = ntohl (msg->element_count_contained); 1093 contained_count = ntohl (msg->element_count_contained);
@@ -1120,9 +1111,9 @@ handle_bob_client_message_multipart (void *cls,
1120 set_elem.data = &elem->key; 1111 set_elem.data = &elem->key;
1121 set_elem.size = sizeof(elem->key); 1112 set_elem.size = sizeof(elem->key);
1122 set_elem.element_type = 0; 1113 set_elem.element_type = 0;
1123 GNUNET_SET_add_element (s->intersection_set, 1114 GNUNET_SETI_add_element (s->intersection_set,
1124 &set_elem, 1115 &set_elem,
1125 NULL, NULL); 1116 NULL, NULL);
1126 } 1117 }
1127 s->client_received_element_count += contained_count; 1118 s->client_received_element_count += contained_count;
1128 GNUNET_SERVICE_client_continue (s->client); 1119 GNUNET_SERVICE_client_continue (s->client);
@@ -1206,7 +1197,7 @@ handle_bob_client_message (void *cls,
1206 uint32_t contained_count; 1197 uint32_t contained_count;
1207 uint32_t total_count; 1198 uint32_t total_count;
1208 const struct GNUNET_SCALARPRODUCT_Element *elements; 1199 const struct GNUNET_SCALARPRODUCT_Element *elements;
1209 struct GNUNET_SET_Element set_elem; 1200 struct GNUNET_SETI_Element set_elem;
1210 struct GNUNET_SCALARPRODUCT_Element *elem; 1201 struct GNUNET_SCALARPRODUCT_Element *elem;
1211 1202
1212 total_count = ntohl (msg->element_count_total); 1203 total_count = ntohl (msg->element_count_total);
@@ -1220,9 +1211,7 @@ handle_bob_client_message (void *cls,
1220 s->intersected_elements 1211 s->intersected_elements
1221 = GNUNET_CONTAINER_multihashmap_create (s->total, 1212 = GNUNET_CONTAINER_multihashmap_create (s->total,
1222 GNUNET_YES); 1213 GNUNET_YES);
1223 s->intersection_set 1214 s->intersection_set = GNUNET_SETI_create (cfg);
1224 = GNUNET_SET_create (cfg,
1225 GNUNET_SET_OPERATION_INTERSECTION);
1226 for (uint32_t i = 0; i < contained_count; i++) 1215 for (uint32_t i = 0; i < contained_count; i++)
1227 { 1216 {
1228 if (0 == GNUNET_ntohll (elements[i].value)) 1217 if (0 == GNUNET_ntohll (elements[i].value))
@@ -1244,9 +1233,9 @@ handle_bob_client_message (void *cls,
1244 set_elem.data = &elem->key; 1233 set_elem.data = &elem->key;
1245 set_elem.size = sizeof(elem->key); 1234 set_elem.size = sizeof(elem->key);
1246 set_elem.element_type = 0; 1235 set_elem.element_type = 0;
1247 GNUNET_SET_add_element (s->intersection_set, 1236 GNUNET_SETI_add_element (s->intersection_set,
1248 &set_elem, 1237 &set_elem,
1249 NULL, NULL); 1238 NULL, NULL);
1250 s->used_element_count++; 1239 s->used_element_count++;
1251 } 1240 }
1252 GNUNET_SERVICE_client_continue (s->client); 1241 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 @@
1gnunet-seti-profiler
2gnunet-service-seti
3test_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 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4pkgcfgdir= $(pkgdatadir)/config.d/
5
6libexecdir= $(pkglibdir)/libexec/
7
8plugindir = $(libdir)/gnunet
9
10pkgcfg_DATA = \
11 seti.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
15endif
16
17if HAVE_TESTING
18bin_PROGRAMS = \
19 gnunet-seti-profiler
20endif
21
22libexec_PROGRAMS = \
23 gnunet-service-seti
24
25lib_LTLIBRARIES = \
26 libgnunetseti.la
27
28gnunet_seti_profiler_SOURCES = \
29 gnunet-seti-profiler.c
30gnunet_seti_profiler_LDADD = \
31 $(top_builddir)/src/util/libgnunetutil.la \
32 $(top_builddir)/src/statistics/libgnunetstatistics.la \
33 libgnunetseti.la \
34 $(top_builddir)/src/testing/libgnunettesting.la \
35 $(GN_LIBINTL)
36
37
38gnunet_service_seti_SOURCES = \
39 gnunet-service-seti.c \
40 gnunet-service-set_protocol.h
41gnunet_service_seti_LDADD = \
42 $(top_builddir)/src/util/libgnunetutil.la \
43 $(top_builddir)/src/statistics/libgnunetstatistics.la \
44 $(top_builddir)/src/core/libgnunetcore.la \
45 $(top_builddir)/src/cadet/libgnunetcadet.la \
46 $(top_builddir)/src/block/libgnunetblock.la \
47 libgnunetseti.la \
48 $(GN_LIBINTL)
49
50libgnunetseti_la_SOURCES = \
51 seti_api.c seti.h
52libgnunetseti_la_LIBADD = \
53 $(top_builddir)/src/util/libgnunetutil.la \
54 $(LTLIBINTL)
55libgnunetseti_la_LDFLAGS = \
56 $(GN_LIB_LDFLAGS)
57
58if HAVE_TESTING
59check_PROGRAMS = \
60 test_seti_api
61endif
62
63if ENABLE_TEST_RUN
64AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
65TESTS = $(check_PROGRAMS)
66endif
67
68test_seti_api_SOURCES = \
69 test_seti_api.c
70test_seti_api_LDADD = \
71 $(top_builddir)/src/util/libgnunetutil.la \
72 $(top_builddir)/src/testing/libgnunettesting.la \
73 libgnunetseti.la
74
75plugin_LTLIBRARIES = \
76 libgnunet_plugin_block_seti_test.la
77
78libgnunet_plugin_block_seti_test_la_SOURCES = \
79 plugin_block_seti_test.c
80libgnunet_plugin_block_seti_test_la_LIBADD = \
81 $(top_builddir)/src/block/libgnunetblock.la \
82 $(top_builddir)/src/block/libgnunetblockgroup.la \
83 $(top_builddir)/src/util/libgnunetutil.la \
84 $(LTLIBINTL)
85libgnunet_plugin_block_seti_test_la_LDFLAGS = \
86 $(GN_PLUGIN_LDFLAGS)
87
88
89EXTRA_DIST = \
90 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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013-2017, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file set/gnunet-service-seti.c
22 * @brief two-peer set intersection operations
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#include "gnunet-service-seti_protocol.h"
27#include "gnunet_statistics_service.h"
28#include "gnunet_cadet_service.h"
29#include "gnunet_seti_service.h"
30#include "gnunet_block_lib.h"
31#include "seti.h"
32
33/**
34 * How long do we hold on to an incoming channel if there is
35 * no local listener before giving up?
36 */
37#define INCOMING_CHANNEL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
38
39
40/**
41 * Current phase we are in for a intersection operation.
42 */
43enum IntersectionOperationPhase
44{
45 /**
46 * We are just starting.
47 */
48 PHASE_INITIAL,
49
50 /**
51 * We have send the number of our elements to the other
52 * peer, but did not setup our element set yet.
53 */
54 PHASE_COUNT_SENT,
55
56 /**
57 * We have initialized our set and are now reducing it by exchanging
58 * Bloom filters until one party notices the their element hashes
59 * are equal.
60 */
61 PHASE_BF_EXCHANGE,
62
63 /**
64 * We must next send the P2P DONE message (after finishing mostly
65 * with the local client). Then we will wait for the channel to close.
66 */
67 PHASE_MUST_SEND_DONE,
68
69 /**
70 * We have received the P2P DONE message, and must finish with the
71 * local client before terminating the channel.
72 */
73 PHASE_DONE_RECEIVED,
74
75 /**
76 * The protocol is over. Results may still have to be sent to the
77 * client.
78 */
79 PHASE_FINISHED
80};
81
82
83/**
84 * A set that supports a specific operation with other peers.
85 */
86struct Set;
87
88/**
89 * Information about an element element in the set. All elements are
90 * stored in a hash-table from their hash-code to their 'struct
91 * Element', so that the remove and add operations are reasonably
92 * fast.
93 */
94struct ElementEntry;
95
96/**
97 * Operation context used to execute a set operation.
98 */
99struct Operation;
100
101
102/**
103 * Information about an element element in the set. All elements are
104 * stored in a hash-table from their hash-code to their `struct
105 * Element`, so that the remove and add operations are reasonably
106 * fast.
107 */
108struct ElementEntry
109{
110 /**
111 * The actual element. The data for the element
112 * should be allocated at the end of this struct.
113 */
114 struct GNUNET_SETI_Element element;
115
116 /**
117 * Hash of the element. For set union: Will be used to derive the
118 * different IBF keys for different salts.
119 */
120 struct GNUNET_HashCode element_hash;
121
122 /**
123 * Generation in which the element was added.
124 */
125 unsigned int generation_added;
126
127 /**
128 * #GNUNET_YES if the element is a remote element, and does not belong
129 * to the operation's set.
130 */
131 int remote;
132};
133
134
135/**
136 * A listener is inhabited by a client, and waits for evaluation
137 * requests from remote peers.
138 */
139struct Listener;
140
141
142/**
143 * State we keep per client.
144 */
145struct ClientState
146{
147 /**
148 * Set, if associated with the client, otherwise NULL.
149 */
150 struct Set *set;
151
152 /**
153 * Listener, if associated with the client, otherwise NULL.
154 */
155 struct Listener *listener;
156
157 /**
158 * Client handle.
159 */
160 struct GNUNET_SERVICE_Client *client;
161
162 /**
163 * Message queue.
164 */
165 struct GNUNET_MQ_Handle *mq;
166};
167
168
169/**
170 * Operation context used to execute a set operation.
171 */
172struct Operation
173{
174 /**
175 * The identity of the requesting peer. Needs to
176 * be stored here as the op spec might not have been created yet.
177 */
178 struct GNUNET_PeerIdentity peer;
179
180 /**
181 * XOR of the keys of all of the elements (remaining) in my set.
182 * Always updated when elements are added or removed to
183 * @e my_elements.
184 */
185 struct GNUNET_HashCode my_xor;
186
187 /**
188 * XOR of the keys of all of the elements (remaining) in
189 * the other peer's set. Updated when we receive the
190 * other peer's Bloom filter.
191 */
192 struct GNUNET_HashCode other_xor;
193
194 /**
195 * Kept in a DLL of the listener, if @e listener is non-NULL.
196 */
197 struct Operation *next;
198
199 /**
200 * Kept in a DLL of the listener, if @e listener is non-NULL.
201 */
202 struct Operation *prev;
203
204 /**
205 * Channel to the peer.
206 */
207 struct GNUNET_CADET_Channel *channel;
208
209 /**
210 * Port this operation runs on.
211 */
212 struct Listener *listener;
213
214 /**
215 * Message queue for the channel.
216 */
217 struct GNUNET_MQ_Handle *mq;
218
219 /**
220 * Context message, may be NULL.
221 */
222 struct GNUNET_MessageHeader *context_msg;
223
224 /**
225 * Set associated with the operation, NULL until the spec has been
226 * associated with a set.
227 */
228 struct Set *set;
229
230 /**
231 * The bf we currently receive
232 */
233 struct GNUNET_CONTAINER_BloomFilter *remote_bf;
234
235 /**
236 * BF of the set's element.
237 */
238 struct GNUNET_CONTAINER_BloomFilter *local_bf;
239
240 /**
241 * Remaining elements in the intersection operation.
242 * Maps element-id-hashes to 'elements in our set'.
243 */
244 struct GNUNET_CONTAINER_MultiHashMap *my_elements;
245
246 /**
247 * Iterator for sending the final set of @e my_elements to the client.
248 */
249 struct GNUNET_CONTAINER_MultiHashMapIterator *full_result_iter;
250
251 /**
252 * For multipart BF transmissions, we have to store the
253 * bloomfilter-data until we fully received it.
254 */
255 char *bf_data;
256
257 /**
258 * Timeout task, if the incoming peer has not been accepted
259 * after the timeout, it will be disconnected.
260 */
261 struct GNUNET_SCHEDULER_Task *timeout_task;
262
263 /**
264 * How many bytes of @e bf_data are valid?
265 */
266 uint32_t bf_data_offset;
267
268 /**
269 * Current element count contained within @e my_elements.
270 * (May differ briefly during initialization.)
271 */
272 uint32_t my_element_count;
273
274 /**
275 * size of the bloomfilter in @e bf_data.
276 */
277 uint32_t bf_data_size;
278
279 /**
280 * size of the bloomfilter
281 */
282 uint32_t bf_bits_per_element;
283
284 /**
285 * Salt currently used for BF construction (by us or the other peer,
286 * depending on where we are in the code).
287 */
288 uint32_t salt;
289
290 /**
291 * Current state of the operation.
292 */
293 enum IntersectionOperationPhase phase;
294
295 /**
296 * Generation in which the operation handle was created.
297 */
298 unsigned int generation_created;
299
300 /**
301 * Did we send the client that we are done?
302 */
303 int client_done_sent;
304
305 /**
306 * Set whenever we reach the state where the death of the
307 * channel is perfectly find and should NOT result in the
308 * operation being cancelled.
309 */
310 int channel_death_expected;
311
312 /**
313 * Remote peers element count
314 */
315 uint32_t remote_element_count;
316
317 /**
318 * ID used to identify an operation between service and client
319 */
320 uint32_t client_request_id;
321
322 /**
323 * When are elements sent to the client, and which elements are sent?
324 */
325 int return_intersection;
326
327 /**
328 * Unique request id for the request from a remote peer, sent to the
329 * client, which will accept or reject the request. Set to '0' iff
330 * the request has not been suggested yet.
331 */
332 uint32_t suggest_id;
333
334};
335
336
337/**
338 * SetContent stores the actual set elements, which may be shared by
339 * multiple generations derived from one set.
340 */
341struct SetContent
342{
343 /**
344 * Maps `struct GNUNET_HashCode *` to `struct ElementEntry *`.
345 */
346 struct GNUNET_CONTAINER_MultiHashMap *elements;
347
348 /**
349 * Number of references to the content.
350 */
351 unsigned int refcount;
352
353 /**
354 * FIXME: document!
355 */
356 unsigned int latest_generation;
357
358 /**
359 * Number of concurrently active iterators.
360 */
361 int iterator_count;
362};
363
364
365/**
366 * A set that supports a specific operation with other peers.
367 */
368struct Set
369{
370 /**
371 * Sets are held in a doubly linked list (in `sets_head` and `sets_tail`).
372 */
373 struct Set *next;
374
375 /**
376 * Sets are held in a doubly linked list.
377 */
378 struct Set *prev;
379
380 /**
381 * Client that owns the set. Only one client may own a set,
382 * and there can only be one set per client.
383 */
384 struct ClientState *cs;
385
386 /**
387 * Content, possibly shared by multiple sets,
388 * and thus reference counted.
389 */
390 struct SetContent *content;
391
392 /**
393 * Number of currently valid elements in the set which have not been
394 * removed.
395 */
396 uint32_t current_set_element_count;
397
398 /**
399 * Evaluate operations are held in a linked list.
400 */
401 struct Operation *ops_head;
402
403 /**
404 * Evaluate operations are held in a linked list.
405 */
406 struct Operation *ops_tail;
407
408 /**
409 * Current generation, that is, number of previously executed
410 * operations and lazy copies on the underlying set content.
411 */
412 unsigned int current_generation;
413
414};
415
416
417/**
418 * A listener is inhabited by a client, and waits for evaluation
419 * requests from remote peers.
420 */
421struct Listener
422{
423 /**
424 * Listeners are held in a doubly linked list.
425 */
426 struct Listener *next;
427
428 /**
429 * Listeners are held in a doubly linked list.
430 */
431 struct Listener *prev;
432
433 /**
434 * Head of DLL of operations this listener is responsible for.
435 * Once the client has accepted/declined the operation, the
436 * operation is moved to the respective set's operation DLLS.
437 */
438 struct Operation *op_head;
439
440 /**
441 * Tail of DLL of operations this listener is responsible for.
442 * Once the client has accepted/declined the operation, the
443 * operation is moved to the respective set's operation DLLS.
444 */
445 struct Operation *op_tail;
446
447 /**
448 * Client that owns the listener.
449 * Only one client may own a listener.
450 */
451 struct ClientState *cs;
452
453 /**
454 * The port we are listening on with CADET.
455 */
456 struct GNUNET_CADET_Port *open_port;
457
458 /**
459 * Application ID for the operation, used to distinguish
460 * multiple operations of the same type with the same peer.
461 */
462 struct GNUNET_HashCode app_id;
463
464};
465
466
467/**
468 * Handle to the cadet service, used to listen for and connect to
469 * remote peers.
470 */
471static struct GNUNET_CADET_Handle *cadet;
472
473/**
474 * Statistics handle.
475 */
476static struct GNUNET_STATISTICS_Handle *_GSS_statistics;
477
478/**
479 * Listeners are held in a doubly linked list.
480 */
481static struct Listener *listener_head;
482
483/**
484 * Listeners are held in a doubly linked list.
485 */
486static struct Listener *listener_tail;
487
488/**
489 * Number of active clients.
490 */
491static unsigned int num_clients;
492
493/**
494 * Are we in shutdown? if #GNUNET_YES and the number of clients
495 * drops to zero, disconnect from CADET.
496 */
497static int in_shutdown;
498
499/**
500 * Counter for allocating unique IDs for clients, used to identify
501 * incoming operation requests from remote peers, that the client can
502 * choose to accept or refuse. 0 must not be used (reserved for
503 * uninitialized).
504 */
505static uint32_t suggest_id;
506
507
508/**
509 * If applicable in the current operation mode, send a result message
510 * to the client indicating we removed an element.
511 *
512 * @param op intersection operation
513 * @param element element to send
514 */
515static void
516send_client_removed_element (struct Operation *op,
517 struct GNUNET_SETI_Element *element)
518{
519 struct GNUNET_MQ_Envelope *ev;
520 struct GNUNET_SETI_ResultMessage *rm;
521
522 if (GNUNET_YES == op->return_intersection)
523 {
524 GNUNET_break (0);
525 return; /* Wrong mode for transmitting removed elements */
526 }
527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528 "Sending removed element (size %u) to client\n",
529 element->size);
530 GNUNET_STATISTICS_update (_GSS_statistics,
531 "# Element removed messages sent",
532 1,
533 GNUNET_NO);
534 GNUNET_assert (0 != op->client_request_id);
535 ev = GNUNET_MQ_msg_extra (rm,
536 element->size,
537 GNUNET_MESSAGE_TYPE_SETI_RESULT);
538 if (NULL == ev)
539 {
540 GNUNET_break (0);
541 return;
542 }
543 rm->result_status = htons (GNUNET_SETI_STATUS_DEL_LOCAL);
544 rm->request_id = htonl (op->client_request_id);
545 rm->element_type = element->element_type;
546 GNUNET_memcpy (&rm[1],
547 element->data,
548 element->size);
549 GNUNET_MQ_send (op->set->cs->mq,
550 ev);
551}
552
553
554/**
555 * Is element @a ee part of the set used by @a op?
556 *
557 * @param ee element to test
558 * @param op operation the defines the set and its generation
559 * @return #GNUNET_YES if the element is in the set, #GNUNET_NO if not
560 */
561static int
562_GSS_is_element_of_operation (struct ElementEntry *ee,
563 struct Operation *op)
564{
565 return op->generation_created >= ee->generation_added;
566}
567
568
569/**
570 * Fills the "my_elements" hashmap with all relevant elements.
571 *
572 * @param cls the `struct Operation *` we are performing
573 * @param key current key code
574 * @param value the `struct ElementEntry *` from the hash map
575 * @return #GNUNET_YES (we should continue to iterate)
576 */
577static int
578filtered_map_initialization (void *cls,
579 const struct GNUNET_HashCode *key,
580 void *value)
581{
582 struct Operation *op = cls;
583 struct ElementEntry *ee = value;
584 struct GNUNET_HashCode mutated_hash;
585
586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
587 "FIMA called for %s:%u\n",
588 GNUNET_h2s (&ee->element_hash),
589 ee->element.size);
590
591 if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
592 {
593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594 "Reduced initialization, not starting with %s:%u (wrong generation)\n",
595 GNUNET_h2s (&ee->element_hash),
596 ee->element.size);
597 return GNUNET_YES; /* element not valid in our operation's generation */
598 }
599
600 /* Test if element is in other peer's bloomfilter */
601 GNUNET_BLOCK_mingle_hash (&ee->element_hash,
602 op->salt,
603 &mutated_hash);
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
605 "Testing mingled hash %s with salt %u\n",
606 GNUNET_h2s (&mutated_hash),
607 op->salt);
608 if (GNUNET_NO ==
609 GNUNET_CONTAINER_bloomfilter_test (op->remote_bf,
610 &mutated_hash))
611 {
612 /* remove this element */
613 send_client_removed_element (op,
614 &ee->element);
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "Reduced initialization, not starting with %s:%u\n",
617 GNUNET_h2s (&ee->element_hash),
618 ee->element.size);
619 return GNUNET_YES;
620 }
621 op->my_element_count++;
622 GNUNET_CRYPTO_hash_xor (&op->my_xor,
623 &ee->element_hash,
624 &op->my_xor);
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
626 "Filtered initialization of my_elements, adding %s:%u\n",
627 GNUNET_h2s (&ee->element_hash),
628 ee->element.size);
629 GNUNET_break (GNUNET_YES ==
630 GNUNET_CONTAINER_multihashmap_put (op->my_elements,
631 &ee->element_hash,
632 ee,
633 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
634
635 return GNUNET_YES;
636}
637
638
639/**
640 * Removes elements from our hashmap if they are not contained within the
641 * provided remote bloomfilter.
642 *
643 * @param cls closure with the `struct Operation *`
644 * @param key current key code
645 * @param value value in the hash map
646 * @return #GNUNET_YES (we should continue to iterate)
647 */
648static int
649iterator_bf_reduce (void *cls,
650 const struct GNUNET_HashCode *key,
651 void *value)
652{
653 struct Operation *op = cls;
654 struct ElementEntry *ee = value;
655 struct GNUNET_HashCode mutated_hash;
656
657 GNUNET_BLOCK_mingle_hash (&ee->element_hash,
658 op->salt,
659 &mutated_hash);
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 "Testing mingled hash %s with salt %u\n",
662 GNUNET_h2s (&mutated_hash),
663 op->salt);
664 if (GNUNET_NO ==
665 GNUNET_CONTAINER_bloomfilter_test (op->remote_bf,
666 &mutated_hash))
667 {
668 GNUNET_break (0 < op->my_element_count);
669 op->my_element_count--;
670 GNUNET_CRYPTO_hash_xor (&op->my_xor,
671 &ee->element_hash,
672 &op->my_xor);
673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
674 "Bloom filter reduction of my_elements, removing %s:%u\n",
675 GNUNET_h2s (&ee->element_hash),
676 ee->element.size);
677 GNUNET_assert (GNUNET_YES ==
678 GNUNET_CONTAINER_multihashmap_remove (op->my_elements,
679 &ee->element_hash,
680 ee));
681 send_client_removed_element (op,
682 &ee->element);
683 }
684 else
685 {
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687 "Bloom filter reduction of my_elements, keeping %s:%u\n",
688 GNUNET_h2s (&ee->element_hash),
689 ee->element.size);
690 }
691 return GNUNET_YES;
692}
693
694
695/**
696 * Create initial bloomfilter based on all the elements given.
697 *
698 * @param cls the `struct Operation *`
699 * @param key current key code
700 * @param value the `struct ElementEntry` to process
701 * @return #GNUNET_YES (we should continue to iterate)
702 */
703static int
704iterator_bf_create (void *cls,
705 const struct GNUNET_HashCode *key,
706 void *value)
707{
708 struct Operation *op = cls;
709 struct ElementEntry *ee = value;
710 struct GNUNET_HashCode mutated_hash;
711
712 GNUNET_BLOCK_mingle_hash (&ee->element_hash,
713 op->salt,
714 &mutated_hash);
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
716 "Initializing BF with hash %s with salt %u\n",
717 GNUNET_h2s (&mutated_hash),
718 op->salt);
719 GNUNET_CONTAINER_bloomfilter_add (op->local_bf,
720 &mutated_hash);
721 return GNUNET_YES;
722}
723
724
725/**
726 * Destroy the given operation. Used for any operation where both
727 * peers were known and that thus actually had a vt and channel. Must
728 * not be used for operations where 'listener' is still set and we do
729 * not know the other peer.
730 *
731 * Call the implementation-specific cancel function of the operation.
732 * Disconnects from the remote peer. Does not disconnect the client,
733 * as there may be multiple operations per set.
734 *
735 * @param op operation to destroy
736 */
737static void
738_GSS_operation_destroy (struct Operation *op)
739{
740 struct Set *set = op->set;
741 struct GNUNET_CADET_Channel *channel;
742
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying operation %p\n", op);
744 GNUNET_assert (NULL == op->listener);
745 if (NULL != op->remote_bf)
746 {
747 GNUNET_CONTAINER_bloomfilter_free (op->remote_bf);
748 op->remote_bf = NULL;
749 }
750 if (NULL != op->local_bf)
751 {
752 GNUNET_CONTAINER_bloomfilter_free (op->local_bf);
753 op->local_bf = NULL;
754 }
755 if (NULL != op->my_elements)
756 {
757 GNUNET_CONTAINER_multihashmap_destroy (op->my_elements);
758 op->my_elements = NULL;
759 }
760 if (NULL != op->full_result_iter)
761 {
762 GNUNET_CONTAINER_multihashmap_iterator_destroy (
763 op->full_result_iter);
764 op->full_result_iter = NULL;
765 }
766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
767 "Destroying intersection op state done\n");
768 if (NULL != set)
769 {
770 GNUNET_CONTAINER_DLL_remove (set->ops_head,
771 set->ops_tail,
772 op);
773 op->set = NULL;
774 }
775 if (NULL != op->context_msg)
776 {
777 GNUNET_free (op->context_msg);
778 op->context_msg = NULL;
779 }
780 if (NULL != (channel = op->channel))
781 {
782 /* This will free op; called conditionally as this helper function
783 is also called from within the channel disconnect handler. */
784 op->channel = NULL;
785 GNUNET_CADET_channel_destroy (channel);
786 }
787 /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
788 * there was a channel end handler that will free 'op' on the call stack. */
789}
790
791
792/**
793 * This function probably should not exist
794 * and be replaced by inlining more specific
795 * logic in the various places where it is called.
796 */
797static void
798_GSS_operation_destroy2 (struct Operation *op);
799
800
801/**
802 * Destroy an incoming request from a remote peer
803 *
804 * @param op remote request to destroy
805 */
806static void
807incoming_destroy (struct Operation *op)
808{
809 struct Listener *listener;
810
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
812 "Destroying incoming operation %p\n",
813 op);
814 if (NULL != (listener = op->listener))
815 {
816 GNUNET_CONTAINER_DLL_remove (listener->op_head,
817 listener->op_tail,
818 op);
819 op->listener = NULL;
820 }
821 if (NULL != op->timeout_task)
822 {
823 GNUNET_SCHEDULER_cancel (op->timeout_task);
824 op->timeout_task = NULL;
825 }
826 _GSS_operation_destroy2 (op);
827}
828
829
830/**
831 * Signal to the client that the operation has finished and
832 * destroy the operation.
833 *
834 * @param cls operation to destroy
835 */
836static void
837send_client_done_and_destroy (void *cls)
838{
839 struct Operation *op = cls;
840 struct GNUNET_MQ_Envelope *ev;
841 struct GNUNET_SETI_ResultMessage *rm;
842
843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
844 "Intersection succeeded, sending DONE to local client\n");
845 GNUNET_STATISTICS_update (_GSS_statistics,
846 "# Intersection operations succeeded",
847 1,
848 GNUNET_NO);
849 ev = GNUNET_MQ_msg (rm,
850 GNUNET_MESSAGE_TYPE_SETI_RESULT);
851 rm->request_id = htonl (op->client_request_id);
852 rm->result_status = htons (GNUNET_SETI_STATUS_DONE);
853 rm->element_type = htons (0);
854 GNUNET_MQ_send (op->set->cs->mq,
855 ev);
856 _GSS_operation_destroy (op);
857}
858
859
860/**
861 * This function probably should not exist
862 * and be replaced by inlining more specific
863 * logic in the various places where it is called.
864 */
865static void
866_GSS_operation_destroy2 (struct Operation *op)
867{
868 struct GNUNET_CADET_Channel *channel;
869
870 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
871 "channel_end_cb called\n");
872 if (NULL != (channel = op->channel))
873 {
874 /* This will free op; called conditionally as this helper function
875 is also called from within the channel disconnect handler. */
876 op->channel = NULL;
877 GNUNET_CADET_channel_destroy (channel);
878 }
879 if (NULL != op->listener)
880 {
881 incoming_destroy (op);
882 return;
883 }
884 if (NULL != op->set)
885 {
886 if (GNUNET_YES == op->channel_death_expected)
887 {
888 /* oh goodie, we are done! */
889 send_client_done_and_destroy (op);
890 }
891 else
892 {
893 /* sorry, channel went down early, too bad. */
894 _GSS_operation_destroy (op);
895 }
896 }
897 else
898 _GSS_operation_destroy (op);
899 GNUNET_free (op);
900}
901
902
903/**
904 * Inform the client that the intersection operation has failed,
905 * and proceed to destroy the evaluate operation.
906 *
907 * @param op the intersection operation to fail
908 */
909static void
910fail_intersection_operation (struct Operation *op)
911{
912 struct GNUNET_MQ_Envelope *ev;
913 struct GNUNET_SETI_ResultMessage *msg;
914
915 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
916 "Intersection operation failed\n");
917 GNUNET_STATISTICS_update (_GSS_statistics,
918 "# Intersection operations failed",
919 1,
920 GNUNET_NO);
921 if (NULL != op->my_elements)
922 {
923 GNUNET_CONTAINER_multihashmap_destroy (op->my_elements);
924 op->my_elements = NULL;
925 }
926 ev = GNUNET_MQ_msg (msg,
927 GNUNET_MESSAGE_TYPE_SETI_RESULT);
928 msg->result_status = htons (GNUNET_SETI_STATUS_FAILURE);
929 msg->request_id = htonl (op->client_request_id);
930 msg->element_type = htons (0);
931 GNUNET_MQ_send (op->set->cs->mq,
932 ev);
933 _GSS_operation_destroy (op);
934}
935
936
937/**
938 * Send a bloomfilter to our peer. After the result done message has
939 * been sent to the client, destroy the evaluate operation.
940 *
941 * @param op intersection operation
942 */
943static void
944send_bloomfilter (struct Operation *op)
945{
946 struct GNUNET_MQ_Envelope *ev;
947 struct BFMessage *msg;
948 uint32_t bf_size;
949 uint32_t bf_elementbits;
950 uint32_t chunk_size;
951 char *bf_data;
952 uint32_t offset;
953
954 /* We consider the ratio of the set sizes to determine
955 the number of bits per element, as the smaller set
956 should use more bits to maximize its set reduction
957 potential and minimize overall bandwidth consumption. */
958 bf_elementbits = 2 + ceil (log2 ((double)
959 (op->remote_element_count
960 / (double) op->my_element_count)));
961 if (bf_elementbits < 1)
962 bf_elementbits = 1; /* make sure k is not 0 */
963 /* optimize BF-size to ~50% of bits set */
964 bf_size = ceil ((double) (op->my_element_count
965 * bf_elementbits / log (2)));
966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
967 "Sending Bloom filter (%u) of size %u bytes\n",
968 (unsigned int) bf_elementbits,
969 (unsigned int) bf_size);
970 op->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
971 bf_size,
972 bf_elementbits);
973 op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
974 UINT32_MAX);
975 GNUNET_CONTAINER_multihashmap_iterate (op->my_elements,
976 &iterator_bf_create,
977 op);
978
979 /* send our Bloom filter */
980 GNUNET_STATISTICS_update (_GSS_statistics,
981 "# Intersection Bloom filters sent",
982 1,
983 GNUNET_NO);
984 chunk_size = 60 * 1024 - sizeof(struct BFMessage);
985 if (bf_size <= chunk_size)
986 {
987 /* singlepart */
988 chunk_size = bf_size;
989 ev = GNUNET_MQ_msg_extra (msg,
990 chunk_size,
991 GNUNET_MESSAGE_TYPE_SETI_P2P_BF);
992 GNUNET_assert (GNUNET_SYSERR !=
993 GNUNET_CONTAINER_bloomfilter_get_raw_data (
994 op->local_bf,
995 (char *) &msg[1],
996 bf_size));
997 msg->sender_element_count = htonl (op->my_element_count);
998 msg->bloomfilter_total_length = htonl (bf_size);
999 msg->bits_per_element = htonl (bf_elementbits);
1000 msg->sender_mutator = htonl (op->salt);
1001 msg->element_xor_hash = op->my_xor;
1002 GNUNET_MQ_send (op->mq, ev);
1003 }
1004 else
1005 {
1006 /* multipart */
1007 bf_data = GNUNET_malloc (bf_size);
1008 GNUNET_assert (GNUNET_SYSERR !=
1009 GNUNET_CONTAINER_bloomfilter_get_raw_data (
1010 op->local_bf,
1011 bf_data,
1012 bf_size));
1013 offset = 0;
1014 while (offset < bf_size)
1015 {
1016 if (bf_size - chunk_size < offset)
1017 chunk_size = bf_size - offset;
1018 ev = GNUNET_MQ_msg_extra (msg,
1019 chunk_size,
1020 GNUNET_MESSAGE_TYPE_SETI_P2P_BF);
1021 GNUNET_memcpy (&msg[1],
1022 &bf_data[offset],
1023 chunk_size);
1024 offset += chunk_size;
1025 msg->sender_element_count = htonl (op->my_element_count);
1026 msg->bloomfilter_total_length = htonl (bf_size);
1027 msg->bits_per_element = htonl (bf_elementbits);
1028 msg->sender_mutator = htonl (op->salt);
1029 msg->element_xor_hash = op->my_xor;
1030 GNUNET_MQ_send (op->mq, ev);
1031 }
1032 GNUNET_free (bf_data);
1033 }
1034 GNUNET_CONTAINER_bloomfilter_free (op->local_bf);
1035 op->local_bf = NULL;
1036}
1037
1038
1039/**
1040 * Remember that we are done dealing with the local client
1041 * AND have sent the other peer our message that we are done,
1042 * so we are not just waiting for the channel to die before
1043 * telling the local client that we are done as our last act.
1044 *
1045 * @param cls the `struct Operation`.
1046 */
1047static void
1048finished_local_operations (void *cls)
1049{
1050 struct Operation *op = cls;
1051
1052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053 "DONE sent to other peer, now waiting for other end to close the channel\n");
1054 op->phase = PHASE_FINISHED;
1055 op->channel_death_expected = GNUNET_YES;
1056}
1057
1058
1059/**
1060 * Notify the other peer that we are done. Once this message
1061 * is out, we still need to notify the local client that we
1062 * are done.
1063 *
1064 * @param op operation to notify for.
1065 */
1066static void
1067send_p2p_done (struct Operation *op)
1068{
1069 struct GNUNET_MQ_Envelope *ev;
1070 struct IntersectionDoneMessage *idm;
1071
1072 GNUNET_assert (PHASE_MUST_SEND_DONE == op->phase);
1073 GNUNET_assert (GNUNET_NO == op->channel_death_expected);
1074 ev = GNUNET_MQ_msg (idm,
1075 GNUNET_MESSAGE_TYPE_SETI_P2P_DONE);
1076 idm->final_element_count = htonl (op->my_element_count);
1077 idm->element_xor_hash = op->my_xor;
1078 GNUNET_MQ_notify_sent (ev,
1079 &finished_local_operations,
1080 op);
1081 GNUNET_MQ_send (op->mq,
1082 ev);
1083}
1084
1085
1086/**
1087 * Send all elements in the full result iterator.
1088 *
1089 * @param cls the `struct Operation *`
1090 */
1091static void
1092send_remaining_elements (void *cls)
1093{
1094 struct Operation *op = cls;
1095 const void *nxt;
1096 const struct ElementEntry *ee;
1097 struct GNUNET_MQ_Envelope *ev;
1098 struct GNUNET_SETI_ResultMessage *rm;
1099 const struct GNUNET_SETI_Element *element;
1100 int res;
1101
1102 if (GNUNET_NO == op->return_intersection)
1103 {
1104 GNUNET_break (0);
1105 return; /* Wrong mode for transmitting removed elements */
1106 }
1107 res = GNUNET_CONTAINER_multihashmap_iterator_next (
1108 op->full_result_iter,
1109 NULL,
1110 &nxt);
1111 if (GNUNET_NO == res)
1112 {
1113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114 "Sending done and destroy because iterator ran out\n");
1115 GNUNET_CONTAINER_multihashmap_iterator_destroy (
1116 op->full_result_iter);
1117 op->full_result_iter = NULL;
1118 if (PHASE_DONE_RECEIVED == op->phase)
1119 {
1120 op->phase = PHASE_FINISHED;
1121 send_client_done_and_destroy (op);
1122 }
1123 else if (PHASE_MUST_SEND_DONE == op->phase)
1124 {
1125 send_p2p_done (op);
1126 }
1127 else
1128 {
1129 GNUNET_assert (0);
1130 }
1131 return;
1132 }
1133 ee = nxt;
1134 element = &ee->element;
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1136 "Sending element %s:%u to client (full set)\n",
1137 GNUNET_h2s (&ee->element_hash),
1138 element->size);
1139 GNUNET_assert (0 != op->client_request_id);
1140 ev = GNUNET_MQ_msg_extra (rm,
1141 element->size,
1142 GNUNET_MESSAGE_TYPE_SETI_RESULT);
1143 GNUNET_assert (NULL != ev);
1144 rm->result_status = htons (GNUNET_SETI_STATUS_ADD_LOCAL);
1145 rm->request_id = htonl (op->client_request_id);
1146 rm->element_type = element->element_type;
1147 GNUNET_memcpy (&rm[1],
1148 element->data,
1149 element->size);
1150 GNUNET_MQ_notify_sent (ev,
1151 &send_remaining_elements,
1152 op);
1153 GNUNET_MQ_send (op->set->cs->mq,
1154 ev);
1155}
1156
1157
1158/**
1159 * Fills the "my_elements" hashmap with the initial set of
1160 * (non-deleted) elements from the set of the specification.
1161 *
1162 * @param cls closure with the `struct Operation *`
1163 * @param key current key code for the element
1164 * @param value value in the hash map with the `struct ElementEntry *`
1165 * @return #GNUNET_YES (we should continue to iterate)
1166 */
1167static int
1168initialize_map_unfiltered (void *cls,
1169 const struct GNUNET_HashCode *key,
1170 void *value)
1171{
1172 struct ElementEntry *ee = value;
1173 struct Operation *op = cls;
1174
1175 if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
1176 return GNUNET_YES; /* element not live in operation's generation */
1177 GNUNET_CRYPTO_hash_xor (&op->my_xor,
1178 &ee->element_hash,
1179 &op->my_xor);
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1181 "Initial full initialization of my_elements, adding %s:%u\n",
1182 GNUNET_h2s (&ee->element_hash),
1183 ee->element.size);
1184 GNUNET_break (GNUNET_YES ==
1185 GNUNET_CONTAINER_multihashmap_put (op->my_elements,
1186 &ee->element_hash,
1187 ee,
1188 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1189 return GNUNET_YES;
1190}
1191
1192
1193/**
1194 * Send our element count to the peer, in case our element count is
1195 * lower than theirs.
1196 *
1197 * @param op intersection operation
1198 */
1199static void
1200send_element_count (struct Operation *op)
1201{
1202 struct GNUNET_MQ_Envelope *ev;
1203 struct IntersectionElementInfoMessage *msg;
1204
1205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1206 "Sending our element count (%u)\n",
1207 op->my_element_count);
1208 ev = GNUNET_MQ_msg (msg,
1209 GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO);
1210 msg->sender_element_count = htonl (op->my_element_count);
1211 GNUNET_MQ_send (op->mq, ev);
1212}
1213
1214
1215/**
1216 * We go first, initialize our map with all elements and
1217 * send the first Bloom filter.
1218 *
1219 * @param op operation to start exchange for
1220 */
1221static void
1222begin_bf_exchange (struct Operation *op)
1223{
1224 op->phase = PHASE_BF_EXCHANGE;
1225 GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1226 &initialize_map_unfiltered,
1227 op);
1228 send_bloomfilter (op);
1229}
1230
1231
1232/**
1233 * Handle the initial `struct IntersectionElementInfoMessage` from a
1234 * remote peer.
1235 *
1236 * @param cls the intersection operation
1237 * @param mh the header of the message
1238 */
1239static void
1240handle_intersection_p2p_element_info (void *cls,
1241 const struct
1242 IntersectionElementInfoMessage *msg)
1243{
1244 struct Operation *op = cls;
1245
1246 op->remote_element_count = ntohl (msg->sender_element_count);
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1248 "Received remote element count (%u), I have %u\n",
1249 op->remote_element_count,
1250 op->my_element_count);
1251 if (((PHASE_INITIAL != op->phase) &&
1252 (PHASE_COUNT_SENT != op->phase)) ||
1253 (op->my_element_count > op->remote_element_count) ||
1254 (0 == op->my_element_count) ||
1255 (0 == op->remote_element_count))
1256 {
1257 GNUNET_break_op (0);
1258 fail_intersection_operation (op);
1259 return;
1260 }
1261 GNUNET_break (NULL == op->remote_bf);
1262 begin_bf_exchange (op);
1263 GNUNET_CADET_receive_done (op->channel);
1264}
1265
1266
1267/**
1268 * Process a Bloomfilter once we got all the chunks.
1269 *
1270 * @param op the intersection operation
1271 */
1272static void
1273process_bf (struct Operation *op)
1274{
1275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1276 "Received BF in phase %u, foreign count is %u, my element count is %u/%u\n",
1277 op->phase,
1278 op->remote_element_count,
1279 op->my_element_count,
1280 GNUNET_CONTAINER_multihashmap_size (op->set->content->elements));
1281 switch (op->phase)
1282 {
1283 case PHASE_INITIAL:
1284 GNUNET_break_op (0);
1285 fail_intersection_operation (op);
1286 return;
1287 case PHASE_COUNT_SENT:
1288 /* This is the first BF being sent, build our initial map with
1289 filtering in place */
1290 op->my_element_count = 0;
1291 GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1292 &filtered_map_initialization,
1293 op);
1294 break;
1295 case PHASE_BF_EXCHANGE:
1296 /* Update our set by reduction */
1297 GNUNET_CONTAINER_multihashmap_iterate (op->my_elements,
1298 &iterator_bf_reduce,
1299 op);
1300 break;
1301 case PHASE_MUST_SEND_DONE:
1302 GNUNET_break_op (0);
1303 fail_intersection_operation (op);
1304 return;
1305 case PHASE_DONE_RECEIVED:
1306 GNUNET_break_op (0);
1307 fail_intersection_operation (op);
1308 return;
1309 case PHASE_FINISHED:
1310 GNUNET_break_op (0);
1311 fail_intersection_operation (op);
1312 return;
1313 }
1314 GNUNET_CONTAINER_bloomfilter_free (op->remote_bf);
1315 op->remote_bf = NULL;
1316
1317 if ((0 == op->my_element_count) || /* fully disjoint */
1318 ((op->my_element_count == op->remote_element_count) &&
1319 (0 == GNUNET_memcmp (&op->my_xor,
1320 &op->other_xor))))
1321 {
1322 /* we are done */
1323 op->phase = PHASE_MUST_SEND_DONE;
1324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1325 "Intersection succeeded, sending DONE to other peer\n");
1326 GNUNET_CONTAINER_bloomfilter_free (op->local_bf);
1327 op->local_bf = NULL;
1328 if (GNUNET_YES == op->return_intersection)
1329 {
1330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1331 "Sending full result set (%u elements)\n",
1332 GNUNET_CONTAINER_multihashmap_size (op->my_elements));
1333 op->full_result_iter
1334 = GNUNET_CONTAINER_multihashmap_iterator_create (
1335 op->my_elements);
1336 send_remaining_elements (op);
1337 return;
1338 }
1339 send_p2p_done (op);
1340 return;
1341 }
1342 op->phase = PHASE_BF_EXCHANGE;
1343 send_bloomfilter (op);
1344}
1345
1346
1347/**
1348 * Check an BF message from a remote peer.
1349 *
1350 * @param cls the intersection operation
1351 * @param msg the header of the message
1352 * @return #GNUNET_OK if @a msg is well-formed
1353 */
1354static int
1355check_intersection_p2p_bf (void *cls,
1356 const struct BFMessage *msg)
1357{
1358 struct Operation *op = cls;
1359
1360 (void) op;
1361 return GNUNET_OK;
1362}
1363
1364
1365/**
1366 * Handle an BF message from a remote peer.
1367 *
1368 * @param cls the intersection operation
1369 * @param msg the header of the message
1370 */
1371static void
1372handle_intersection_p2p_bf (void *cls,
1373 const struct BFMessage *msg)
1374{
1375 struct Operation *op = cls;
1376 uint32_t bf_size;
1377 uint32_t chunk_size;
1378 uint32_t bf_bits_per_element;
1379
1380 switch (op->phase)
1381 {
1382 case PHASE_INITIAL:
1383 GNUNET_break_op (0);
1384 fail_intersection_operation (op);
1385 return;
1386
1387 case PHASE_COUNT_SENT:
1388 case PHASE_BF_EXCHANGE:
1389 bf_size = ntohl (msg->bloomfilter_total_length);
1390 bf_bits_per_element = ntohl (msg->bits_per_element);
1391 chunk_size = htons (msg->header.size) - sizeof(struct BFMessage);
1392 op->other_xor = msg->element_xor_hash;
1393 if (bf_size == chunk_size)
1394 {
1395 if (NULL != op->bf_data)
1396 {
1397 GNUNET_break_op (0);
1398 fail_intersection_operation (op);
1399 return;
1400 }
1401 /* single part, done here immediately */
1402 op->remote_bf
1403 = GNUNET_CONTAINER_bloomfilter_init ((const char *) &msg[1],
1404 bf_size,
1405 bf_bits_per_element);
1406 op->salt = ntohl (msg->sender_mutator);
1407 op->remote_element_count = ntohl (msg->sender_element_count);
1408 process_bf (op);
1409 break;
1410 }
1411 /* multipart chunk */
1412 if (NULL == op->bf_data)
1413 {
1414 /* first chunk, initialize */
1415 op->bf_data = GNUNET_malloc (bf_size);
1416 op->bf_data_size = bf_size;
1417 op->bf_bits_per_element = bf_bits_per_element;
1418 op->bf_data_offset = 0;
1419 op->salt = ntohl (msg->sender_mutator);
1420 op->remote_element_count = ntohl (msg->sender_element_count);
1421 }
1422 else
1423 {
1424 /* increment */
1425 if ((op->bf_data_size != bf_size) ||
1426 (op->bf_bits_per_element != bf_bits_per_element) ||
1427 (op->bf_data_offset + chunk_size > bf_size) ||
1428 (op->salt != ntohl (msg->sender_mutator)) ||
1429 (op->remote_element_count != ntohl (msg->sender_element_count)))
1430 {
1431 GNUNET_break_op (0);
1432 fail_intersection_operation (op);
1433 return;
1434 }
1435 }
1436 GNUNET_memcpy (&op->bf_data[op->bf_data_offset],
1437 (const char *) &msg[1],
1438 chunk_size);
1439 op->bf_data_offset += chunk_size;
1440 if (op->bf_data_offset == bf_size)
1441 {
1442 /* last chunk, run! */
1443 op->remote_bf
1444 = GNUNET_CONTAINER_bloomfilter_init (op->bf_data,
1445 bf_size,
1446 bf_bits_per_element);
1447 GNUNET_free (op->bf_data);
1448 op->bf_data = NULL;
1449 op->bf_data_size = 0;
1450 process_bf (op);
1451 }
1452 break;
1453
1454 default:
1455 GNUNET_break_op (0);
1456 fail_intersection_operation (op);
1457 return;
1458 }
1459 GNUNET_CADET_receive_done (op->channel);
1460}
1461
1462
1463/**
1464 * Remove all elements from our hashmap.
1465 *
1466 * @param cls closure with the `struct Operation *`
1467 * @param key current key code
1468 * @param value value in the hash map
1469 * @return #GNUNET_YES (we should continue to iterate)
1470 */
1471static int
1472filter_all (void *cls,
1473 const struct GNUNET_HashCode *key,
1474 void *value)
1475{
1476 struct Operation *op = cls;
1477 struct ElementEntry *ee = value;
1478
1479 GNUNET_break (0 < op->my_element_count);
1480 op->my_element_count--;
1481 GNUNET_CRYPTO_hash_xor (&op->my_xor,
1482 &ee->element_hash,
1483 &op->my_xor);
1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485 "Final reduction of my_elements, removing %s:%u\n",
1486 GNUNET_h2s (&ee->element_hash),
1487 ee->element.size);
1488 GNUNET_assert (GNUNET_YES ==
1489 GNUNET_CONTAINER_multihashmap_remove (op->my_elements,
1490 &ee->element_hash,
1491 ee));
1492 send_client_removed_element (op,
1493 &ee->element);
1494 return GNUNET_YES;
1495}
1496
1497
1498/**
1499 * Handle a done message from a remote peer
1500 *
1501 * @param cls the intersection operation
1502 * @param mh the message
1503 */
1504static void
1505handle_intersection_p2p_done (void *cls,
1506 const struct IntersectionDoneMessage *idm)
1507{
1508 struct Operation *op = cls;
1509
1510 if (PHASE_BF_EXCHANGE != op->phase)
1511 {
1512 /* wrong phase to conclude? FIXME: Or should we allow this
1513 if the other peer has _initially_ already an empty set? */
1514 GNUNET_break_op (0);
1515 fail_intersection_operation (op);
1516 return;
1517 }
1518 if (0 == ntohl (idm->final_element_count))
1519 {
1520 /* other peer determined empty set is the intersection,
1521 remove all elements */
1522 GNUNET_CONTAINER_multihashmap_iterate (op->my_elements,
1523 &filter_all,
1524 op);
1525 }
1526 if ((op->my_element_count != ntohl (idm->final_element_count)) ||
1527 (0 != GNUNET_memcmp (&op->my_xor,
1528 &idm->element_xor_hash)))
1529 {
1530 /* Other peer thinks we are done, but we disagree on the result! */
1531 GNUNET_break_op (0);
1532 fail_intersection_operation (op);
1533 return;
1534 }
1535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536 "Got IntersectionDoneMessage, have %u elements in intersection\n",
1537 op->my_element_count);
1538 op->phase = PHASE_DONE_RECEIVED;
1539 GNUNET_CADET_receive_done (op->channel);
1540
1541 GNUNET_assert (GNUNET_NO == op->client_done_sent);
1542 if (GNUNET_YES == op->return_intersection)
1543 {
1544 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1545 "Sending full result set to client (%u elements)\n",
1546 GNUNET_CONTAINER_multihashmap_size (op->my_elements));
1547 op->full_result_iter
1548 = GNUNET_CONTAINER_multihashmap_iterator_create (op->my_elements);
1549 send_remaining_elements (op);
1550 return;
1551 }
1552 op->phase = PHASE_FINISHED;
1553 send_client_done_and_destroy (op);
1554}
1555
1556
1557/**
1558 * Get the incoming socket associated with the given id.
1559 *
1560 * @param listener the listener to look in
1561 * @param id id to look for
1562 * @return the incoming socket associated with the id,
1563 * or NULL if there is none
1564 */
1565static struct Operation *
1566get_incoming (uint32_t id)
1567{
1568 for (struct Listener *listener = listener_head; NULL != listener;
1569 listener = listener->next)
1570 {
1571 for (struct Operation *op = listener->op_head; NULL != op; op = op->next)
1572 if (op->suggest_id == id)
1573 return op;
1574 }
1575 return NULL;
1576}
1577
1578
1579/**
1580 * Callback called when a client connects to the service.
1581 *
1582 * @param cls closure for the service
1583 * @param c the new client that connected to the service
1584 * @param mq the message queue used to send messages to the client
1585 * @return @a `struct ClientState`
1586 */
1587static void *
1588client_connect_cb (void *cls,
1589 struct GNUNET_SERVICE_Client *c,
1590 struct GNUNET_MQ_Handle *mq)
1591{
1592 struct ClientState *cs;
1593
1594 num_clients++;
1595 cs = GNUNET_new (struct ClientState);
1596 cs->client = c;
1597 cs->mq = mq;
1598 return cs;
1599}
1600
1601
1602/**
1603 * Iterator over hash map entries to free element entries.
1604 *
1605 * @param cls closure
1606 * @param key current key code
1607 * @param value a `struct ElementEntry *` to be free'd
1608 * @return #GNUNET_YES (continue to iterate)
1609 */
1610static int
1611destroy_elements_iterator (void *cls,
1612 const struct GNUNET_HashCode *key,
1613 void *value)
1614{
1615 struct ElementEntry *ee = value;
1616
1617 GNUNET_free (ee);
1618 return GNUNET_YES;
1619}
1620
1621
1622/**
1623 * Clean up after a client has disconnected
1624 *
1625 * @param cls closure, unused
1626 * @param client the client to clean up after
1627 * @param internal_cls the `struct ClientState`
1628 */
1629static void
1630client_disconnect_cb (void *cls,
1631 struct GNUNET_SERVICE_Client *client,
1632 void *internal_cls)
1633{
1634 struct ClientState *cs = internal_cls;
1635 struct Operation *op;
1636 struct Listener *listener;
1637 struct Set *set;
1638
1639 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, cleaning up\n");
1640 if (NULL != (set = cs->set))
1641 {
1642 struct SetContent *content = set->content;
1643
1644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying client's set\n");
1645 /* Destroy pending set operations */
1646 while (NULL != set->ops_head)
1647 _GSS_operation_destroy (set->ops_head);
1648
1649 /* free set content (or at least decrement RC) */
1650 set->content = NULL;
1651 GNUNET_assert (0 != content->refcount);
1652 content->refcount--;
1653 if (0 == content->refcount)
1654 {
1655 GNUNET_assert (NULL != content->elements);
1656 GNUNET_CONTAINER_multihashmap_iterate (content->elements,
1657 &destroy_elements_iterator,
1658 NULL);
1659 GNUNET_CONTAINER_multihashmap_destroy (content->elements);
1660 content->elements = NULL;
1661 GNUNET_free (content);
1662 }
1663 GNUNET_free (set);
1664 }
1665
1666 if (NULL != (listener = cs->listener))
1667 {
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying client's listener\n");
1669 GNUNET_CADET_close_port (listener->open_port);
1670 listener->open_port = NULL;
1671 while (NULL != (op = listener->op_head))
1672 {
1673 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1674 "Destroying incoming operation `%u' from peer `%s'\n",
1675 (unsigned int) op->client_request_id,
1676 GNUNET_i2s (&op->peer));
1677 incoming_destroy (op);
1678 }
1679 GNUNET_CONTAINER_DLL_remove (listener_head, listener_tail, listener);
1680 GNUNET_free (listener);
1681 }
1682 GNUNET_free (cs);
1683 num_clients--;
1684 if ((GNUNET_YES == in_shutdown) && (0 == num_clients))
1685 {
1686 if (NULL != cadet)
1687 {
1688 GNUNET_CADET_disconnect (cadet);
1689 cadet = NULL;
1690 }
1691 }
1692}
1693
1694
1695/**
1696 * Check a request for a set operation from another peer.
1697 *
1698 * @param cls the operation state
1699 * @param msg the received message
1700 * @return #GNUNET_OK if the channel should be kept alive,
1701 * #GNUNET_SYSERR to destroy the channel
1702 */
1703static int
1704check_incoming_msg (void *cls,
1705 const struct OperationRequestMessage *msg)
1706{
1707 struct Operation *op = cls;
1708 struct Listener *listener = op->listener;
1709 const struct GNUNET_MessageHeader *nested_context;
1710
1711 /* double operation request */
1712 if (0 != op->suggest_id)
1713 {
1714 GNUNET_break_op (0);
1715 return GNUNET_SYSERR;
1716 }
1717 /* This should be equivalent to the previous condition, but can't hurt to check twice */
1718 if (NULL == listener)
1719 {
1720 GNUNET_break (0);
1721 return GNUNET_SYSERR;
1722 }
1723 nested_context = GNUNET_MQ_extract_nested_mh (msg);
1724 if ((NULL != nested_context) &&
1725 (ntohs (nested_context->size) > GNUNET_SETI_CONTEXT_MESSAGE_MAX_SIZE))
1726 {
1727 GNUNET_break_op (0);
1728 return GNUNET_SYSERR;
1729 }
1730 return GNUNET_OK;
1731}
1732
1733
1734/**
1735 * Handle a request for a set operation from another peer. Checks if we
1736 * have a listener waiting for such a request (and in that case initiates
1737 * asking the listener about accepting the connection). If no listener
1738 * is waiting, we queue the operation request in hope that a listener
1739 * shows up soon (before timeout).
1740 *
1741 * This msg is expected as the first and only msg handled through the
1742 * non-operation bound virtual table, acceptance of this operation replaces
1743 * our virtual table and subsequent msgs would be routed differently (as
1744 * we then know what type of operation this is).
1745 *
1746 * @param cls the operation state
1747 * @param msg the received message
1748 * @return #GNUNET_OK if the channel should be kept alive,
1749 * #GNUNET_SYSERR to destroy the channel
1750 */
1751static void
1752handle_incoming_msg (void *cls,
1753 const struct OperationRequestMessage *msg)
1754{
1755 struct Operation *op = cls;
1756 struct Listener *listener = op->listener;
1757 const struct GNUNET_MessageHeader *nested_context;
1758 struct GNUNET_MQ_Envelope *env;
1759 struct GNUNET_SETI_RequestMessage *cmsg;
1760
1761 nested_context = GNUNET_MQ_extract_nested_mh (msg);
1762 /* Make a copy of the nested_context (application-specific context
1763 information that is opaque to set) so we can pass it to the
1764 listener later on */
1765 if (NULL != nested_context)
1766 op->context_msg = GNUNET_copy_message (nested_context);
1767 op->remote_element_count = ntohl (msg->element_count);
1768 GNUNET_log (
1769 GNUNET_ERROR_TYPE_DEBUG,
1770 "Received P2P operation request (port %s) for active listener\n",
1771 GNUNET_h2s (&op->listener->app_id));
1772 GNUNET_assert (0 == op->suggest_id);
1773 if (0 == suggest_id)
1774 suggest_id++;
1775 op->suggest_id = suggest_id++;
1776 GNUNET_assert (NULL != op->timeout_task);
1777 GNUNET_SCHEDULER_cancel (op->timeout_task);
1778 op->timeout_task = NULL;
1779 env = GNUNET_MQ_msg_nested_mh (cmsg,
1780 GNUNET_MESSAGE_TYPE_SETI_REQUEST,
1781 op->context_msg);
1782 GNUNET_log (
1783 GNUNET_ERROR_TYPE_DEBUG,
1784 "Suggesting incoming request with accept id %u to listener %p of client %p\n",
1785 op->suggest_id,
1786 listener,
1787 listener->cs);
1788 cmsg->accept_id = htonl (op->suggest_id);
1789 cmsg->peer_id = op->peer;
1790 GNUNET_MQ_send (listener->cs->mq, env);
1791 /* NOTE: GNUNET_CADET_receive_done() will be called in
1792 #handle_client_accept() */
1793}
1794
1795
1796/**
1797 * Called when a client wants to create a new set. This is typically
1798 * the first request from a client, and includes the type of set
1799 * operation to be performed.
1800 *
1801 * @param cls client that sent the message
1802 * @param m message sent by the client
1803 */
1804static void
1805handle_client_create_set (void *cls,
1806 const struct GNUNET_SETI_CreateMessage *msg)
1807{
1808 struct ClientState *cs = cls;
1809 struct Set *set;
1810
1811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1812 "Client created new intersection set\n");
1813 if (NULL != cs->set)
1814 {
1815 /* There can only be one set per client */
1816 GNUNET_break (0);
1817 GNUNET_SERVICE_client_drop (cs->client);
1818 return;
1819 }
1820 set = GNUNET_new (struct Set);
1821 set->content = GNUNET_new (struct SetContent);
1822 set->content->refcount = 1;
1823 set->content->elements = GNUNET_CONTAINER_multihashmap_create (1,
1824 GNUNET_YES);
1825 set->cs = cs;
1826 cs->set = set;
1827 GNUNET_SERVICE_client_continue (cs->client);
1828}
1829
1830
1831/**
1832 * Timeout happens iff:
1833 * - we suggested an operation to our listener,
1834 * but did not receive a response in time
1835 * - we got the channel from a peer but no #GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST
1836 *
1837 * @param cls channel context
1838 * @param tc context information (why was this task triggered now)
1839 */
1840static void
1841incoming_timeout_cb (void *cls)
1842{
1843 struct Operation *op = cls;
1844
1845 op->timeout_task = NULL;
1846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1847 "Remote peer's incoming request timed out\n");
1848 incoming_destroy (op);
1849}
1850
1851
1852/**
1853 * Method called whenever another peer has added us to a channel the
1854 * other peer initiated. Only called (once) upon reception of data
1855 * from a channel we listen on.
1856 *
1857 * The channel context represents the operation itself and gets added
1858 * to a DLL, from where it gets looked up when our local listener
1859 * client responds to a proposed/suggested operation or connects and
1860 * associates with this operation.
1861 *
1862 * @param cls closure
1863 * @param channel new handle to the channel
1864 * @param source peer that started the channel
1865 * @return initial channel context for the channel
1866 * returns NULL on error
1867 */
1868static void *
1869channel_new_cb (void *cls,
1870 struct GNUNET_CADET_Channel *channel,
1871 const struct GNUNET_PeerIdentity *source)
1872{
1873 struct Listener *listener = cls;
1874 struct Operation *op;
1875
1876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1877 "New incoming channel\n");
1878 op = GNUNET_new (struct Operation);
1879 op->listener = listener;
1880 op->peer = *source;
1881 op->channel = channel;
1882 op->mq = GNUNET_CADET_get_mq (op->channel);
1883 op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1884 UINT32_MAX);
1885 op->timeout_task = GNUNET_SCHEDULER_add_delayed (INCOMING_CHANNEL_TIMEOUT,
1886 &incoming_timeout_cb,
1887 op);
1888 GNUNET_CONTAINER_DLL_insert (listener->op_head,
1889 listener->op_tail,
1890 op);
1891 return op;
1892}
1893
1894
1895/**
1896 * Function called whenever a channel is destroyed. Should clean up
1897 * any associated state. It must NOT call
1898 * GNUNET_CADET_channel_destroy() on the channel.
1899 *
1900 * The peer_disconnect function is part of a a virtual table set initially either
1901 * when a peer creates a new channel with us, or once we create
1902 * a new channel ourselves (evaluate).
1903 *
1904 * Once we know the exact type of operation (union/intersection), the vt is
1905 * replaced with an operation specific instance (_GSS_[op]_vt).
1906 *
1907 * @param channel_ctx place where local state associated
1908 * with the channel is stored
1909 * @param channel connection to the other end (henceforth invalid)
1910 */
1911static void
1912channel_end_cb (void *channel_ctx,
1913 const struct GNUNET_CADET_Channel *channel)
1914{
1915 struct Operation *op = channel_ctx;
1916
1917 op->channel = NULL;
1918 _GSS_operation_destroy2 (op);
1919}
1920
1921
1922/**
1923 * Function called whenever an MQ-channel's transmission window size changes.
1924 *
1925 * The first callback in an outgoing channel will be with a non-zero value
1926 * and will mean the channel is connected to the destination.
1927 *
1928 * For an incoming channel it will be called immediately after the
1929 * #GNUNET_CADET_ConnectEventHandler, also with a non-zero value.
1930 *
1931 * @param cls Channel closure.
1932 * @param channel Connection to the other end (henceforth invalid).
1933 * @param window_size New window size. If the is more messages than buffer size
1934 * this value will be negative..
1935 */
1936static void
1937channel_window_cb (void *cls,
1938 const struct GNUNET_CADET_Channel *channel,
1939 int window_size)
1940{
1941 /* FIXME: not implemented, we could do flow control here... */
1942}
1943
1944
1945/**
1946 * Called when a client wants to create a new listener.
1947 *
1948 * @param cls client that sent the message
1949 * @param msg message sent by the client
1950 */
1951static void
1952handle_client_listen (void *cls,
1953 const struct GNUNET_SETI_ListenMessage *msg)
1954{
1955 struct ClientState *cs = cls;
1956 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1957 GNUNET_MQ_hd_var_size (incoming_msg,
1958 GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST,
1959 struct OperationRequestMessage,
1960 NULL),
1961 GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
1962 GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO,
1963 struct IntersectionElementInfoMessage,
1964 NULL),
1965 GNUNET_MQ_hd_var_size (intersection_p2p_bf,
1966 GNUNET_MESSAGE_TYPE_SETI_P2P_BF,
1967 struct BFMessage,
1968 NULL),
1969 GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
1970 GNUNET_MESSAGE_TYPE_SETI_P2P_DONE,
1971 struct IntersectionDoneMessage,
1972 NULL),
1973 GNUNET_MQ_handler_end ()
1974 };
1975 struct Listener *listener;
1976
1977 if (NULL != cs->listener)
1978 {
1979 /* max. one active listener per client! */
1980 GNUNET_break (0);
1981 GNUNET_SERVICE_client_drop (cs->client);
1982 return;
1983 }
1984 listener = GNUNET_new (struct Listener);
1985 listener->cs = cs;
1986 cs->listener = listener;
1987 listener->app_id = msg->app_id;
1988 GNUNET_CONTAINER_DLL_insert (listener_head,
1989 listener_tail,
1990 listener);
1991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1992 "New listener for set intersection created (port %s)\n",
1993 GNUNET_h2s (&listener->app_id));
1994 listener->open_port = GNUNET_CADET_open_port (cadet,
1995 &msg->app_id,
1996 &channel_new_cb,
1997 listener,
1998 &channel_window_cb,
1999 &channel_end_cb,
2000 cadet_handlers);
2001 GNUNET_SERVICE_client_continue (cs->client);
2002}
2003
2004
2005/**
2006 * Called when the listening client rejects an operation
2007 * request by another peer.
2008 *
2009 * @param cls client that sent the message
2010 * @param msg message sent by the client
2011 */
2012static void
2013handle_client_reject (void *cls,
2014 const struct GNUNET_SETI_RejectMessage *msg)
2015{
2016 struct ClientState *cs = cls;
2017 struct Operation *op;
2018
2019 op = get_incoming (ntohl (msg->accept_reject_id));
2020 if (NULL == op)
2021 {
2022 /* no matching incoming operation for this reject;
2023 could be that the other peer already disconnected... */
2024 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2025 "Client rejected unknown operation %u\n",
2026 (unsigned int) ntohl (msg->accept_reject_id));
2027 GNUNET_SERVICE_client_continue (cs->client);
2028 return;
2029 }
2030 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2031 "Peer request (app %s) rejected by client\n",
2032 GNUNET_h2s (&cs->listener->app_id));
2033 _GSS_operation_destroy2 (op);
2034 GNUNET_SERVICE_client_continue (cs->client);
2035}
2036
2037
2038/**
2039 * Called when a client wants to add or remove an element to a set it inhabits.
2040 *
2041 * @param cls client that sent the message
2042 * @param msg message sent by the client
2043 */
2044static int
2045check_client_set_add (void *cls,
2046 const struct GNUNET_SETI_ElementMessage *msg)
2047{
2048 /* NOTE: Technically, we should probably check with the
2049 block library whether the element we are given is well-formed */
2050 return GNUNET_OK;
2051}
2052
2053
2054/**
2055 * Called when a client wants to add an element to a set it inhabits.
2056 *
2057 * @param cls client that sent the message
2058 * @param msg message sent by the client
2059 */
2060static void
2061handle_client_set_add (void *cls,
2062 const struct GNUNET_SETI_ElementMessage *msg)
2063{
2064 struct ClientState *cs = cls;
2065 struct Set *set;
2066 struct GNUNET_SETI_Element el;
2067 struct ElementEntry *ee;
2068 struct GNUNET_HashCode hash;
2069
2070 if (NULL == (set = cs->set))
2071 {
2072 /* client without a set requested an operation */
2073 GNUNET_break (0);
2074 GNUNET_SERVICE_client_drop (cs->client);
2075 return;
2076 }
2077 GNUNET_SERVICE_client_continue (cs->client);
2078 el.size = ntohs (msg->header.size) - sizeof(*msg);
2079 el.data = &msg[1];
2080 el.element_type = ntohs (msg->element_type);
2081 GNUNET_SETI_element_hash (&el,
2082 &hash);
2083 ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
2084 &hash);
2085 if (NULL == ee)
2086 {
2087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2088 "Client inserts element %s of size %u\n",
2089 GNUNET_h2s (&hash),
2090 el.size);
2091 ee = GNUNET_malloc (el.size + sizeof(*ee));
2092 ee->element.size = el.size;
2093 GNUNET_memcpy (&ee[1], el.data, el.size);
2094 ee->element.data = &ee[1];
2095 ee->element.element_type = el.element_type;
2096 ee->remote = GNUNET_NO;
2097 ee->element_hash = hash;
2098 GNUNET_break (GNUNET_YES ==
2099 GNUNET_CONTAINER_multihashmap_put (
2100 set->content->elements,
2101 &ee->element_hash,
2102 ee,
2103 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2104 }
2105 else
2106 {
2107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2108 "Client inserted element %s of size %u twice (ignored)\n",
2109 GNUNET_h2s (&hash),
2110 el.size);
2111 /* same element inserted twice */
2112 return;
2113 }
2114 set->current_set_element_count++;
2115}
2116
2117
2118/**
2119 * Advance the current generation of a set,
2120 * adding exclusion ranges if necessary.
2121 *
2122 * @param set the set where we want to advance the generation
2123 */
2124static void
2125advance_generation (struct Set *set)
2126{
2127 if (set->current_generation == set->content->latest_generation)
2128 {
2129 set->content->latest_generation++;
2130 set->current_generation++;
2131 return;
2132 }
2133 GNUNET_assert (set->current_generation < set->content->latest_generation);
2134}
2135
2136
2137/**
2138 * Called when a client wants to initiate a set operation with another
2139 * peer. Initiates the CADET connection to the listener and sends the
2140 * request.
2141 *
2142 * @param cls client that sent the message
2143 * @param msg message sent by the client
2144 * @return #GNUNET_OK if the message is well-formed
2145 */
2146static int
2147check_client_evaluate (void *cls,
2148 const struct GNUNET_SETI_EvaluateMessage *msg)
2149{
2150 /* FIXME: suboptimal, even if the context below could be NULL,
2151 there are malformed messages this does not check for... */
2152 return GNUNET_OK;
2153}
2154
2155
2156/**
2157 * Called when a client wants to initiate a set operation with another
2158 * peer. Initiates the CADET connection to the listener and sends the
2159 * request.
2160 *
2161 * @param cls client that sent the message
2162 * @param msg message sent by the client
2163 */
2164static void
2165handle_client_evaluate (void *cls,
2166 const struct GNUNET_SETI_EvaluateMessage *msg)
2167{
2168 struct ClientState *cs = cls;
2169 struct Operation *op = GNUNET_new (struct Operation);
2170 const struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2171 GNUNET_MQ_hd_var_size (incoming_msg,
2172 GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST,
2173 struct OperationRequestMessage,
2174 op),
2175 GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
2176 GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO,
2177 struct IntersectionElementInfoMessage,
2178 op),
2179 GNUNET_MQ_hd_var_size (intersection_p2p_bf,
2180 GNUNET_MESSAGE_TYPE_SETI_P2P_BF,
2181 struct BFMessage,
2182 op),
2183 GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
2184 GNUNET_MESSAGE_TYPE_SETI_P2P_DONE,
2185 struct IntersectionDoneMessage,
2186 op),
2187 GNUNET_MQ_handler_end ()
2188 };
2189 struct Set *set;
2190 const struct GNUNET_MessageHeader *context;
2191
2192 if (NULL == (set = cs->set))
2193 {
2194 GNUNET_break (0);
2195 GNUNET_free (op);
2196 GNUNET_SERVICE_client_drop (cs->client);
2197 return;
2198 }
2199 op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2200 UINT32_MAX);
2201 op->peer = msg->target_peer;
2202 op->return_intersection = htonl (msg->return_intersection);
2203 fprintf (stderr,
2204 "Return intersection for evaluate is %d\n",
2205 op->return_intersection);
2206 op->client_request_id = ntohl (msg->request_id);
2207 context = GNUNET_MQ_extract_nested_mh (msg);
2208
2209 /* Advance generation values, so that
2210 mutations won't interfer with the running operation. */
2211 op->set = set;
2212 op->generation_created = set->current_generation;
2213 advance_generation (set);
2214 GNUNET_CONTAINER_DLL_insert (set->ops_head,
2215 set->ops_tail,
2216 op);
2217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2218 "Creating new CADET channel to port %s for set intersection\n",
2219 GNUNET_h2s (&msg->app_id));
2220 op->channel = GNUNET_CADET_channel_create (cadet,
2221 op,
2222 &msg->target_peer,
2223 &msg->app_id,
2224 &channel_window_cb,
2225 &channel_end_cb,
2226 cadet_handlers);
2227 op->mq = GNUNET_CADET_get_mq (op->channel);
2228 {
2229 struct GNUNET_MQ_Envelope *ev;
2230 struct OperationRequestMessage *msg;
2231
2232 ev = GNUNET_MQ_msg_nested_mh (msg,
2233 GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST,
2234 context);
2235 if (NULL == ev)
2236 {
2237 /* the context message is too large!? */
2238 GNUNET_break (0);
2239 GNUNET_SERVICE_client_drop (cs->client);
2240 return;
2241 }
2242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2243 "Initiating intersection operation evaluation\n");
2244 /* we started the operation, thus we have to send the operation request */
2245 op->phase = PHASE_INITIAL;
2246 op->my_element_count = op->set->current_set_element_count;
2247 op->my_elements
2248 = GNUNET_CONTAINER_multihashmap_create (op->my_element_count,
2249 GNUNET_YES);
2250
2251 msg->element_count = htonl (op->my_element_count);
2252 GNUNET_MQ_send (op->mq,
2253 ev);
2254 op->phase = PHASE_COUNT_SENT;
2255 if (NULL != context)
2256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2257 "Sent op request with context message\n");
2258 else
2259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2260 "Sent op request without context message\n");
2261 }
2262 GNUNET_SERVICE_client_continue (cs->client);
2263}
2264
2265
2266/**
2267 * Handle a request from the client to cancel a running set operation.
2268 *
2269 * @param cls the client
2270 * @param msg the message
2271 */
2272static void
2273handle_client_cancel (void *cls,
2274 const struct GNUNET_SETI_CancelMessage *msg)
2275{
2276 struct ClientState *cs = cls;
2277 struct Set *set;
2278 struct Operation *op;
2279 int found;
2280
2281 if (NULL == (set = cs->set))
2282 {
2283 /* client without a set requested an operation */
2284 GNUNET_break (0);
2285 GNUNET_SERVICE_client_drop (cs->client);
2286 return;
2287 }
2288 found = GNUNET_NO;
2289 for (op = set->ops_head; NULL != op; op = op->next)
2290 {
2291 if (op->client_request_id == ntohl (msg->request_id))
2292 {
2293 found = GNUNET_YES;
2294 break;
2295 }
2296 }
2297 if (GNUNET_NO == found)
2298 {
2299 /* It may happen that the operation was already destroyed due to
2300 * the other peer disconnecting. The client may not know about this
2301 * yet and try to cancel the (just barely non-existent) operation.
2302 * So this is not a hard error.
2303 *///
2304 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2305 "Client canceled non-existent op %u\n",
2306 (uint32_t) ntohl (msg->request_id));
2307 }
2308 else
2309 {
2310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2311 "Client requested cancel for op %u\n",
2312 (uint32_t) ntohl (msg->request_id));
2313 _GSS_operation_destroy (op);
2314 }
2315 GNUNET_SERVICE_client_continue (cs->client);
2316}
2317
2318
2319/**
2320 * Handle a request from the client to accept a set operation that
2321 * came from a remote peer. We forward the accept to the associated
2322 * operation for handling
2323 *
2324 * @param cls the client
2325 * @param msg the message
2326 */
2327static void
2328handle_client_accept (void *cls,
2329 const struct GNUNET_SETI_AcceptMessage *msg)
2330{
2331 struct ClientState *cs = cls;
2332 struct Set *set;
2333 struct Operation *op;
2334 struct GNUNET_SETI_ResultMessage *result_message;
2335 struct GNUNET_MQ_Envelope *ev;
2336 struct Listener *listener;
2337
2338 if (NULL == (set = cs->set))
2339 {
2340 /* client without a set requested to accept */
2341 GNUNET_break (0);
2342 GNUNET_SERVICE_client_drop (cs->client);
2343 return;
2344 }
2345 op = get_incoming (ntohl (msg->accept_reject_id));
2346 if (NULL == op)
2347 {
2348 /* It is not an error if the set op does not exist -- it may
2349 * have been destroyed when the partner peer disconnected. */
2350 GNUNET_log (
2351 GNUNET_ERROR_TYPE_INFO,
2352 "Client %p accepted request %u of listener %p that is no longer active\n",
2353 cs,
2354 ntohl (msg->accept_reject_id),
2355 cs->listener);
2356 ev = GNUNET_MQ_msg (result_message,
2357 GNUNET_MESSAGE_TYPE_SETI_RESULT);
2358 result_message->request_id = msg->request_id;
2359 result_message->result_status = htons (GNUNET_SETI_STATUS_FAILURE);
2360 GNUNET_MQ_send (set->cs->mq, ev);
2361 GNUNET_SERVICE_client_continue (cs->client);
2362 return;
2363 }
2364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2365 "Client accepting request %u\n",
2366 (uint32_t) ntohl (msg->accept_reject_id));
2367 listener = op->listener;
2368 op->listener = NULL;
2369 op->return_intersection = htonl (msg->return_intersection);
2370 fprintf (stderr,
2371 "Return intersection for accept is %d\n",
2372 op->return_intersection);
2373 GNUNET_CONTAINER_DLL_remove (listener->op_head,
2374 listener->op_tail,
2375 op);
2376 op->set = set;
2377 GNUNET_CONTAINER_DLL_insert (set->ops_head,
2378 set->ops_tail,
2379 op);
2380 op->client_request_id = ntohl (msg->request_id);
2381
2382 /* Advance generation values, so that future mutations do not
2383 interfer with the running operation. */
2384 op->generation_created = set->current_generation;
2385 advance_generation (set);
2386 {
2387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2388 "Accepting set intersection operation\n");
2389 op->phase = PHASE_INITIAL;
2390 op->my_element_count
2391 = op->set->current_set_element_count;
2392 op->my_elements
2393 = GNUNET_CONTAINER_multihashmap_create (
2394 GNUNET_MIN (op->my_element_count,
2395 op->remote_element_count),
2396 GNUNET_YES);
2397 if (op->remote_element_count < op->my_element_count)
2398 {
2399 /* If the other peer (Alice) has fewer elements than us (Bob),
2400 we just send the count as Alice should send the first BF */
2401 send_element_count (op);
2402 op->phase = PHASE_COUNT_SENT;
2403 }
2404 else
2405 {
2406 /* We have fewer elements, so we start with the BF */
2407 begin_bf_exchange (op);
2408 }
2409 }
2410 /* Now allow CADET to continue, as we did not do this in
2411 #handle_incoming_msg (as we wanted to first see if the
2412 local client would accept the request). */
2413 GNUNET_CADET_receive_done (op->channel);
2414 GNUNET_SERVICE_client_continue (cs->client);
2415}
2416
2417
2418/**
2419 * Called to clean up, after a shutdown has been requested.
2420 *
2421 * @param cls closure, NULL
2422 */
2423static void
2424shutdown_task (void *cls)
2425{
2426 /* Delay actual shutdown to allow service to disconnect clients */
2427 in_shutdown = GNUNET_YES;
2428 if (0 == num_clients)
2429 {
2430 if (NULL != cadet)
2431 {
2432 GNUNET_CADET_disconnect (cadet);
2433 cadet = NULL;
2434 }
2435 }
2436 GNUNET_STATISTICS_destroy (_GSS_statistics,
2437 GNUNET_YES);
2438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2439 "handled shutdown request\n");
2440}
2441
2442
2443/**
2444 * Function called by the service's run
2445 * method to run service-specific setup code.
2446 *
2447 * @param cls closure
2448 * @param cfg configuration to use
2449 * @param service the initialized service
2450 */
2451static void
2452run (void *cls,
2453 const struct GNUNET_CONFIGURATION_Handle *cfg,
2454 struct GNUNET_SERVICE_Handle *service)
2455{
2456 /* FIXME: need to modify SERVICE (!) API to allow
2457 us to run a shutdown task *after* clients were
2458 forcefully disconnected! */
2459 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2460 NULL);
2461 _GSS_statistics = GNUNET_STATISTICS_create ("seti",
2462 cfg);
2463 cadet = GNUNET_CADET_connect (cfg);
2464 if (NULL == cadet)
2465 {
2466 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2467 _ ("Could not connect to CADET service\n"));
2468 GNUNET_SCHEDULER_shutdown ();
2469 return;
2470 }
2471}
2472
2473
2474/**
2475 * Define "main" method using service macro.
2476 */
2477GNUNET_SERVICE_MAIN (
2478 "seti",
2479 GNUNET_SERVICE_OPTION_NONE,
2480 &run,
2481 &client_connect_cb,
2482 &client_disconnect_cb,
2483 NULL,
2484 GNUNET_MQ_hd_fixed_size (client_accept,
2485 GNUNET_MESSAGE_TYPE_SETI_ACCEPT,
2486 struct GNUNET_SETI_AcceptMessage,
2487 NULL),
2488 GNUNET_MQ_hd_var_size (client_set_add,
2489 GNUNET_MESSAGE_TYPE_SETI_ADD,
2490 struct GNUNET_SETI_ElementMessage,
2491 NULL),
2492 GNUNET_MQ_hd_fixed_size (client_create_set,
2493 GNUNET_MESSAGE_TYPE_SETI_CREATE,
2494 struct GNUNET_SETI_CreateMessage,
2495 NULL),
2496 GNUNET_MQ_hd_var_size (client_evaluate,
2497 GNUNET_MESSAGE_TYPE_SETI_EVALUATE,
2498 struct GNUNET_SETI_EvaluateMessage,
2499 NULL),
2500 GNUNET_MQ_hd_fixed_size (client_listen,
2501 GNUNET_MESSAGE_TYPE_SETI_LISTEN,
2502 struct GNUNET_SETI_ListenMessage,
2503 NULL),
2504 GNUNET_MQ_hd_fixed_size (client_reject,
2505 GNUNET_MESSAGE_TYPE_SETI_REJECT,
2506 struct GNUNET_SETI_RejectMessage,
2507 NULL),
2508 GNUNET_MQ_hd_fixed_size (client_cancel,
2509 GNUNET_MESSAGE_TYPE_SETI_CANCEL,
2510 struct GNUNET_SETI_CancelMessage,
2511 NULL),
2512 GNUNET_MQ_handler_end ());
2513
2514
2515/* 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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2014, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Florian Dold
22 * @author Christian Grothoff
23 * @file seti/gnunet-service-seti_protocol.h
24 * @brief Peer-to-Peer messages for gnunet set
25 */
26#ifndef SETI_PROTOCOL_H
27#define SETI_PROTOCOL_H
28
29#include "platform.h"
30#include "gnunet_common.h"
31
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35struct OperationRequestMessage
36{
37 /**
38 * Type: #GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * For Intersection: my element count
44 */
45 uint32_t element_count GNUNET_PACKED;
46
47 /**
48 * Application-specific identifier of the request.
49 */
50 struct GNUNET_HashCode app_idX;
51
52 /* rest: optional message */
53};
54
55
56/**
57 * During intersection, the first (and possibly second) message
58 * send it the number of elements in the set, to allow the peers
59 * to decide who should start with the Bloom filter.
60 */
61struct IntersectionElementInfoMessage
62{
63 /**
64 * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO
65 */
66 struct GNUNET_MessageHeader header;
67
68 /**
69 * mutator used with this bloomfilter.
70 */
71 uint32_t sender_element_count GNUNET_PACKED;
72};
73
74
75/**
76 * Bloom filter messages exchanged for set intersection calculation.
77 */
78struct BFMessage
79{
80 /**
81 * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF
82 */
83 struct GNUNET_MessageHeader header;
84
85 /**
86 * Number of elements the sender still has in the set.
87 */
88 uint32_t sender_element_count GNUNET_PACKED;
89
90 /**
91 * XOR of all hashes over all elements remaining in the set.
92 * Used to determine termination.
93 */
94 struct GNUNET_HashCode element_xor_hash;
95
96 /**
97 * Mutator used with this bloomfilter.
98 */
99 uint32_t sender_mutator GNUNET_PACKED;
100
101 /**
102 * Total length of the bloomfilter data.
103 */
104 uint32_t bloomfilter_total_length GNUNET_PACKED;
105
106 /**
107 * Number of bits (k-value) used in encoding the bloomfilter.
108 */
109 uint32_t bits_per_element GNUNET_PACKED;
110
111 /**
112 * rest: the sender's bloomfilter
113 */
114};
115
116
117/**
118 * Last message, send to confirm the final set. Contains the element
119 * count as it is possible that the peer determined that we were done
120 * by getting the empty set, which in that case also needs to be
121 * communicated.
122 */
123struct IntersectionDoneMessage
124{
125 /**
126 * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE
127 */
128 struct GNUNET_MessageHeader header;
129
130 /**
131 * Final number of elements in intersection.
132 */
133 uint32_t final_element_count GNUNET_PACKED;
134
135 /**
136 * XOR of all hashes over all elements remaining in the set.
137 */
138 struct GNUNET_HashCode element_xor_hash;
139};
140
141
142GNUNET_NETWORK_STRUCT_END
143
144#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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/gnunet-seti-profiler.c
23 * @brief profiling tool for set intersection
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_statistics_service.h"
29#include "gnunet_seti_service.h"
30#include "gnunet_testbed_service.h"
31
32
33static int ret;
34
35static unsigned int num_a = 5;
36static unsigned int num_b = 5;
37static unsigned int num_c = 20;
38
39const static struct GNUNET_CONFIGURATION_Handle *config;
40
41struct SetInfo
42{
43 char *id;
44 struct GNUNET_SETI_Handle *set;
45 struct GNUNET_SETI_OperationHandle *oh;
46 struct GNUNET_CONTAINER_MultiHashMap *sent;
47 struct GNUNET_CONTAINER_MultiHashMap *received;
48 int done;
49} info1, info2;
50
51static struct GNUNET_CONTAINER_MultiHashMap *common_sent;
52
53static struct GNUNET_HashCode app_id;
54
55static struct GNUNET_PeerIdentity local_peer;
56
57static struct GNUNET_SETI_ListenHandle *set_listener;
58
59static unsigned int use_intersection;
60
61static unsigned int element_size = 32;
62
63/**
64 * Handle to the statistics service.
65 */
66static struct GNUNET_STATISTICS_Handle *statistics;
67
68/**
69 * The profiler will write statistics
70 * for all peers to the file with this name.
71 */
72static char *statistics_filename;
73
74/**
75 * The profiler will write statistics
76 * for all peers to this file.
77 */
78static FILE *statistics_file;
79
80
81static int
82map_remove_iterator (void *cls,
83 const struct GNUNET_HashCode *key,
84 void *value)
85{
86 struct GNUNET_CONTAINER_MultiHashMap *m = cls;
87 int ret;
88
89 GNUNET_assert (NULL != key);
90
91 ret = GNUNET_CONTAINER_multihashmap_remove_all (m, key);
92 if (GNUNET_OK != ret)
93 printf ("spurious element\n");
94 return GNUNET_YES;
95}
96
97
98/**
99 * Callback function to process statistic values.
100 *
101 * @param cls closure
102 * @param subsystem name of subsystem that created the statistic
103 * @param name the name of the datum
104 * @param value the current value
105 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
106 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
107 */
108static int
109statistics_result (void *cls,
110 const char *subsystem,
111 const char *name,
112 uint64_t value,
113 int is_persistent)
114{
115 if (NULL != statistics_file)
116 {
117 fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
118 long) value);
119 }
120 return GNUNET_OK;
121}
122
123
124static void
125statistics_done (void *cls,
126 int success)
127{
128 GNUNET_assert (GNUNET_YES == success);
129 if (NULL != statistics_file)
130 fclose (statistics_file);
131 GNUNET_SCHEDULER_shutdown ();
132}
133
134
135static void
136check_all_done (void)
137{
138 if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
139 return;
140
141 GNUNET_CONTAINER_multihashmap_iterate (info1.received, map_remove_iterator,
142 info2.sent);
143 GNUNET_CONTAINER_multihashmap_iterate (info2.received, map_remove_iterator,
144 info1.sent);
145
146 printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
147 info1.sent));
148 printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
149 info2.sent));
150
151 if (NULL == statistics_filename)
152 {
153 GNUNET_SCHEDULER_shutdown ();
154 return;
155 }
156
157 statistics_file = fopen (statistics_filename, "w");
158 GNUNET_STATISTICS_get (statistics, NULL, NULL,
159 &statistics_done,
160 &statistics_result, NULL);
161}
162
163
164static void
165set_result_cb (void *cls,
166 const struct GNUNET_SETI_Element *element,
167 uint64_t current_size,
168 enum GNUNET_SETI_Status status)
169{
170 struct SetInfo *info = cls;
171 struct GNUNET_HashCode hash;
172
173 GNUNET_assert (GNUNET_NO == info->done);
174 switch (status)
175 {
176 case GNUNET_SETI_STATUS_DONE:
177 info->done = GNUNET_YES;
178 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
179 "set intersection done\n");
180 check_all_done ();
181 info->oh = NULL;
182 return;
183 case GNUNET_SETI_STATUS_FAILURE:
184 info->oh = NULL;
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 "failure\n");
187 GNUNET_SCHEDULER_shutdown ();
188 return;
189 case GNUNET_SETI_STATUS_ADD_LOCAL:
190 GNUNET_CRYPTO_hash (element->data,
191 element->size,
192 &hash);
193 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
194 "set %s: keep element %s\n",
195 info->id,
196 GNUNET_h2s (&hash));
197 break;
198 case GNUNET_SETI_STATUS_DEL_LOCAL:
199 GNUNET_CRYPTO_hash (element->data,
200 element->size,
201 &hash);
202 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
203 "set %s: remove element %s\n",
204 info->id,
205 GNUNET_h2s (&hash));
206 return;
207 default:
208 GNUNET_assert (0);
209 }
210
211 if (element->size != element_size)
212 {
213 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
214 "wrong element size: %u, expected %u\n",
215 element->size,
216 (unsigned int) sizeof(struct GNUNET_HashCode));
217 GNUNET_assert (0);
218 }
219
220 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
221 "set %s: got element (%s)\n",
222 info->id, GNUNET_h2s (element->data));
223 GNUNET_assert (NULL != element->data);
224 {
225 struct GNUNET_HashCode data_hash;
226
227 GNUNET_CRYPTO_hash (element->data,
228 element_size,
229 &data_hash);
230 GNUNET_CONTAINER_multihashmap_put (info->received,
231 &data_hash,
232 NULL,
233 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
234 }
235}
236
237
238static void
239set_listen_cb (void *cls,
240 const struct GNUNET_PeerIdentity *other_peer,
241 const struct GNUNET_MessageHeader *context_msg,
242 struct GNUNET_SETI_Request *request)
243{
244 /* max. 1 option plus terminator */
245 struct GNUNET_SETI_Option opts[2] = { { 0 } };
246 unsigned int n_opts = 0;
247
248 if (NULL == request)
249 {
250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
251 "listener failed\n");
252 return;
253 }
254 GNUNET_assert (NULL == info2.oh);
255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
256 "set listen cb called\n");
257 if (use_intersection)
258 {
259 opts[n_opts++] = (struct GNUNET_SETI_Option) { .type =
260 GNUNET_SETI_OPTION_RETURN_INTERSECTION };
261 }
262 opts[n_opts].type = GNUNET_SETI_OPTION_END;
263 info2.oh = GNUNET_SETI_accept (request,
264 opts,
265 &set_result_cb,
266 &info2);
267 GNUNET_SETI_commit (info2.oh,
268 info2.set);
269}
270
271
272static int
273set_insert_iterator (void *cls,
274 const struct GNUNET_HashCode *key,
275 void *value)
276{
277 struct GNUNET_SETI_Handle *set = cls;
278 struct GNUNET_SETI_Element el;
279
280 el.element_type = 0;
281 el.data = value;
282 el.size = element_size;
283 GNUNET_SETI_add_element (set, &el, NULL, NULL);
284 return GNUNET_YES;
285}
286
287
288static void
289handle_shutdown (void *cls)
290{
291 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
292 "Shutting down set profiler\n");
293 if (NULL != set_listener)
294 {
295 GNUNET_SETI_listen_cancel (set_listener);
296 set_listener = NULL;
297 }
298 if (NULL != info1.oh)
299 {
300 GNUNET_SETI_operation_cancel (info1.oh);
301 info1.oh = NULL;
302 }
303 if (NULL != info2.oh)
304 {
305 GNUNET_SETI_operation_cancel (info2.oh);
306 info2.oh = NULL;
307 }
308 if (NULL != info1.set)
309 {
310 GNUNET_SETI_destroy (info1.set);
311 info1.set = NULL;
312 }
313 if (NULL != info2.set)
314 {
315 GNUNET_SETI_destroy (info2.set);
316 info2.set = NULL;
317 }
318 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
319}
320
321
322static void
323run (void *cls,
324 const struct GNUNET_CONFIGURATION_Handle *cfg,
325 struct GNUNET_TESTING_Peer *peer)
326{
327 unsigned int i;
328 struct GNUNET_HashCode hash;
329 /* max. 1 option plus terminator */
330 struct GNUNET_SETI_Option opts[2] = { { 0 } };
331 unsigned int n_opts = 0;
332
333 config = cfg;
334
335 GNUNET_assert (element_size > 0);
336
337 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer))
338 {
339 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
340 "could not retrieve host identity\n");
341 ret = 0;
342 return;
343 }
344 statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
345 GNUNET_SCHEDULER_add_shutdown (&handle_shutdown, NULL);
346 info1.id = "a";
347 info2.id = "b";
348 info1.sent = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
349 info2.sent = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
350 common_sent = GNUNET_CONTAINER_multihashmap_create (num_c + 1, GNUNET_NO);
351 info1.received = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
352 info2.received = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
353 for (i = 0; i < num_a; i++)
354 {
355 char *data = GNUNET_malloc (element_size);
356 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
357 GNUNET_CRYPTO_hash (data, element_size, &hash);
358 GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, data,
359 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
360 }
361
362 for (i = 0; i < num_b; i++)
363 {
364 char *data = GNUNET_malloc (element_size);
365 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
366 GNUNET_CRYPTO_hash (data, element_size, &hash);
367 GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, data,
368 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
369 }
370
371 for (i = 0; i < num_c; i++)
372 {
373 char *data = GNUNET_malloc (element_size);
374 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
375 GNUNET_CRYPTO_hash (data, element_size, &hash);
376 GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
377 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
378 }
379
380 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &app_id);
381
382 info1.set = GNUNET_SETI_create (config);
383 info2.set = GNUNET_SETI_create (config);
384 GNUNET_CONTAINER_multihashmap_iterate (info1.sent,
385 &set_insert_iterator,
386 info1.set);
387 GNUNET_CONTAINER_multihashmap_iterate (info2.sent,
388 &set_insert_iterator,
389 info2.set);
390 GNUNET_CONTAINER_multihashmap_iterate (common_sent,
391 &set_insert_iterator,
392 info1.set);
393 GNUNET_CONTAINER_multihashmap_iterate (common_sent,
394 &set_insert_iterator,
395 info2.set);
396
397 set_listener = GNUNET_SETI_listen (config,
398 &app_id,
399 &set_listen_cb,
400 NULL);
401 if (use_intersection)
402 {
403 opts[n_opts++] = (struct GNUNET_SETI_Option) { .type =
404 GNUNET_SETI_OPTION_RETURN_INTERSECTION };
405 }
406 opts[n_opts].type = GNUNET_SETI_OPTION_END;
407
408 info1.oh = GNUNET_SETI_prepare (&local_peer,
409 &app_id,
410 NULL,
411 opts,
412 set_result_cb,
413 &info1);
414 GNUNET_SETI_commit (info1.oh,
415 info1.set);
416 GNUNET_SETI_destroy (info1.set);
417 info1.set = NULL;
418}
419
420
421static void
422pre_run (void *cls,
423 char *const *args,
424 const char *cfgfile,
425 const struct GNUNET_CONFIGURATION_Handle *cfg)
426{
427 if (0 != GNUNET_TESTING_peer_run ("set-profiler",
428 cfgfile,
429 &run, NULL))
430 ret = 2;
431}
432
433
434int
435main (int argc, char **argv)
436{
437 struct GNUNET_GETOPT_CommandLineOption options[] = {
438 GNUNET_GETOPT_option_uint ('A',
439 "num-first",
440 NULL,
441 gettext_noop ("number of values"),
442 &num_a),
443 GNUNET_GETOPT_option_uint ('B',
444 "num-second",
445 NULL,
446 gettext_noop ("number of values"),
447 &num_b),
448 GNUNET_GETOPT_option_uint ('C',
449 "num-common",
450 NULL,
451 gettext_noop ("number of values"),
452 &num_c),
453 GNUNET_GETOPT_option_uint ('i',
454 "use-intersection",
455 NULL,
456 gettext_noop (
457 "return intersection instead of delta"),
458 &use_intersection),
459 GNUNET_GETOPT_option_uint ('w',
460 "element-size",
461 NULL,
462 gettext_noop ("element size"),
463 &element_size),
464 GNUNET_GETOPT_option_filename ('s',
465 "statistics",
466 "FILENAME",
467 gettext_noop ("write statistics to file"),
468 &statistics_filename),
469 GNUNET_GETOPT_OPTION_END
470 };
471
472 GNUNET_PROGRAM_run2 (argc, argv,
473 "gnunet-seti-profiler",
474 "help",
475 options,
476 &pre_run,
477 NULL,
478 GNUNET_YES);
479 return ret;
480}
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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file seti/plugin_block_seti_test.c
23 * @brief set test block, recognizes elements with non-zero first byte as invalid
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_block_plugin.h"
29#include "gnunet_block_group_lib.h"
30
31
32/**
33 * Function called to validate a reply or a request. For
34 * request evaluation, simply pass "NULL" for the reply_block.
35 *
36 * @param cls closure
37 * @param ctx block context
38 * @param type block type
39 * @param group block group to use
40 * @param eo control flags
41 * @param query original query (hash)
42 * @param xquery extrended query data (can be NULL, depending on type)
43 * @param xquery_size number of bytes in xquery
44 * @param reply_block response to validate
45 * @param reply_block_size number of bytes in reply block
46 * @return characterization of result
47 */
48static enum GNUNET_BLOCK_EvaluationResult
49block_plugin_seti_test_evaluate (void *cls,
50 struct GNUNET_BLOCK_Context *ctx,
51 enum GNUNET_BLOCK_Type type,
52 struct GNUNET_BLOCK_Group *group,
53 enum GNUNET_BLOCK_EvaluationOptions eo,
54 const struct GNUNET_HashCode *query,
55 const void *xquery,
56 size_t xquery_size,
57 const void *reply_block,
58 size_t reply_block_size)
59{
60 if ((NULL == reply_block) ||
61 (reply_block_size == 0) ||
62 (0 != ((char *) reply_block)[0]))
63 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
64 return GNUNET_BLOCK_EVALUATION_OK_MORE;
65}
66
67
68/**
69 * Function called to obtain the key for a block.
70 *
71 * @param cls closure
72 * @param type block type
73 * @param block block to get the key for
74 * @param block_size number of bytes in block
75 * @param key set to the key (query) for the given block
76 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
77 * (or if extracting a key from a block of this type does not work)
78 */
79static int
80block_plugin_seti_test_get_key (void *cls,
81 enum GNUNET_BLOCK_Type type,
82 const void *block,
83 size_t block_size,
84 struct GNUNET_HashCode *key)
85{
86 return GNUNET_SYSERR;
87}
88
89
90/**
91 * Entry point for the plugin.
92 */
93void *
94libgnunet_plugin_block_seti_test_init (void *cls)
95{
96 static enum GNUNET_BLOCK_Type types[] = {
97 GNUNET_BLOCK_TYPE_SETI_TEST,
98 GNUNET_BLOCK_TYPE_ANY /* end of list */
99 };
100 struct GNUNET_BLOCK_PluginFunctions *api;
101
102 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
103 api->evaluate = &block_plugin_seti_test_evaluate;
104 api->get_key = &block_plugin_seti_test_get_key;
105 api->types = types;
106 return api;
107}
108
109
110/**
111 * Exit point from the plugin.
112 */
113void *
114libgnunet_plugin_block_seti_test_done (void *cls)
115{
116 struct GNUNET_BLOCK_PluginFunctions *api = cls;
117
118 GNUNET_free (api);
119 return NULL;
120}
121
122
123/* 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 @@
1[seti]
2START_ON_DEMAND = @START_ON_DEMAND@
3@UNIXONLY@PORT = 2106
4HOSTNAME = localhost
5BINARY = gnunet-service-seti
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-seti.sock
9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES
11
12#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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2014, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file set/seti.h
22 * @brief messages used for the set intersection api
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#ifndef SETI_H
27#define SETI_H
28
29#include "platform.h"
30#include "gnunet_common.h"
31#include "gnunet_set_service.h"
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35/**
36 * Message sent by the client to the service to ask starting
37 * a new set to perform operations with.
38 */
39struct GNUNET_SETI_CreateMessage
40{
41 /**
42 * Type: #GNUNET_MESSAGE_TYPE_SETI_CREATE
43 */
44 struct GNUNET_MessageHeader header;
45};
46
47
48/**
49 * Message sent by the client to the service to start listening for
50 * incoming requests to perform a certain type of set operation for a
51 * certain type of application.
52 */
53struct GNUNET_SETI_ListenMessage
54{
55 /**
56 * Type: #GNUNET_MESSAGE_TYPE_SETI_LISTEN
57 */
58 struct GNUNET_MessageHeader header;
59
60 /**
61 * Operation type, values of `enum GNUNET_SETI_OperationType`
62 */
63 uint32_t operation GNUNET_PACKED;
64
65 /**
66 * application id
67 */
68 struct GNUNET_HashCode app_id;
69};
70
71
72/**
73 * Message sent by a listening client to the service to accept
74 * performing the operation with the other peer.
75 */
76struct GNUNET_SETI_AcceptMessage
77{
78 /**
79 * Type: #GNUNET_MESSAGE_TYPE_SETI_ACCEPT
80 */
81 struct GNUNET_MessageHeader header;
82
83 /**
84 * ID of the incoming request we want to accept.
85 */
86 uint32_t accept_reject_id GNUNET_PACKED;
87
88 /**
89 * Request ID to identify responses.
90 */
91 uint32_t request_id GNUNET_PACKED;
92
93 /**
94 * Return the intersection (1), instead of the elements to
95 * remove / the delta (0), in NBO.
96 */
97 uint32_t return_intersection;
98
99};
100
101
102/**
103 * Message sent by a listening client to the service to reject
104 * performing the operation with the other peer.
105 */
106struct GNUNET_SETI_RejectMessage
107{
108 /**
109 * Type: #GNUNET_MESSAGE_TYPE_SETI_REJECT
110 */
111 struct GNUNET_MessageHeader header;
112
113 /**
114 * ID of the incoming request we want to reject.
115 */
116 uint32_t accept_reject_id GNUNET_PACKED;
117};
118
119
120/**
121 * A request for an operation with another client.
122 */
123struct GNUNET_SETI_RequestMessage
124{
125 /**
126 * Type: #GNUNET_MESSAGE_TYPE_SETI_REQUEST.
127 */
128 struct GNUNET_MessageHeader header;
129
130 /**
131 * ID of the to identify the request when accepting or
132 * rejecting it.
133 */
134 uint32_t accept_id GNUNET_PACKED;
135
136 /**
137 * Identity of the requesting peer.
138 */
139 struct GNUNET_PeerIdentity peer_id;
140
141 /* rest: context message, that is, application-specific
142 message to convince listener to pick up */
143};
144
145
146/**
147 * Message sent by client to service to initiate a set operation as a
148 * client (not as listener). A set (which determines the operation
149 * type) must already exist in association with this client.
150 */
151struct GNUNET_SETI_EvaluateMessage
152{
153 /**
154 * Type: #GNUNET_MESSAGE_TYPE_SETI_EVALUATE
155 */
156 struct GNUNET_MessageHeader header;
157
158 /**
159 * Id of our set to evaluate, chosen implicitly by the client when it
160 * calls #GNUNET_SETI_commit().
161 */
162 uint32_t request_id GNUNET_PACKED;
163
164 /**
165 * Peer to evaluate the operation with
166 */
167 struct GNUNET_PeerIdentity target_peer;
168
169 /**
170 * Application id
171 */
172 struct GNUNET_HashCode app_id;
173
174 /**
175 * Return the intersection (1), instead of the elements to
176 * remove / the delta (0), in NBO.
177 */
178 uint32_t return_intersection;
179
180 /* rest: context message, that is, application-specific
181 message to convince listener to pick up */
182};
183
184
185/**
186 * Message sent by the service to the client to indicate an
187 * element that is removed (set intersection) or added
188 * (set union) or part of the final result, depending on
189 * options specified for the operation.
190 */
191struct GNUNET_SETI_ResultMessage
192{
193 /**
194 * Type: #GNUNET_MESSAGE_TYPE_SETI_RESULT
195 */
196 struct GNUNET_MessageHeader header;
197
198 /**
199 * Current set size.
200 */
201 uint64_t current_size;
202
203 /**
204 * id the result belongs to
205 */
206 uint32_t request_id GNUNET_PACKED;
207
208 /**
209 * Was the evaluation successful? Contains
210 * an `enum GNUNET_SETI_Status` in NBO.
211 */
212 uint16_t result_status GNUNET_PACKED;
213
214 /**
215 * Type of the element attachted to the message, if any.
216 */
217 uint16_t element_type GNUNET_PACKED;
218
219 /* rest: the actual element */
220};
221
222
223/**
224 * Message sent by client to the service to add an element to the set.
225 */
226struct GNUNET_SETI_ElementMessage
227{
228 /**
229 * Type: #GNUNET_MESSAGE_TYPE_SETI_ADD.
230 */
231 struct GNUNET_MessageHeader header;
232
233 /**
234 * Type of the element to add or remove.
235 */
236 uint16_t element_type GNUNET_PACKED;
237
238 /**
239 * For alignment, always zero.
240 */
241 uint16_t reserved GNUNET_PACKED;
242
243 /* rest: the actual element */
244};
245
246
247/**
248 * Sent to the service by the client
249 * in order to cancel a set operation.
250 */
251struct GNUNET_SETI_CancelMessage
252{
253 /**
254 * Type: #GNUNET_MESSAGE_TYPE_SETI_CANCEL
255 */
256 struct GNUNET_MessageHeader header;
257
258 /**
259 * ID of the request we want to cancel.
260 */
261 uint32_t request_id GNUNET_PACKED;
262};
263
264
265GNUNET_NETWORK_STRUCT_END
266
267#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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file seti/seti_api.c
22 * @brief api for the set service
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_protocols.h"
29#include "gnunet_seti_service.h"
30#include "seti.h"
31
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "seti-api", __VA_ARGS__)
34
35
36/**
37 * Opaque handle to a set.
38 */
39struct GNUNET_SETI_Handle
40{
41 /**
42 * Message queue for @e client.
43 */
44 struct GNUNET_MQ_Handle *mq;
45
46 /**
47 * Linked list of operations on the set.
48 */
49 struct GNUNET_SETI_OperationHandle *ops_head;
50
51 /**
52 * Linked list of operations on the set.
53 */
54 struct GNUNET_SETI_OperationHandle *ops_tail;
55
56 /**
57 * Configuration, needed when creating (lazy) copies.
58 */
59 const struct GNUNET_CONFIGURATION_Handle *cfg;
60
61 /**
62 * Should the set be destroyed once all operations are gone?
63 * #GNUNET_SYSERR if #GNUNET_SETI_destroy() must raise this flag,
64 * #GNUNET_YES if #GNUNET_SETI_destroy() did raise this flag.
65 */
66 int destroy_requested;
67
68 /**
69 * Has the set become invalid (e.g. service died)?
70 */
71 int invalid;
72
73 /**
74 * Both client and service count the number of iterators
75 * created so far to match replies with iterators.
76 */
77 uint16_t iteration_id;
78
79};
80
81
82/**
83 * Handle for a set operation request from another peer.
84 */
85struct GNUNET_SETI_Request
86{
87 /**
88 * Id of the request, used to identify the request when
89 * accepting/rejecting it.
90 */
91 uint32_t accept_id;
92
93 /**
94 * Has the request been accepted already?
95 * #GNUNET_YES/#GNUNET_NO
96 */
97 int accepted;
98};
99
100
101/**
102 * Handle to an operation. Only known to the service after committing
103 * the handle with a set.
104 */
105struct GNUNET_SETI_OperationHandle
106{
107 /**
108 * Function to be called when we have a result,
109 * or an error.
110 */
111 GNUNET_SETI_ResultIterator result_cb;
112
113 /**
114 * Closure for @e result_cb.
115 */
116 void *result_cls;
117
118 /**
119 * Local set used for the operation,
120 * NULL if no set has been provided by conclude yet.
121 */
122 struct GNUNET_SETI_Handle *set;
123
124 /**
125 * Message sent to the server on calling conclude,
126 * NULL if conclude has been called.
127 */
128 struct GNUNET_MQ_Envelope *conclude_mqm;
129
130 /**
131 * Address of the request if in the conclude message,
132 * used to patch the request id into the message when the set is known.
133 */
134 uint32_t *request_id_addr;
135
136 /**
137 * Handles are kept in a linked list.
138 */
139 struct GNUNET_SETI_OperationHandle *prev;
140
141 /**
142 * Handles are kept in a linked list.
143 */
144 struct GNUNET_SETI_OperationHandle *next;
145
146 /**
147 * Request ID to identify the operation within the set.
148 */
149 uint32_t request_id;
150
151 /**
152 * Should we return the resulting intersection (ADD) or
153 * the elements to remove (DEL)?
154 */
155 int return_intersection;
156};
157
158
159/**
160 * Opaque handle to a listen operation.
161 */
162struct GNUNET_SETI_ListenHandle
163{
164 /**
165 * Message queue for the client.
166 */
167 struct GNUNET_MQ_Handle*mq;
168
169 /**
170 * Configuration handle for the listener, stored
171 * here to be able to reconnect transparently on
172 * connection failure.
173 */
174 const struct GNUNET_CONFIGURATION_Handle *cfg;
175
176 /**
177 * Function to call on a new incoming request,
178 * or on error.
179 */
180 GNUNET_SETI_ListenCallback listen_cb;
181
182 /**
183 * Closure for @e listen_cb.
184 */
185 void *listen_cls;
186
187 /**
188 * Task for reconnecting when the listener fails.
189 */
190 struct GNUNET_SCHEDULER_Task *reconnect_task;
191
192 /**
193 * Application ID we listen for.
194 */
195 struct GNUNET_HashCode app_id;
196
197 /**
198 * Time to wait until we try to reconnect on failure.
199 */
200 struct GNUNET_TIME_Relative reconnect_backoff;
201
202};
203
204
205/**
206 * Check that the given @a msg is well-formed.
207 *
208 * @param cls closure
209 * @param msg message to check
210 * @return #GNUNET_OK if message is well-formed
211 */
212static int
213check_result (void *cls,
214 const struct GNUNET_SETI_ResultMessage *msg)
215{
216 /* minimum size was already checked, everything else is OK! */
217 return GNUNET_OK;
218}
219
220
221/**
222 * Handle result message for a set operation.
223 *
224 * @param cls the set
225 * @param mh the message
226 */
227static void
228handle_result (void *cls,
229 const struct GNUNET_SETI_ResultMessage *msg)
230{
231 struct GNUNET_SETI_Handle *set = cls;
232 struct GNUNET_SETI_OperationHandle *oh;
233 struct GNUNET_SETI_Element e;
234 enum GNUNET_SETI_Status result_status;
235 int destroy_set;
236
237 GNUNET_assert (NULL != set->mq);
238 result_status = (enum GNUNET_SETI_Status) ntohs (msg->result_status);
239 LOG (GNUNET_ERROR_TYPE_DEBUG,
240 "Got result message with status %d\n",
241 result_status);
242 oh = GNUNET_MQ_assoc_get (set->mq,
243 ntohl (msg->request_id));
244 if (NULL == oh)
245 {
246 /* 'oh' can be NULL if we canceled the operation, but the service
247 did not get the cancel message yet. */
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 "Ignoring result from canceled operation\n");
250 return;
251 }
252
253 switch (result_status)
254 {
255 case GNUNET_SETI_STATUS_ADD_LOCAL:
256 case GNUNET_SETI_STATUS_DEL_LOCAL:
257 e.data = &msg[1];
258 e.size = ntohs (msg->header.size)
259 - sizeof(struct GNUNET_SETI_ResultMessage);
260 e.element_type = ntohs (msg->element_type);
261 if (NULL != oh->result_cb)
262 oh->result_cb (oh->result_cls,
263 &e,
264 GNUNET_ntohll (msg->current_size),
265 result_status);
266 return;
267 case GNUNET_SETI_STATUS_FAILURE:
268 case GNUNET_SETI_STATUS_DONE:
269 GNUNET_MQ_assoc_remove (set->mq,
270 ntohl (msg->request_id));
271 GNUNET_CONTAINER_DLL_remove (set->ops_head,
272 set->ops_tail,
273 oh);
274 /* Need to do this calculation _before_ the result callback,
275 as IF the application still has a valid set handle, it
276 may trigger destruction of the set during the callback. */
277 destroy_set = (GNUNET_YES == set->destroy_requested) &&
278 (NULL == set->ops_head);
279 if (NULL != oh->result_cb)
280 {
281 oh->result_cb (oh->result_cls,
282 NULL,
283 GNUNET_ntohll (msg->current_size),
284 result_status);
285 }
286 else
287 {
288 LOG (GNUNET_ERROR_TYPE_DEBUG,
289 "No callback for final status\n");
290 }
291 if (destroy_set)
292 GNUNET_SETI_destroy (set);
293 GNUNET_free (oh);
294 return;
295 }
296}
297
298
299/**
300 * Destroy the given set operation.
301 *
302 * @param oh set operation to destroy
303 */
304static void
305set_operation_destroy (struct GNUNET_SETI_OperationHandle *oh)
306{
307 struct GNUNET_SETI_Handle *set = oh->set;
308 struct GNUNET_SETI_OperationHandle *h_assoc;
309
310 if (NULL != oh->conclude_mqm)
311 GNUNET_MQ_discard (oh->conclude_mqm);
312 /* is the operation already commited? */
313 if (NULL != set)
314 {
315 GNUNET_CONTAINER_DLL_remove (set->ops_head,
316 set->ops_tail,
317 oh);
318 h_assoc = GNUNET_MQ_assoc_remove (set->mq,
319 oh->request_id);
320 GNUNET_assert ((NULL == h_assoc) ||
321 (h_assoc == oh));
322 }
323 GNUNET_free (oh);
324}
325
326
327/**
328 * Cancel the given set operation. We need to send an explicit cancel
329 * message, as all operations one one set communicate using one
330 * handle.
331 *
332 * @param oh set operation to cancel
333 */
334void
335GNUNET_SETI_operation_cancel (struct GNUNET_SETI_OperationHandle *oh)
336{
337 struct GNUNET_SETI_Handle *set = oh->set;
338 struct GNUNET_SETI_CancelMessage *m;
339 struct GNUNET_MQ_Envelope *mqm;
340
341 LOG (GNUNET_ERROR_TYPE_DEBUG,
342 "Cancelling SET operation\n");
343 if (NULL != set)
344 {
345 mqm = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SETI_CANCEL);
346 m->request_id = htonl (oh->request_id);
347 GNUNET_MQ_send (set->mq, mqm);
348 }
349 set_operation_destroy (oh);
350 if ((NULL != set) &&
351 (GNUNET_YES == set->destroy_requested) &&
352 (NULL == set->ops_head))
353 {
354 LOG (GNUNET_ERROR_TYPE_DEBUG,
355 "Destroying set after operation cancel\n");
356 GNUNET_SETI_destroy (set);
357 }
358}
359
360
361/**
362 * We encountered an error communicating with the set service while
363 * performing a set operation. Report to the application.
364 *
365 * @param cls the `struct GNUNET_SETI_Handle`
366 * @param error error code
367 */
368static void
369handle_client_set_error (void *cls,
370 enum GNUNET_MQ_Error error)
371{
372 struct GNUNET_SETI_Handle *set = cls;
373
374 LOG (GNUNET_ERROR_TYPE_ERROR,
375 "Handling client set error %d\n",
376 error);
377 while (NULL != set->ops_head)
378 {
379 if ((NULL != set->ops_head->result_cb) &&
380 (GNUNET_NO == set->destroy_requested))
381 set->ops_head->result_cb (set->ops_head->result_cls,
382 NULL,
383 0,
384 GNUNET_SETI_STATUS_FAILURE);
385 set_operation_destroy (set->ops_head);
386 }
387 set->invalid = GNUNET_YES;
388}
389
390
391/**
392 * Create an empty set.
393 *
394 * @param cfg configuration to use for connecting to the
395 * set service
396 * @return a handle to the set
397 */
398struct GNUNET_SETI_Handle *
399GNUNET_SETI_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
400{
401 struct GNUNET_SETI_Handle *set = GNUNET_new (struct GNUNET_SETI_Handle);
402 struct GNUNET_MQ_MessageHandler mq_handlers[] = {
403 GNUNET_MQ_hd_var_size (result,
404 GNUNET_MESSAGE_TYPE_SETI_RESULT,
405 struct GNUNET_SETI_ResultMessage,
406 set),
407 GNUNET_MQ_handler_end ()
408 };
409 struct GNUNET_MQ_Envelope *mqm;
410 struct GNUNET_SETI_CreateMessage *create_msg;
411
412 set->cfg = cfg;
413 set->mq = GNUNET_CLIENT_connect (cfg,
414 "seti",
415 mq_handlers,
416 &handle_client_set_error,
417 set);
418 if (NULL == set->mq)
419 {
420 GNUNET_free (set);
421 return NULL;
422 }
423 LOG (GNUNET_ERROR_TYPE_DEBUG,
424 "Creating new intersection set\n");
425 mqm = GNUNET_MQ_msg (create_msg,
426 GNUNET_MESSAGE_TYPE_SETI_CREATE);
427 GNUNET_MQ_send (set->mq,
428 mqm);
429 return set;
430}
431
432
433/**
434 * Add an element to the given set. After the element has been added
435 * (in the sense of being transmitted to the set service), @a cont
436 * will be called. Multiple calls to GNUNET_SETI_add_element() can be
437 * queued.
438 *
439 * @param set set to add element to
440 * @param element element to add to the set
441 * @param cb continuation called after the element has been added
442 * @param cb_cls closure for @a cont
443 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
444 * set is invalid (e.g. the set service crashed)
445 */
446int
447GNUNET_SETI_add_element (struct GNUNET_SETI_Handle *set,
448 const struct GNUNET_SETI_Element *element,
449 GNUNET_SCHEDULER_TaskCallback cb,
450 void *cb_cls)
451{
452 struct GNUNET_MQ_Envelope *mqm;
453 struct GNUNET_SETI_ElementMessage *msg;
454
455 LOG (GNUNET_ERROR_TYPE_DEBUG,
456 "adding element of type %u to set %p\n",
457 (unsigned int) element->element_type,
458 set);
459 if (GNUNET_YES == set->invalid)
460 {
461 if (NULL != cb)
462 cb (cb_cls);
463 return GNUNET_SYSERR;
464 }
465 mqm = GNUNET_MQ_msg_extra (msg,
466 element->size,
467 GNUNET_MESSAGE_TYPE_SETI_ADD);
468 msg->element_type = htons (element->element_type);
469 GNUNET_memcpy (&msg[1],
470 element->data,
471 element->size);
472 GNUNET_MQ_notify_sent (mqm,
473 cb,
474 cb_cls);
475 GNUNET_MQ_send (set->mq,
476 mqm);
477 return GNUNET_OK;
478}
479
480
481/**
482 * Destroy the set handle if no operations are left, mark the set
483 * for destruction otherwise.
484 *
485 * @param set set handle to destroy
486 */
487void
488GNUNET_SETI_destroy (struct GNUNET_SETI_Handle *set)
489{
490 /* destroying set while iterator is active is currently
491 not supported; we should expand the API to allow
492 clients to explicitly cancel the iteration! */
493 if ((NULL != set->ops_head) ||
494 (GNUNET_SYSERR == set->destroy_requested))
495 {
496 LOG (GNUNET_ERROR_TYPE_DEBUG,
497 "Set operations are pending, delaying set destruction\n");
498 set->destroy_requested = GNUNET_YES;
499 return;
500 }
501 LOG (GNUNET_ERROR_TYPE_DEBUG,
502 "Really destroying set\n");
503 if (NULL != set->mq)
504 {
505 GNUNET_MQ_destroy (set->mq);
506 set->mq = NULL;
507 }
508 GNUNET_free (set);
509}
510
511
512/**
513 * Prepare a set operation to be evaluated with another peer.
514 * The evaluation will not start until the client provides
515 * a local set with #GNUNET_SETI_commit().
516 *
517 * @param other_peer peer with the other set
518 * @param app_id hash for the application using the set
519 * @param context_msg additional information for the request
520 * @param options options to use when processing the request
521 * @param result_cb called on error or success
522 * @param result_cls closure for @e result_cb
523 * @return a handle to cancel the operation
524 */
525struct GNUNET_SETI_OperationHandle *
526GNUNET_SETI_prepare (const struct GNUNET_PeerIdentity *other_peer,
527 const struct GNUNET_HashCode *app_id,
528 const struct GNUNET_MessageHeader *context_msg,
529 const struct GNUNET_SETI_Option options[],
530 GNUNET_SETI_ResultIterator result_cb,
531 void *result_cls)
532{
533 struct GNUNET_MQ_Envelope *mqm;
534 struct GNUNET_SETI_OperationHandle *oh;
535 struct GNUNET_SETI_EvaluateMessage *msg;
536
537 oh = GNUNET_new (struct GNUNET_SETI_OperationHandle);
538 oh->result_cb = result_cb;
539 oh->result_cls = result_cls;
540 mqm = GNUNET_MQ_msg_nested_mh (msg,
541 GNUNET_MESSAGE_TYPE_SETI_EVALUATE,
542 context_msg);
543 msg->app_id = *app_id;
544 msg->target_peer = *other_peer;
545 for (const struct GNUNET_SETI_Option *opt = options;
546 GNUNET_SETI_OPTION_END != opt->type;
547 opt++)
548 {
549 switch (opt->type)
550 {
551 case GNUNET_SETI_OPTION_RETURN_INTERSECTION:
552 msg->return_intersection = htonl (GNUNET_YES);
553 break;
554 default:
555 LOG (GNUNET_ERROR_TYPE_ERROR,
556 "Option with type %d not recognized\n",
557 (int) opt->type);
558 }
559 }
560 oh->conclude_mqm = mqm;
561 oh->request_id_addr = &msg->request_id;
562 return oh;
563}
564
565
566/**
567 * Connect to the set service in order to listen for requests.
568 *
569 * @param cls the `struct GNUNET_SETI_ListenHandle *` to connect
570 */
571static void
572listen_connect (void *cls);
573
574
575/**
576 * Check validity of request message for a listen operation
577 *
578 * @param cls the listen handle
579 * @param msg the message
580 * @return #GNUNET_OK if the message is well-formed
581 */
582static int
583check_request (void *cls,
584 const struct GNUNET_SETI_RequestMessage *msg)
585{
586 const struct GNUNET_MessageHeader *context_msg;
587
588 if (ntohs (msg->header.size) == sizeof(*msg))
589 return GNUNET_OK; /* no context message is OK */
590 context_msg = GNUNET_MQ_extract_nested_mh (msg);
591 if (NULL == context_msg)
592 {
593 /* malformed context message is NOT ok */
594 GNUNET_break_op (0);
595 return GNUNET_SYSERR;
596 }
597 return GNUNET_OK;
598}
599
600
601/**
602 * Handle request message for a listen operation
603 *
604 * @param cls the listen handle
605 * @param msg the message
606 */
607static void
608handle_request (void *cls,
609 const struct GNUNET_SETI_RequestMessage *msg)
610{
611 struct GNUNET_SETI_ListenHandle *lh = cls;
612 struct GNUNET_SETI_Request req;
613 const struct GNUNET_MessageHeader *context_msg;
614 struct GNUNET_MQ_Envelope *mqm;
615 struct GNUNET_SETI_RejectMessage *rmsg;
616
617 LOG (GNUNET_ERROR_TYPE_DEBUG,
618 "Processing incoming operation request with id %u\n",
619 ntohl (msg->accept_id));
620 /* we got another valid request => reset the backoff */
621 lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
622 req.accept_id = ntohl (msg->accept_id);
623 req.accepted = GNUNET_NO;
624 context_msg = GNUNET_MQ_extract_nested_mh (msg);
625 /* calling #GNUNET_SETI_accept() in the listen cb will set req->accepted */
626 lh->listen_cb (lh->listen_cls,
627 &msg->peer_id,
628 context_msg,
629 &req);
630 if (GNUNET_YES == req.accepted)
631 return; /* the accept-case is handled in #GNUNET_SETI_accept() */
632 LOG (GNUNET_ERROR_TYPE_DEBUG,
633 "Rejected request %u\n",
634 ntohl (msg->accept_id));
635 mqm = GNUNET_MQ_msg (rmsg,
636 GNUNET_MESSAGE_TYPE_SETI_REJECT);
637 rmsg->accept_reject_id = msg->accept_id;
638 GNUNET_MQ_send (lh->mq,
639 mqm);
640}
641
642
643/**
644 * Our connection with the set service encountered an error,
645 * re-initialize with exponential back-off.
646 *
647 * @param cls the `struct GNUNET_SETI_ListenHandle *`
648 * @param error reason for the disconnect
649 */
650static void
651handle_client_listener_error (void *cls,
652 enum GNUNET_MQ_Error error)
653{
654 struct GNUNET_SETI_ListenHandle *lh = cls;
655
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "Listener broke down (%d), re-connecting\n",
658 (int) error);
659 GNUNET_MQ_destroy (lh->mq);
660 lh->mq = NULL;
661 lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff,
662 &listen_connect,
663 lh);
664 lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff);
665}
666
667
668/**
669 * Connect to the set service in order to listen for requests.
670 *
671 * @param cls the `struct GNUNET_SETI_ListenHandle *` to connect
672 */
673static void
674listen_connect (void *cls)
675{
676 struct GNUNET_SETI_ListenHandle *lh = cls;
677 struct GNUNET_MQ_MessageHandler mq_handlers[] = {
678 GNUNET_MQ_hd_var_size (request,
679 GNUNET_MESSAGE_TYPE_SETI_REQUEST,
680 struct GNUNET_SETI_RequestMessage,
681 lh),
682 GNUNET_MQ_handler_end ()
683 };
684 struct GNUNET_MQ_Envelope *mqm;
685 struct GNUNET_SETI_ListenMessage *msg;
686
687 lh->reconnect_task = NULL;
688 GNUNET_assert (NULL == lh->mq);
689 lh->mq = GNUNET_CLIENT_connect (lh->cfg,
690 "seti",
691 mq_handlers,
692 &handle_client_listener_error,
693 lh);
694 if (NULL == lh->mq)
695 return;
696 mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SETI_LISTEN);
697 msg->app_id = lh->app_id;
698 GNUNET_MQ_send (lh->mq,
699 mqm);
700}
701
702
703/**
704 * Wait for set operation requests for the given application id
705 *
706 * @param cfg configuration to use for connecting to
707 * the set service, needs to be valid for the lifetime of the listen handle
708 * @param app_id id of the application that handles set operation requests
709 * @param listen_cb called for each incoming request matching the operation
710 * and application id
711 * @param listen_cls handle for @a listen_cb
712 * @return a handle that can be used to cancel the listen operation
713 */
714struct GNUNET_SETI_ListenHandle *
715GNUNET_SETI_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
716 const struct GNUNET_HashCode *app_id,
717 GNUNET_SETI_ListenCallback listen_cb,
718 void *listen_cls)
719{
720 struct GNUNET_SETI_ListenHandle *lh;
721
722 LOG (GNUNET_ERROR_TYPE_DEBUG,
723 "Starting listener for app %s\n",
724 GNUNET_h2s (app_id));
725 lh = GNUNET_new (struct GNUNET_SETI_ListenHandle);
726 lh->listen_cb = listen_cb;
727 lh->listen_cls = listen_cls;
728 lh->cfg = cfg;
729 lh->app_id = *app_id;
730 lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
731 listen_connect (lh);
732 if (NULL == lh->mq)
733 {
734 GNUNET_free (lh);
735 return NULL;
736 }
737 return lh;
738}
739
740
741/**
742 * Cancel the given listen operation.
743 *
744 * @param lh handle for the listen operation
745 */
746void
747GNUNET_SETI_listen_cancel (struct GNUNET_SETI_ListenHandle *lh)
748{
749 LOG (GNUNET_ERROR_TYPE_DEBUG,
750 "Canceling listener %s\n",
751 GNUNET_h2s (&lh->app_id));
752 if (NULL != lh->mq)
753 {
754 GNUNET_MQ_destroy (lh->mq);
755 lh->mq = NULL;
756 }
757 if (NULL != lh->reconnect_task)
758 {
759 GNUNET_SCHEDULER_cancel (lh->reconnect_task);
760 lh->reconnect_task = NULL;
761 }
762 GNUNET_free (lh);
763}
764
765
766/**
767 * Accept a request we got via #GNUNET_SETI_listen. Must be called during
768 * #GNUNET_SETI_listen, as the 'struct GNUNET_SETI_Request' becomes invalid
769 * afterwards.
770 * Call #GNUNET_SETI_commit to provide the local set to use for the operation,
771 * and to begin the exchange with the remote peer.
772 *
773 * @param request request to accept
774 * @param options options to use when processing the request
775 * @param result_cb callback for the results
776 * @param result_cls closure for @a result_cb
777 * @return a handle to cancel the operation
778 */
779struct GNUNET_SETI_OperationHandle *
780GNUNET_SETI_accept (struct GNUNET_SETI_Request *request,
781 const struct GNUNET_SETI_Option options[],
782 GNUNET_SETI_ResultIterator result_cb,
783 void *result_cls)
784{
785 struct GNUNET_MQ_Envelope *mqm;
786 struct GNUNET_SETI_OperationHandle *oh;
787 struct GNUNET_SETI_AcceptMessage *msg;
788
789 GNUNET_assert (GNUNET_NO == request->accepted);
790 LOG (GNUNET_ERROR_TYPE_DEBUG,
791 "Client accepts set intersection operation with id %u\n",
792 request->accept_id);
793 request->accepted = GNUNET_YES;
794 mqm = GNUNET_MQ_msg (msg,
795 GNUNET_MESSAGE_TYPE_SETI_ACCEPT);
796 msg->accept_reject_id = htonl (request->accept_id);
797 oh = GNUNET_new (struct GNUNET_SETI_OperationHandle);
798 oh->result_cb = result_cb;
799 oh->result_cls = result_cls;
800 oh->conclude_mqm = mqm;
801 oh->request_id_addr = &msg->request_id;
802 for (const struct GNUNET_SETI_Option *opt = options;
803 GNUNET_SETI_OPTION_END != opt->type;
804 opt++)
805 {
806 switch (opt->type)
807 {
808 case GNUNET_SETI_OPTION_RETURN_INTERSECTION:
809 oh->return_intersection = GNUNET_YES;
810 msg->return_intersection = htonl (GNUNET_YES);
811 break;
812 default:
813 LOG (GNUNET_ERROR_TYPE_ERROR,
814 "Option with type %d not recognized\n",
815 (int) opt->type);
816 }
817 }
818 return oh;
819}
820
821
822/**
823 * Commit a set to be used with a set operation.
824 * This function is called once we have fully constructed
825 * the set that we want to use for the operation. At this
826 * time, the P2P protocol can then begin to exchange the
827 * set information and call the result callback with the
828 * result information.
829 *
830 * @param oh handle to the set operation
831 * @param set the set to use for the operation
832 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
833 * set is invalid (e.g. the set service crashed)
834 */
835int
836GNUNET_SETI_commit (struct GNUNET_SETI_OperationHandle *oh,
837 struct GNUNET_SETI_Handle *set)
838{
839 if (NULL != oh->set)
840 {
841 /* Some other set was already committed for this
842 * operation, there is a logic bug in the client of this API */
843 GNUNET_break (0);
844 return GNUNET_OK;
845 }
846 GNUNET_assert (NULL != set);
847 if (GNUNET_YES == set->invalid)
848 return GNUNET_SYSERR;
849 LOG (GNUNET_ERROR_TYPE_DEBUG,
850 "Client commits to SET\n");
851 GNUNET_assert (NULL != oh->conclude_mqm);
852 oh->set = set;
853 GNUNET_CONTAINER_DLL_insert (set->ops_head,
854 set->ops_tail,
855 oh);
856 oh->request_id = GNUNET_MQ_assoc_add (set->mq,
857 oh);
858 *oh->request_id_addr = htonl (oh->request_id);
859 GNUNET_MQ_send (set->mq,
860 oh->conclude_mqm);
861 oh->conclude_mqm = NULL;
862 oh->request_id_addr = NULL;
863 return GNUNET_OK;
864}
865
866
867/**
868 * Hash a set element.
869 *
870 * @param element the element that should be hashed
871 * @param[out] ret_hash a pointer to where the hash of @a element
872 * should be stored
873 */
874void
875GNUNET_SETI_element_hash (const struct GNUNET_SETI_Element *element,
876 struct GNUNET_HashCode *ret_hash)
877{
878 struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
879
880 /* It's not guaranteed that the element data is always after the element header,
881 so we need to hash the chunks separately. */
882 GNUNET_CRYPTO_hash_context_read (ctx,
883 &element->size,
884 sizeof(uint16_t));
885 GNUNET_CRYPTO_hash_context_read (ctx,
886 &element->element_type,
887 sizeof(uint16_t));
888 GNUNET_CRYPTO_hash_context_read (ctx,
889 element->data,
890 element->size);
891 GNUNET_CRYPTO_hash_context_finish (ctx,
892 ret_hash);
893}
894
895
896/* 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 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[PATHS]
4GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-set/
5
6[seti]
7START_ON_DEMAND = YES
8#PREFIX = valgrind --leak-check=full
9#PREFIX = gdbserver :1234
10OPTIONS = -L INFO
11
12[transport]
13PLUGINS = unix
14OPTIONS = -LERROR
15
16[nat]
17RETURN_LOCAL_ADDRESSES = YES
18DISABLEV6 = YES
19USE_LOCALADDR = YES
20
21[peerinfo]
22NO_IO = YES
23
24[nat]
25# Use addresses from the local network interfaces (inluding loopback, but also others)
26USE_LOCALADDR = YES
27
28# Disable IPv6 support
29DISABLEV6 = NO
30
31# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
32RETURN_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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2014, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/test_seti_api.c
23 * @brief testcase for full result mode of the intersection set operation
24 * @author Christian Fuchs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_seti_service.h"
31
32
33static int ret;
34
35static struct GNUNET_PeerIdentity local_id;
36
37static struct GNUNET_HashCode app_id;
38
39static struct GNUNET_SETI_Handle *set1;
40
41static struct GNUNET_SETI_Handle *set2;
42
43static struct GNUNET_SETI_ListenHandle *listen_handle;
44
45static const struct GNUNET_CONFIGURATION_Handle *config;
46
47static struct GNUNET_SCHEDULER_Task *tt;
48
49static struct GNUNET_SETI_OperationHandle *oh1;
50
51static struct GNUNET_SETI_OperationHandle *oh2;
52
53
54static void
55result_cb_set1 (void *cls,
56 const struct GNUNET_SETI_Element *element,
57 uint64_t current_size,
58 enum GNUNET_SETI_Status status)
59{
60 static int count;
61
62 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
63 "Processing result set 1 (%d)\n",
64 status);
65 switch (status)
66 {
67 case GNUNET_SETI_STATUS_ADD_LOCAL:
68 count++;
69 break;
70 case GNUNET_SETI_STATUS_FAILURE:
71 oh1 = NULL;
72 ret = 1;
73 break;
74 case GNUNET_SETI_STATUS_DONE:
75 oh1 = NULL;
76 GNUNET_assert (1 == count);
77 GNUNET_SETI_destroy (set1);
78 set1 = NULL;
79 if (NULL == set2)
80 GNUNET_SCHEDULER_shutdown ();
81 break;
82
83 default:
84 GNUNET_assert (0);
85 }
86}
87
88
89static void
90result_cb_set2 (void *cls,
91 const struct GNUNET_SETI_Element *element,
92 uint64_t current_size,
93 enum GNUNET_SETI_Status status)
94{
95 static int count;
96
97 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
98 "Processing result set 2 (%d)\n",
99 status);
100 switch (status)
101 {
102 case GNUNET_SETI_STATUS_ADD_LOCAL:
103 count++;
104 break;
105 case GNUNET_SETI_STATUS_FAILURE:
106 oh2 = NULL;
107 ret = 1;
108 break;
109 case GNUNET_SETI_STATUS_DONE:
110 oh2 = NULL;
111 GNUNET_break (1 == count);
112 if (1 != count)
113 ret |= 2;
114 GNUNET_SETI_destroy (set2);
115 set2 = NULL;
116 if (NULL == set1)
117 GNUNET_SCHEDULER_shutdown ();
118 break;
119 case GNUNET_SETI_STATUS_DEL_LOCAL:
120 /* unexpected! */
121 ret = 1;
122 break;
123 }
124}
125
126
127static void
128listen_cb (void *cls,
129 const struct GNUNET_PeerIdentity *other_peer,
130 const struct GNUNET_MessageHeader *context_msg,
131 struct GNUNET_SETI_Request *request)
132{
133 struct GNUNET_SETI_Option opts[] = {
134 { .type = GNUNET_SETI_OPTION_RETURN_INTERSECTION },
135 { .type = GNUNET_SETI_OPTION_END }
136 };
137
138 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
139 "starting intersection by accepting and committing\n");
140 GNUNET_assert (NULL != context_msg);
141 GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
142 oh2 = GNUNET_SETI_accept (request,
143 opts,
144 &result_cb_set2,
145 NULL);
146 GNUNET_SETI_commit (oh2,
147 set2);
148}
149
150
151/**
152 * Start the set operation.
153 *
154 * @param cls closure, unused
155 */
156static void
157start (void *cls)
158{
159 struct GNUNET_MessageHeader context_msg;
160 struct GNUNET_SETI_Option opts[] = {
161 { .type = GNUNET_SETI_OPTION_RETURN_INTERSECTION },
162 { .type = GNUNET_SETI_OPTION_END }
163 };
164
165 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
166 "starting listener\n");
167 context_msg.size = htons (sizeof (context_msg));
168 context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
169 listen_handle = GNUNET_SETI_listen (config,
170 &app_id,
171 &listen_cb,
172 NULL);
173 oh1 = GNUNET_SETI_prepare (&local_id,
174 &app_id,
175 &context_msg,
176 opts,
177 &result_cb_set1,
178 NULL);
179 GNUNET_SETI_commit (oh1,
180 set1);
181}
182
183
184/**
185 * Initialize the second set, continue
186 *
187 * @param cls closure, unused
188 */
189static void
190init_set2 (void *cls)
191{
192 struct GNUNET_SETI_Element element;
193
194 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
195 "initializing set 2\n");
196 element.element_type = 0;
197 element.data = "hello";
198 element.size = strlen (element.data);
199 GNUNET_SETI_add_element (set2,
200 &element,
201 NULL,
202 NULL);
203 element.data = "quux";
204 element.size = strlen (element.data);
205 GNUNET_SETI_add_element (set2,
206 &element,
207 NULL,
208 NULL);
209 element.data = "baz";
210 element.size = strlen (element.data);
211 GNUNET_SETI_add_element (set2,
212 &element,
213 &start,
214 NULL);
215}
216
217
218/**
219 * Initialize the first set, continue.
220 */
221static void
222init_set1 (void)
223{
224 struct GNUNET_SETI_Element element;
225
226 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
227 "initializing set 1\n");
228 element.element_type = 0;
229 element.data = "hello";
230 element.size = strlen (element.data);
231 GNUNET_SETI_add_element (set1,
232 &element,
233 NULL,
234 NULL);
235 element.data = "bar";
236 element.size = strlen (element.data);
237 GNUNET_SETI_add_element (set1,
238 &element,
239 &init_set2,
240 NULL);
241}
242
243
244/**
245 * Function run on shutdown.
246 *
247 * @param cls closure
248 */
249static void
250do_shutdown (void *cls)
251{
252 if (NULL != tt)
253 {
254 GNUNET_SCHEDULER_cancel (tt);
255 tt = NULL;
256 }
257 if (NULL != oh1)
258 {
259 GNUNET_SETI_operation_cancel (oh1);
260 oh1 = NULL;
261 }
262 if (NULL != oh2)
263 {
264 GNUNET_SETI_operation_cancel (oh2);
265 oh2 = NULL;
266 }
267 if (NULL != set1)
268 {
269 GNUNET_SETI_destroy (set1);
270 set1 = NULL;
271 }
272 if (NULL != set2)
273 {
274 GNUNET_SETI_destroy (set2);
275 set2 = NULL;
276 }
277 if (NULL != listen_handle)
278 {
279 GNUNET_SETI_listen_cancel (listen_handle);
280 listen_handle = NULL;
281 }
282}
283
284
285/**
286 * Function run on timeout.
287 *
288 * @param cls closure
289 */
290static void
291timeout_fail (void *cls)
292{
293 tt = NULL;
294 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
295 "Testcase failed with timeout\n");
296 GNUNET_SCHEDULER_shutdown ();
297 ret = 1;
298}
299
300
301/**
302 * Signature of the 'main' function for a (single-peer) testcase that
303 * is run using 'GNUNET_TESTING_peer_run'.
304 *
305 * @param cls closure
306 * @param cfg configuration of the peer that was started
307 * @param peer identity of the peer that was created
308 */
309static void
310run (void *cls,
311 const struct GNUNET_CONFIGURATION_Handle *cfg,
312 struct GNUNET_TESTING_Peer *peer)
313{
314 config = cfg;
315 GNUNET_TESTING_peer_get_identity (peer,
316 &local_id);
317 tt = GNUNET_SCHEDULER_add_delayed (
318 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
319 5),
320 &timeout_fail,
321 NULL);
322 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
323 NULL);
324
325 set1 = GNUNET_SETI_create (cfg);
326 set2 = GNUNET_SETI_create (cfg);
327 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
328 &app_id);
329
330 /* test the real set reconciliation */
331 init_set1 ();
332}
333
334
335int
336main (int argc,
337 char **argv)
338{
339 if (0 != GNUNET_TESTING_peer_run ("test_seti_api",
340 "test_seti.conf",
341 &run,
342 NULL))
343 return 1;
344 return ret;
345}
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 @@
1gnunet-setu-profiler
2gnunet-service-setu
3gnunet-setu-ibf-profiler
4test_setu_api
5test_setu_copy
6test_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 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4pkgcfgdir= $(pkgdatadir)/config.d/
5
6libexecdir= $(pkglibdir)/libexec/
7
8plugindir = $(libdir)/gnunet
9
10pkgcfg_DATA = \
11 setu.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = -fprofile-arcs -ftest-coverage
15endif
16
17if HAVE_TESTING
18bin_PROGRAMS = \
19 gnunet-setu-profiler
20
21noinst_PROGRAMS = \
22 gnunet-setu-ibf-profiler
23endif
24
25libexec_PROGRAMS = \
26 gnunet-service-setu
27
28lib_LTLIBRARIES = \
29 libgnunetsetu.la
30
31gnunet_setu_profiler_SOURCES = \
32 gnunet-setu-profiler.c
33gnunet_setu_profiler_LDADD = \
34 $(top_builddir)/src/util/libgnunetutil.la \
35 $(top_builddir)/src/statistics/libgnunetstatistics.la \
36 libgnunetsetu.la \
37 $(top_builddir)/src/testing/libgnunettesting.la \
38 $(GN_LIBINTL)
39
40
41gnunet_setu_ibf_profiler_SOURCES = \
42 gnunet-setu-ibf-profiler.c \
43 ibf.c
44gnunet_setu_ibf_profiler_LDADD = \
45 $(top_builddir)/src/util/libgnunetutil.la \
46 $(GN_LIBINTL)
47
48gnunet_service_setu_SOURCES = \
49 gnunet-service-setu.c gnunet-service-setu.h \
50 ibf.c ibf.h \
51 gnunet-service-setu_strata_estimator.c gnunet-service-setu_strata_estimator.h \
52 gnunet-service-setu_protocol.h
53gnunet_service_setu_LDADD = \
54 $(top_builddir)/src/util/libgnunetutil.la \
55 $(top_builddir)/src/statistics/libgnunetstatistics.la \
56 $(top_builddir)/src/core/libgnunetcore.la \
57 $(top_builddir)/src/cadet/libgnunetcadet.la \
58 $(top_builddir)/src/block/libgnunetblock.la \
59 libgnunetsetu.la \
60 $(GN_LIBINTL)
61
62libgnunetsetu_la_SOURCES = \
63 setu_api.c setu.h
64libgnunetsetu_la_LIBADD = \
65 $(top_builddir)/src/util/libgnunetutil.la \
66 $(LTLIBINTL)
67libgnunetsetu_la_LDFLAGS = \
68 $(GN_LIB_LDFLAGS)
69
70if HAVE_TESTING
71check_PROGRAMS = \
72 test_setu_api
73endif
74
75if ENABLE_TEST_RUN
76AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
77TESTS = $(check_PROGRAMS)
78endif
79
80test_setu_api_SOURCES = \
81 test_setu_api.c
82test_setu_api_LDADD = \
83 $(top_builddir)/src/util/libgnunetutil.la \
84 $(top_builddir)/src/testing/libgnunettesting.la \
85 libgnunetsetu.la
86
87plugin_LTLIBRARIES = \
88 libgnunet_plugin_block_setu_test.la
89
90libgnunet_plugin_block_setu_test_la_SOURCES = \
91 plugin_block_setu_test.c
92libgnunet_plugin_block_setu_test_la_LIBADD = \
93 $(top_builddir)/src/block/libgnunetblock.la \
94 $(top_builddir)/src/block/libgnunetblockgroup.la \
95 $(top_builddir)/src/util/libgnunetutil.la \
96 $(LTLIBINTL)
97libgnunet_plugin_block_setu_test_la_LDFLAGS = \
98 $(GN_PLUGIN_LDFLAGS)
99
100
101EXTRA_DIST = \
102 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 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013-2017, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file setu/gnunet-service-setu.c
22 * @brief set union operation
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_statistics_service.h"
29#include "ibf.h"
30#include "gnunet_protocols.h"
31#include "gnunet_applications.h"
32#include "gnunet_cadet_service.h"
33#include "gnunet-service-setu_strata_estimator.h"
34#include "gnunet-service-setu_protocol.h"
35#include "gnunet_statistics_service.h"
36#include <gcrypt.h>
37#include "gnunet_setu_service.h"
38#include "setu.h"
39
40#define LOG(kind, ...) GNUNET_log_from (kind, "setu", __VA_ARGS__)
41
42/**
43 * How long do we hold on to an incoming channel if there is
44 * no local listener before giving up?
45 */
46#define INCOMING_CHANNEL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
47
48/**
49 * Number of IBFs in a strata estimator.
50 */
51#define SE_STRATA_COUNT 32
52
53/**
54 * Size of the IBFs in the strata estimator.
55 */
56#define SE_IBF_SIZE 80
57
58/**
59 * The hash num parameter for the difference digests and strata estimators.
60 */
61#define SE_IBF_HASH_NUM 4
62
63/**
64 * Number of buckets that can be transmitted in one message.
65 */
66#define MAX_BUCKETS_PER_MESSAGE ((1 << 15) / IBF_BUCKET_SIZE)
67
68/**
69 * The maximum size of an ibf we use is 2^(MAX_IBF_ORDER).
70 * Choose this value so that computing the IBF is still cheaper
71 * than transmitting all values.
72 */
73#define MAX_IBF_ORDER (20)
74
75/**
76 * Number of buckets used in the ibf per estimated
77 * difference.
78 */
79#define IBF_ALPHA 4
80
81
82/**
83 * Current phase we are in for a union operation.
84 */
85enum UnionOperationPhase
86{
87 /**
88 * We sent the request message, and expect a strata estimator.
89 */
90 PHASE_EXPECT_SE,
91
92 /**
93 * We sent the strata estimator, and expect an IBF. This phase is entered once
94 * upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS.
95 *
96 * XXX: could use better wording.
97 * XXX: repurposed to also expect a "request full set" message, should be renamed
98 *
99 * After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS
100 */
101 PHASE_EXPECT_IBF,
102
103 /**
104 * Continuation for multi part IBFs.
105 */
106 PHASE_EXPECT_IBF_CONT,
107
108 /**
109 * We are decoding an IBF.
110 */
111 PHASE_INVENTORY_ACTIVE,
112
113 /**
114 * The other peer is decoding the IBF we just sent.
115 */
116 PHASE_INVENTORY_PASSIVE,
117
118 /**
119 * The protocol is almost finished, but we still have to flush our message
120 * queue and/or expect some elements.
121 */
122 PHASE_FINISH_CLOSING,
123
124 /**
125 * In the penultimate phase, we wait until all our demands are satisfied.
126 * Then we send a done message, and wait for another done message.
127 */
128 PHASE_FINISH_WAITING,
129
130 /**
131 * In the ultimate phase, we wait until our demands are satisfied and then
132 * quit (sending another DONE message).
133 */
134 PHASE_DONE,
135
136 /**
137 * After sending the full set, wait for responses with the elements
138 * that the local peer is missing.
139 */
140 PHASE_FULL_SENDING,
141};
142
143
144/**
145 * Information about an element element in the set. All elements are
146 * stored in a hash-table from their hash-code to their `struct
147 * Element`, so that the remove and add operations are reasonably
148 * fast.
149 */
150struct ElementEntry
151{
152 /**
153 * The actual element. The data for the element
154 * should be allocated at the end of this struct.
155 */
156 struct GNUNET_SETU_Element element;
157
158 /**
159 * Hash of the element. For set union: Will be used to derive the
160 * different IBF keys for different salts.
161 */
162 struct GNUNET_HashCode element_hash;
163
164 /**
165 * First generation that includes this element.
166 */
167 unsigned int generation;
168
169 /**
170 * #GNUNET_YES if the element is a remote element, and does not belong
171 * to the operation's set.
172 */
173 int remote;
174};
175
176
177/**
178 * A listener is inhabited by a client, and waits for evaluation
179 * requests from remote peers.
180 */
181struct Listener;
182
183
184/**
185 * A set that supports a specific operation with other peers.
186 */
187struct Set;
188
189
190/**
191 * State we keep per client.
192 */
193struct ClientState
194{
195 /**
196 * Set, if associated with the client, otherwise NULL.
197 */
198 struct Set *set;
199
200 /**
201 * Listener, if associated with the client, otherwise NULL.
202 */
203 struct Listener *listener;
204
205 /**
206 * Client handle.
207 */
208 struct GNUNET_SERVICE_Client *client;
209
210 /**
211 * Message queue.
212 */
213 struct GNUNET_MQ_Handle *mq;
214};
215
216
217/**
218 * Operation context used to execute a set operation.
219 */
220struct Operation
221{
222
223 /**
224 * The identity of the requesting peer. Needs to
225 * be stored here as the op spec might not have been created yet.
226 */
227 struct GNUNET_PeerIdentity peer;
228
229 /**
230 * Initial size of our set, just before the operation started.
231 */
232 uint64_t initial_size;
233
234 /**
235 * Kept in a DLL of the listener, if @e listener is non-NULL.
236 */
237 struct Operation *next;
238
239 /**
240 * Kept in a DLL of the listener, if @e listener is non-NULL.
241 */
242 struct Operation *prev;
243
244 /**
245 * Channel to the peer.
246 */
247 struct GNUNET_CADET_Channel *channel;
248
249 /**
250 * Port this operation runs on.
251 */
252 struct Listener *listener;
253
254 /**
255 * Message queue for the channel.
256 */
257 struct GNUNET_MQ_Handle *mq;
258
259 /**
260 * Context message, may be NULL.
261 */
262 struct GNUNET_MessageHeader *context_msg;
263
264 /**
265 * Set associated with the operation, NULL until the spec has been
266 * associated with a set.
267 */
268 struct Set *set;
269
270 /**
271 * Copy of the set's strata estimator at the time of
272 * creation of this operation.
273 */
274 struct StrataEstimator *se;
275
276 /**
277 * The IBF we currently receive.
278 */
279 struct InvertibleBloomFilter *remote_ibf;
280
281 /**
282 * The IBF with the local set's element.
283 */
284 struct InvertibleBloomFilter *local_ibf;
285
286 /**
287 * Maps unsalted IBF-Keys to elements.
288 * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key.
289 * Colliding IBF-Keys are linked.
290 */
291 struct GNUNET_CONTAINER_MultiHashMap32 *key_to_element;
292
293 /**
294 * Timeout task, if the incoming peer has not been accepted
295 * after the timeout, it will be disconnected.
296 */
297 struct GNUNET_SCHEDULER_Task *timeout_task;
298
299 /**
300 * Hashes for elements that we have demanded from the other peer.
301 */
302 struct GNUNET_CONTAINER_MultiHashMap *demanded_hashes;
303
304 /**
305 * Current state of the operation.
306 */
307 enum UnionOperationPhase phase;
308
309 /**
310 * Did we send the client that we are done?
311 */
312 int client_done_sent;
313
314 /**
315 * Number of ibf buckets already received into the @a remote_ibf.
316 */
317 unsigned int ibf_buckets_received;
318
319 /**
320 * Salt that we're using for sending IBFs
321 */
322 uint32_t salt_send;
323
324 /**
325 * Salt for the IBF we've received and that we're currently decoding.
326 */
327 uint32_t salt_receive;
328
329 /**
330 * Number of elements we received from the other peer
331 * that were not in the local set yet.
332 */
333 uint32_t received_fresh;
334
335 /**
336 * Total number of elements received from the other peer.
337 */
338 uint32_t received_total;
339
340 /**
341 * Salt to use for the operation.
342 */
343 uint32_t salt;
344
345 /**
346 * Remote peers element count
347 */
348 uint32_t remote_element_count;
349
350 /**
351 * ID used to identify an operation between service and client
352 */
353 uint32_t client_request_id;
354
355 /**
356 * Always use delta operation instead of sending full sets,
357 * even it it's less efficient.
358 */
359 int force_delta;
360
361 /**
362 * Always send full sets, even if delta operations would
363 * be more efficient.
364 */
365 int force_full;
366
367 /**
368 * #GNUNET_YES to fail operations where Byzantine faults
369 * are suspected
370 */
371 int byzantine;
372
373 /**
374 * #GNUNET_YES to also send back set elements we are sending to
375 * the remote peer.
376 */
377 int symmetric;
378
379 /**
380 * Lower bound for the set size, used only when
381 * byzantine mode is enabled.
382 */
383 int byzantine_lower_bound;
384
385 /**
386 * Unique request id for the request from a remote peer, sent to the
387 * client, which will accept or reject the request. Set to '0' iff
388 * the request has not been suggested yet.
389 */
390 uint32_t suggest_id;
391
392 /**
393 * Generation in which the operation handle
394 * was created.
395 */
396 unsigned int generation_created;
397};
398
399
400/**
401 * SetContent stores the actual set elements, which may be shared by
402 * multiple generations derived from one set.
403 */
404struct SetContent
405{
406 /**
407 * Maps `struct GNUNET_HashCode *` to `struct ElementEntry *`.
408 */
409 struct GNUNET_CONTAINER_MultiHashMap *elements;
410
411 /**
412 * Number of references to the content.
413 */
414 unsigned int refcount;
415
416 /**
417 * FIXME: document!
418 */
419 unsigned int latest_generation;
420
421 /**
422 * Number of concurrently active iterators.
423 */
424 int iterator_count;
425};
426
427
428/**
429 * A set that supports a specific operation with other peers.
430 */
431struct Set
432{
433 /**
434 * Sets are held in a doubly linked list (in `sets_head` and `sets_tail`).
435 */
436 struct Set *next;
437
438 /**
439 * Sets are held in a doubly linked list.
440 */
441 struct Set *prev;
442
443 /**
444 * Client that owns the set. Only one client may own a set,
445 * and there can only be one set per client.
446 */
447 struct ClientState *cs;
448
449 /**
450 * Content, possibly shared by multiple sets,
451 * and thus reference counted.
452 */
453 struct SetContent *content;
454
455 /**
456 * The strata estimator is only generated once for each set. The IBF keys
457 * are derived from the element hashes with salt=0.
458 */
459 struct StrataEstimator *se;
460
461 /**
462 * Evaluate operations are held in a linked list.
463 */
464 struct Operation *ops_head;
465
466 /**
467 * Evaluate operations are held in a linked list.
468 */
469 struct Operation *ops_tail;
470
471 /**
472 * Current generation, that is, number of previously executed
473 * operations and lazy copies on the underlying set content.
474 */
475 unsigned int current_generation;
476
477};
478
479
480/**
481 * The key entry is used to associate an ibf key with an element.
482 */
483struct KeyEntry
484{
485 /**
486 * IBF key for the entry, derived from the current salt.
487 */
488 struct IBF_Key ibf_key;
489
490 /**
491 * The actual element associated with the key.
492 *
493 * Only owned by the union operation if element->operation
494 * is #GNUNET_YES.
495 */
496 struct ElementEntry *element;
497
498 /**
499 * Did we receive this element? Even if element->is_foreign is false, we
500 * might have received the element, so this indicates that the other peer
501 * has it.
502 */
503 int received;
504};
505
506
507/**
508 * Used as a closure for sending elements
509 * with a specific IBF key.
510 */
511struct SendElementClosure
512{
513 /**
514 * The IBF key whose matching elements should be
515 * sent.
516 */
517 struct IBF_Key ibf_key;
518
519 /**
520 * Operation for which the elements
521 * should be sent.
522 */
523 struct Operation *op;
524};
525
526
527/**
528 * A listener is inhabited by a client, and waits for evaluation
529 * requests from remote peers.
530 */
531struct Listener
532{
533 /**
534 * Listeners are held in a doubly linked list.
535 */
536 struct Listener *next;
537
538 /**
539 * Listeners are held in a doubly linked list.
540 */
541 struct Listener *prev;
542
543 /**
544 * Head of DLL of operations this listener is responsible for.
545 * Once the client has accepted/declined the operation, the
546 * operation is moved to the respective set's operation DLLS.
547 */
548 struct Operation *op_head;
549
550 /**
551 * Tail of DLL of operations this listener is responsible for.
552 * Once the client has accepted/declined the operation, the
553 * operation is moved to the respective set's operation DLLS.
554 */
555 struct Operation *op_tail;
556
557 /**
558 * Client that owns the listener.
559 * Only one client may own a listener.
560 */
561 struct ClientState *cs;
562
563 /**
564 * The port we are listening on with CADET.
565 */
566 struct GNUNET_CADET_Port *open_port;
567
568 /**
569 * Application ID for the operation, used to distinguish
570 * multiple operations of the same type with the same peer.
571 */
572 struct GNUNET_HashCode app_id;
573
574};
575
576
577/**
578 * Handle to the cadet service, used to listen for and connect to
579 * remote peers.
580 */
581static struct GNUNET_CADET_Handle *cadet;
582
583/**
584 * Statistics handle.
585 */
586static struct GNUNET_STATISTICS_Handle *_GSS_statistics;
587
588/**
589 * Listeners are held in a doubly linked list.
590 */
591static struct Listener *listener_head;
592
593/**
594 * Listeners are held in a doubly linked list.
595 */
596static struct Listener *listener_tail;
597
598/**
599 * Number of active clients.
600 */
601static unsigned int num_clients;
602
603/**
604 * Are we in shutdown? if #GNUNET_YES and the number of clients
605 * drops to zero, disconnect from CADET.
606 */
607static int in_shutdown;
608
609/**
610 * Counter for allocating unique IDs for clients, used to identify incoming
611 * operation requests from remote peers, that the client can choose to accept
612 * or refuse. 0 must not be used (reserved for uninitialized).
613 */
614static uint32_t suggest_id;
615
616
617/**
618 * Iterator over hash map entries, called to
619 * destroy the linked list of colliding ibf key entries.
620 *
621 * @param cls closure
622 * @param key current key code
623 * @param value value in the hash map
624 * @return #GNUNET_YES if we should continue to iterate,
625 * #GNUNET_NO if not.
626 */
627static int
628destroy_key_to_element_iter (void *cls,
629 uint32_t key,
630 void *value)
631{
632 struct KeyEntry *k = value;
633
634 GNUNET_assert (NULL != k);
635 if (GNUNET_YES == k->element->remote)
636 {
637 GNUNET_free (k->element);
638 k->element = NULL;
639 }
640 GNUNET_free (k);
641 return GNUNET_YES;
642}
643
644
645/**
646 * Signal to the client that the operation has finished and
647 * destroy the operation.
648 *
649 * @param cls operation to destroy
650 */
651static void
652send_client_done (void *cls)
653{
654 struct Operation *op = cls;
655 struct GNUNET_MQ_Envelope *ev;
656 struct GNUNET_SETU_ResultMessage *rm;
657
658 if (GNUNET_YES == op->client_done_sent)
659 return;
660 if (PHASE_DONE != op->phase)
661 {
662 LOG (GNUNET_ERROR_TYPE_WARNING,
663 "Union operation failed\n");
664 GNUNET_STATISTICS_update (_GSS_statistics,
665 "# Union operations failed",
666 1,
667 GNUNET_NO);
668 ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SETU_RESULT);
669 rm->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
670 rm->request_id = htonl (op->client_request_id);
671 rm->element_type = htons (0);
672 GNUNET_MQ_send (op->set->cs->mq,
673 ev);
674 return;
675 }
676
677 op->client_done_sent = GNUNET_YES;
678
679 GNUNET_STATISTICS_update (_GSS_statistics,
680 "# Union operations succeeded",
681 1,
682 GNUNET_NO);
683 LOG (GNUNET_ERROR_TYPE_INFO,
684 "Signalling client that union operation is done\n");
685 ev = GNUNET_MQ_msg (rm,
686 GNUNET_MESSAGE_TYPE_SETU_RESULT);
687 rm->request_id = htonl (op->client_request_id);
688 rm->result_status = htons (GNUNET_SETU_STATUS_DONE);
689 rm->element_type = htons (0);
690 rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (
691 op->key_to_element));
692 GNUNET_MQ_send (op->set->cs->mq,
693 ev);
694}
695
696
697/* FIXME: the destroy logic is a mess and should be cleaned up! */
698
699/**
700 * Destroy the given operation. Used for any operation where both
701 * peers were known and that thus actually had a vt and channel. Must
702 * not be used for operations where 'listener' is still set and we do
703 * not know the other peer.
704 *
705 * Call the implementation-specific cancel function of the operation.
706 * Disconnects from the remote peer. Does not disconnect the client,
707 * as there may be multiple operations per set.
708 *
709 * @param op operation to destroy
710 */
711static void
712_GSS_operation_destroy (struct Operation *op)
713{
714 struct Set *set = op->set;
715 struct GNUNET_CADET_Channel *channel;
716
717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718 "Destroying union operation %p\n",
719 op);
720 GNUNET_assert (NULL == op->listener);
721 /* check if the op was canceled twice */
722 if (NULL != op->remote_ibf)
723 {
724 ibf_destroy (op->remote_ibf);
725 op->remote_ibf = NULL;
726 }
727 if (NULL != op->demanded_hashes)
728 {
729 GNUNET_CONTAINER_multihashmap_destroy (op->demanded_hashes);
730 op->demanded_hashes = NULL;
731 }
732 if (NULL != op->local_ibf)
733 {
734 ibf_destroy (op->local_ibf);
735 op->local_ibf = NULL;
736 }
737 if (NULL != op->se)
738 {
739 strata_estimator_destroy (op->se);
740 op->se = NULL;
741 }
742 if (NULL != op->key_to_element)
743 {
744 GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
745 &destroy_key_to_element_iter,
746 NULL);
747 GNUNET_CONTAINER_multihashmap32_destroy (op->key_to_element);
748 op->key_to_element = NULL;
749 }
750 if (NULL != set)
751 {
752 GNUNET_CONTAINER_DLL_remove (set->ops_head,
753 set->ops_tail,
754 op);
755 op->set = NULL;
756 }
757 if (NULL != op->context_msg)
758 {
759 GNUNET_free (op->context_msg);
760 op->context_msg = NULL;
761 }
762 if (NULL != (channel = op->channel))
763 {
764 /* This will free op; called conditionally as this helper function
765 is also called from within the channel disconnect handler. */
766 op->channel = NULL;
767 GNUNET_CADET_channel_destroy (channel);
768 }
769 /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
770 * there was a channel end handler that will free 'op' on the call stack. */
771}
772
773
774/**
775 * This function probably should not exist
776 * and be replaced by inlining more specific
777 * logic in the various places where it is called.
778 */
779static void
780_GSS_operation_destroy2 (struct Operation *op);
781
782
783/**
784 * Destroy an incoming request from a remote peer
785 *
786 * @param op remote request to destroy
787 */
788static void
789incoming_destroy (struct Operation *op)
790{
791 struct Listener *listener;
792
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
794 "Destroying incoming operation %p\n",
795 op);
796 if (NULL != (listener = op->listener))
797 {
798 GNUNET_CONTAINER_DLL_remove (listener->op_head,
799 listener->op_tail,
800 op);
801 op->listener = NULL;
802 }
803 if (NULL != op->timeout_task)
804 {
805 GNUNET_SCHEDULER_cancel (op->timeout_task);
806 op->timeout_task = NULL;
807 }
808 _GSS_operation_destroy2 (op);
809}
810
811
812/**
813 * This function probably should not exist
814 * and be replaced by inlining more specific
815 * logic in the various places where it is called.
816 */
817static void
818_GSS_operation_destroy2 (struct Operation *op)
819{
820 struct GNUNET_CADET_Channel *channel;
821
822 if (NULL != (channel = op->channel))
823 {
824 /* This will free op; called conditionally as this helper function
825 is also called from within the channel disconnect handler. */
826 op->channel = NULL;
827 GNUNET_CADET_channel_destroy (channel);
828 }
829 if (NULL != op->listener)
830 {
831 incoming_destroy (op);
832 return;
833 }
834 if (NULL != op->set)
835 send_client_done (op);
836 _GSS_operation_destroy (op);
837 GNUNET_free (op);
838}
839
840
841/**
842 * Inform the client that the union operation has failed,
843 * and proceed to destroy the evaluate operation.
844 *
845 * @param op the union operation to fail
846 */
847static void
848fail_union_operation (struct Operation *op)
849{
850 struct GNUNET_MQ_Envelope *ev;
851 struct GNUNET_SETU_ResultMessage *msg;
852
853 LOG (GNUNET_ERROR_TYPE_WARNING,
854 "union operation failed\n");
855 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SETU_RESULT);
856 msg->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
857 msg->request_id = htonl (op->client_request_id);
858 msg->element_type = htons (0);
859 GNUNET_MQ_send (op->set->cs->mq,
860 ev);
861 _GSS_operation_destroy (op);
862}
863
864
865/**
866 * Derive the IBF key from a hash code and
867 * a salt.
868 *
869 * @param src the hash code
870 * @return the derived IBF key
871 */
872static struct IBF_Key
873get_ibf_key (const struct GNUNET_HashCode *src)
874{
875 struct IBF_Key key;
876 uint16_t salt = 0;
877
878 GNUNET_assert (GNUNET_OK ==
879 GNUNET_CRYPTO_kdf (&key, sizeof(key),
880 src, sizeof *src,
881 &salt, sizeof(salt),
882 NULL, 0));
883 return key;
884}
885
886
887/**
888 * Context for #op_get_element_iterator
889 */
890struct GetElementContext
891{
892 /**
893 * FIXME.
894 */
895 struct GNUNET_HashCode hash;
896
897 /**
898 * FIXME.
899 */
900 struct KeyEntry *k;
901};
902
903
904/**
905 * Iterator over the mapping from IBF keys to element entries. Checks if we
906 * have an element with a given GNUNET_HashCode.
907 *
908 * @param cls closure
909 * @param key current key code
910 * @param value value in the hash map
911 * @return #GNUNET_YES if we should search further,
912 * #GNUNET_NO if we've found the element.
913 */
914static int
915op_get_element_iterator (void *cls,
916 uint32_t key,
917 void *value)
918{
919 struct GetElementContext *ctx = cls;
920 struct KeyEntry *k = value;
921
922 GNUNET_assert (NULL != k);
923 if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash,
924 &ctx->hash))
925 {
926 ctx->k = k;
927 return GNUNET_NO;
928 }
929 return GNUNET_YES;
930}
931
932
933/**
934 * Determine whether the given element is already in the operation's element
935 * set.
936 *
937 * @param op operation that should be tested for 'element_hash'
938 * @param element_hash hash of the element to look for
939 * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise
940 */
941static struct KeyEntry *
942op_get_element (struct Operation *op,
943 const struct GNUNET_HashCode *element_hash)
944{
945 int ret;
946 struct IBF_Key ibf_key;
947 struct GetElementContext ctx = { { { 0 } }, 0 };
948
949 ctx.hash = *element_hash;
950
951 ibf_key = get_ibf_key (element_hash);
952 ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->key_to_element,
953 (uint32_t) ibf_key.key_val,
954 &op_get_element_iterator,
955 &ctx);
956
957 /* was the iteration aborted because we found the element? */
958 if (GNUNET_SYSERR == ret)
959 {
960 GNUNET_assert (NULL != ctx.k);
961 return ctx.k;
962 }
963 return NULL;
964}
965
966
967/**
968 * Insert an element into the union operation's
969 * key-to-element mapping. Takes ownership of 'ee'.
970 * Note that this does not insert the element in the set,
971 * only in the operation's key-element mapping.
972 * This is done to speed up re-tried operations, if some elements
973 * were transmitted, and then the IBF fails to decode.
974 *
975 * XXX: clarify ownership, doesn't sound right.
976 *
977 * @param op the union operation
978 * @param ee the element entry
979 * @parem received was this element received from the remote peer?
980 */
981static void
982op_register_element (struct Operation *op,
983 struct ElementEntry *ee,
984 int received)
985{
986 struct IBF_Key ibf_key;
987 struct KeyEntry *k;
988
989 ibf_key = get_ibf_key (&ee->element_hash);
990 k = GNUNET_new (struct KeyEntry);
991 k->element = ee;
992 k->ibf_key = ibf_key;
993 k->received = received;
994 GNUNET_assert (GNUNET_OK ==
995 GNUNET_CONTAINER_multihashmap32_put (op->key_to_element,
996 (uint32_t) ibf_key.key_val,
997 k,
998 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
999}
1000
1001
1002/**
1003 * FIXME.
1004 */
1005static void
1006salt_key (const struct IBF_Key *k_in,
1007 uint32_t salt,
1008 struct IBF_Key *k_out)
1009{
1010 int s = salt % 64;
1011 uint64_t x = k_in->key_val;
1012
1013 /* rotate ibf key */
1014 x = (x >> s) | (x << (64 - s));
1015 k_out->key_val = x;
1016}
1017
1018
1019/**
1020 * FIXME.
1021 */
1022static void
1023unsalt_key (const struct IBF_Key *k_in,
1024 uint32_t salt,
1025 struct IBF_Key *k_out)
1026{
1027 int s = salt % 64;
1028 uint64_t x = k_in->key_val;
1029
1030 x = (x << s) | (x >> (64 - s));
1031 k_out->key_val = x;
1032}
1033
1034
1035/**
1036 * Insert a key into an ibf.
1037 *
1038 * @param cls the ibf
1039 * @param key unused
1040 * @param value the key entry to get the key from
1041 */
1042static int
1043prepare_ibf_iterator (void *cls,
1044 uint32_t key,
1045 void *value)
1046{
1047 struct Operation *op = cls;
1048 struct KeyEntry *ke = value;
1049 struct IBF_Key salted_key;
1050
1051 LOG (GNUNET_ERROR_TYPE_DEBUG,
1052 "[OP %x] inserting %lx (hash %s) into ibf\n",
1053 (void *) op,
1054 (unsigned long) ke->ibf_key.key_val,
1055 GNUNET_h2s (&ke->element->element_hash));
1056 salt_key (&ke->ibf_key,
1057 op->salt_send,
1058 &salted_key);
1059 ibf_insert (op->local_ibf, salted_key);
1060 return GNUNET_YES;
1061}
1062
1063
1064/**
1065 * Is element @a ee part of the set used by @a op?
1066 *
1067 * @param ee element to test
1068 * @param op operation the defines the set and its generation
1069 * @return #GNUNET_YES if the element is in the set, #GNUNET_NO if not
1070 */
1071static int
1072_GSS_is_element_of_operation (struct ElementEntry *ee,
1073 struct Operation *op)
1074{
1075 return ee->generation >= op->generation_created;
1076}
1077
1078
1079/**
1080 * Iterator for initializing the
1081 * key-to-element mapping of a union operation
1082 *
1083 * @param cls the union operation `struct Operation *`
1084 * @param key unused
1085 * @param value the `struct ElementEntry *` to insert
1086 * into the key-to-element mapping
1087 * @return #GNUNET_YES (to continue iterating)
1088 */
1089static int
1090init_key_to_element_iterator (void *cls,
1091 const struct GNUNET_HashCode *key,
1092 void *value)
1093{
1094 struct Operation *op = cls;
1095 struct ElementEntry *ee = value;
1096
1097 /* make sure that the element belongs to the set at the time
1098 * of creating the operation */
1099 if (GNUNET_NO ==
1100 _GSS_is_element_of_operation (ee,
1101 op))
1102 return GNUNET_YES;
1103 GNUNET_assert (GNUNET_NO == ee->remote);
1104 op_register_element (op,
1105 ee,
1106 GNUNET_NO);
1107 return GNUNET_YES;
1108}
1109
1110
1111/**
1112 * Initialize the IBF key to element mapping local to this set operation.
1113 *
1114 * @param op the set union operation
1115 */
1116static void
1117initialize_key_to_element (struct Operation *op)
1118{
1119 unsigned int len;
1120
1121 GNUNET_assert (NULL == op->key_to_element);
1122 len = GNUNET_CONTAINER_multihashmap_size (op->set->content->elements);
1123 op->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
1124 GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1125 &init_key_to_element_iterator,
1126 op);
1127}
1128
1129
1130/**
1131 * Create an ibf with the operation's elements
1132 * of the specified size
1133 *
1134 * @param op the union operation
1135 * @param size size of the ibf to create
1136 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1137 */
1138static int
1139prepare_ibf (struct Operation *op,
1140 uint32_t size)
1141{
1142 GNUNET_assert (NULL != op->key_to_element);
1143
1144 if (NULL != op->local_ibf)
1145 ibf_destroy (op->local_ibf);
1146 op->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
1147 if (NULL == op->local_ibf)
1148 {
1149 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1150 "Failed to allocate local IBF\n");
1151 return GNUNET_SYSERR;
1152 }
1153 GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
1154 &prepare_ibf_iterator,
1155 op);
1156 return GNUNET_OK;
1157}
1158
1159
1160/**
1161 * Send an ibf of appropriate size.
1162 *
1163 * Fragments the IBF into multiple messages if necessary.
1164 *
1165 * @param op the union operation
1166 * @param ibf_order order of the ibf to send, size=2^order
1167 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1168 */
1169static int
1170send_ibf (struct Operation *op,
1171 uint16_t ibf_order)
1172{
1173 unsigned int buckets_sent = 0;
1174 struct InvertibleBloomFilter *ibf;
1175
1176 if (GNUNET_OK !=
1177 prepare_ibf (op, 1 << ibf_order))
1178 {
1179 /* allocation failed */
1180 return GNUNET_SYSERR;
1181 }
1182
1183 LOG (GNUNET_ERROR_TYPE_DEBUG,
1184 "sending ibf of size %u\n",
1185 1 << ibf_order);
1186
1187 {
1188 char name[64] = { 0 };
1189 snprintf (name, sizeof(name), "# sent IBF (order %u)", ibf_order);
1190 GNUNET_STATISTICS_update (_GSS_statistics, name, 1, GNUNET_NO);
1191 }
1192
1193 ibf = op->local_ibf;
1194
1195 while (buckets_sent < (1 << ibf_order))
1196 {
1197 unsigned int buckets_in_message;
1198 struct GNUNET_MQ_Envelope *ev;
1199 struct IBFMessage *msg;
1200
1201 buckets_in_message = (1 << ibf_order) - buckets_sent;
1202 /* limit to maximum */
1203 if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
1204 buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
1205
1206 ev = GNUNET_MQ_msg_extra (msg,
1207 buckets_in_message * IBF_BUCKET_SIZE,
1208 GNUNET_MESSAGE_TYPE_SETU_P2P_IBF);
1209 msg->reserved1 = 0;
1210 msg->reserved2 = 0;
1211 msg->order = ibf_order;
1212 msg->offset = htonl (buckets_sent);
1213 msg->salt = htonl (op->salt_send);
1214 ibf_write_slice (ibf, buckets_sent,
1215 buckets_in_message, &msg[1]);
1216 buckets_sent += buckets_in_message;
1217 LOG (GNUNET_ERROR_TYPE_DEBUG,
1218 "ibf chunk size %u, %u/%u sent\n",
1219 buckets_in_message,
1220 buckets_sent,
1221 1 << ibf_order);
1222 GNUNET_MQ_send (op->mq, ev);
1223 }
1224
1225 /* The other peer must decode the IBF, so
1226 * we're passive. */
1227 op->phase = PHASE_INVENTORY_PASSIVE;
1228 return GNUNET_OK;
1229}
1230
1231
1232/**
1233 * Compute the necessary order of an ibf
1234 * from the size of the symmetric set difference.
1235 *
1236 * @param diff the difference
1237 * @return the required size of the ibf
1238 */
1239static unsigned int
1240get_order_from_difference (unsigned int diff)
1241{
1242 unsigned int ibf_order;
1243
1244 ibf_order = 2;
1245 while (((1 << ibf_order) < (IBF_ALPHA * diff) ||
1246 ((1 << ibf_order) < SE_IBF_HASH_NUM)) &&
1247 (ibf_order < MAX_IBF_ORDER))
1248 ibf_order++;
1249 // add one for correction
1250 return ibf_order + 1;
1251}
1252
1253
1254/**
1255 * Send a set element.
1256 *
1257 * @param cls the union operation `struct Operation *`
1258 * @param key unused
1259 * @param value the `struct ElementEntry *` to insert
1260 * into the key-to-element mapping
1261 * @return #GNUNET_YES (to continue iterating)
1262 */
1263static int
1264send_full_element_iterator (void *cls,
1265 const struct GNUNET_HashCode *key,
1266 void *value)
1267{
1268 struct Operation *op = cls;
1269 struct GNUNET_SETU_ElementMessage *emsg;
1270 struct ElementEntry *ee = value;
1271 struct GNUNET_SETU_Element *el = &ee->element;
1272 struct GNUNET_MQ_Envelope *ev;
1273
1274 LOG (GNUNET_ERROR_TYPE_DEBUG,
1275 "Sending element %s\n",
1276 GNUNET_h2s (key));
1277 ev = GNUNET_MQ_msg_extra (emsg,
1278 el->size,
1279 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT);
1280 emsg->element_type = htons (el->element_type);
1281 GNUNET_memcpy (&emsg[1],
1282 el->data,
1283 el->size);
1284 GNUNET_MQ_send (op->mq,
1285 ev);
1286 return GNUNET_YES;
1287}
1288
1289
1290/**
1291 * Switch to full set transmission for @a op.
1292 *
1293 * @param op operation to switch to full set transmission.
1294 */
1295static void
1296send_full_set (struct Operation *op)
1297{
1298 struct GNUNET_MQ_Envelope *ev;
1299
1300 op->phase = PHASE_FULL_SENDING;
1301 LOG (GNUNET_ERROR_TYPE_DEBUG,
1302 "Dedicing to transmit the full set\n");
1303 /* FIXME: use a more memory-friendly way of doing this with an
1304 iterator, just as we do in the non-full case! */
1305 (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
1306 &send_full_element_iterator,
1307 op);
1308 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE);
1309 GNUNET_MQ_send (op->mq,
1310 ev);
1311}
1312
1313
1314/**
1315 * Handle a strata estimator from a remote peer
1316 *
1317 * @param cls the union operation
1318 * @param msg the message
1319 */
1320static int
1321check_union_p2p_strata_estimator (void *cls,
1322 const struct StrataEstimatorMessage *msg)
1323{
1324 struct Operation *op = cls;
1325 int is_compressed;
1326 size_t len;
1327
1328 if (op->phase != PHASE_EXPECT_SE)
1329 {
1330 GNUNET_break (0);
1331 return GNUNET_SYSERR;
1332 }
1333 is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
1334 msg->header.type));
1335 len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
1336 if ((GNUNET_NO == is_compressed) &&
1337 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE))
1338 {
1339 GNUNET_break (0);
1340 return GNUNET_SYSERR;
1341 }
1342 return GNUNET_OK;
1343}
1344
1345
1346/**
1347 * Handle a strata estimator from a remote peer
1348 *
1349 * @param cls the union operation
1350 * @param msg the message
1351 */
1352static void
1353handle_union_p2p_strata_estimator (void *cls,
1354 const struct StrataEstimatorMessage *msg)
1355{
1356 struct Operation *op = cls;
1357 struct StrataEstimator *remote_se;
1358 unsigned int diff;
1359 uint64_t other_size;
1360 size_t len;
1361 int is_compressed;
1362
1363 is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
1364 msg->header.type));
1365 GNUNET_STATISTICS_update (_GSS_statistics,
1366 "# bytes of SE received",
1367 ntohs (msg->header.size),
1368 GNUNET_NO);
1369 len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
1370 other_size = GNUNET_ntohll (msg->set_size);
1371 remote_se = strata_estimator_create (SE_STRATA_COUNT,
1372 SE_IBF_SIZE,
1373 SE_IBF_HASH_NUM);
1374 if (NULL == remote_se)
1375 {
1376 /* insufficient resources, fail */
1377 fail_union_operation (op);
1378 return;
1379 }
1380 if (GNUNET_OK !=
1381 strata_estimator_read (&msg[1],
1382 len,
1383 is_compressed,
1384 remote_se))
1385 {
1386 /* decompression failed */
1387 strata_estimator_destroy (remote_se);
1388 fail_union_operation (op);
1389 return;
1390 }
1391 GNUNET_assert (NULL != op->se);
1392 diff = strata_estimator_difference (remote_se,
1393 op->se);
1394
1395 if (diff > 200)
1396 diff = diff * 3 / 2;
1397
1398 strata_estimator_destroy (remote_se);
1399 strata_estimator_destroy (op->se);
1400 op->se = NULL;
1401 LOG (GNUNET_ERROR_TYPE_DEBUG,
1402 "got se diff=%d, using ibf size %d\n",
1403 diff,
1404 1U << get_order_from_difference (diff));
1405
1406 {
1407 char *set_debug;
1408
1409 set_debug = getenv ("GNUNET_SETU_BENCHMARK");
1410 if ((NULL != set_debug) &&
1411 (0 == strcmp (set_debug, "1")))
1412 {
1413 FILE *f = fopen ("set.log", "a");
1414 fprintf (f, "%llu\n", (unsigned long long) diff);
1415 fclose (f);
1416 }
1417 }
1418
1419 if ((GNUNET_YES == op->byzantine) &&
1420 (other_size < op->byzantine_lower_bound))
1421 {
1422 GNUNET_break (0);
1423 fail_union_operation (op);
1424 return;
1425 }
1426
1427 if ((GNUNET_YES == op->force_full) ||
1428 (diff > op->initial_size / 4) ||
1429 (0 == other_size))
1430 {
1431 LOG (GNUNET_ERROR_TYPE_DEBUG,
1432 "Deciding to go for full set transmission (diff=%d, own set=%u)\n",
1433 diff,
1434 op->initial_size);
1435 GNUNET_STATISTICS_update (_GSS_statistics,
1436 "# of full sends",
1437 1,
1438 GNUNET_NO);
1439 if ((op->initial_size <= other_size) ||
1440 (0 == other_size))
1441 {
1442 send_full_set (op);
1443 }
1444 else
1445 {
1446 struct GNUNET_MQ_Envelope *ev;
1447
1448 LOG (GNUNET_ERROR_TYPE_DEBUG,
1449 "Telling other peer that we expect its full set\n");
1450 op->phase = PHASE_EXPECT_IBF;
1451 ev = GNUNET_MQ_msg_header (
1452 GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL);
1453 GNUNET_MQ_send (op->mq,
1454 ev);
1455 }
1456 }
1457 else
1458 {
1459 GNUNET_STATISTICS_update (_GSS_statistics,
1460 "# of ibf sends",
1461 1,
1462 GNUNET_NO);
1463 if (GNUNET_OK !=
1464 send_ibf (op,
1465 get_order_from_difference (diff)))
1466 {
1467 /* Internal error, best we can do is shut the connection */
1468 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1469 "Failed to send IBF, closing connection\n");
1470 fail_union_operation (op);
1471 return;
1472 }
1473 }
1474 GNUNET_CADET_receive_done (op->channel);
1475}
1476
1477
1478/**
1479 * Iterator to send elements to a remote peer
1480 *
1481 * @param cls closure with the element key and the union operation
1482 * @param key ignored
1483 * @param value the key entry
1484 */
1485static int
1486send_offers_iterator (void *cls,
1487 uint32_t key,
1488 void *value)
1489{
1490 struct SendElementClosure *sec = cls;
1491 struct Operation *op = sec->op;
1492 struct KeyEntry *ke = value;
1493 struct GNUNET_MQ_Envelope *ev;
1494 struct GNUNET_MessageHeader *mh;
1495
1496 /* Detect 32-bit key collision for the 64-bit IBF keys. */
1497 if (ke->ibf_key.key_val != sec->ibf_key.key_val)
1498 return GNUNET_YES;
1499
1500 ev = GNUNET_MQ_msg_header_extra (mh,
1501 sizeof(struct GNUNET_HashCode),
1502 GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER);
1503
1504 GNUNET_assert (NULL != ev);
1505 *(struct GNUNET_HashCode *) &mh[1] = ke->element->element_hash;
1506 LOG (GNUNET_ERROR_TYPE_DEBUG,
1507 "[OP %x] sending element offer (%s) to peer\n",
1508 (void *) op,
1509 GNUNET_h2s (&ke->element->element_hash));
1510 GNUNET_MQ_send (op->mq, ev);
1511 return GNUNET_YES;
1512}
1513
1514
1515/**
1516 * Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key.
1517 *
1518 * @param op union operation
1519 * @param ibf_key IBF key of interest
1520 */
1521static void
1522send_offers_for_key (struct Operation *op,
1523 struct IBF_Key ibf_key)
1524{
1525 struct SendElementClosure send_cls;
1526
1527 send_cls.ibf_key = ibf_key;
1528 send_cls.op = op;
1529 (void) GNUNET_CONTAINER_multihashmap32_get_multiple (
1530 op->key_to_element,
1531 (uint32_t) ibf_key.
1532 key_val,
1533 &send_offers_iterator,
1534 &send_cls);
1535}
1536
1537
1538/**
1539 * Decode which elements are missing on each side, and
1540 * send the appropriate offers and inquiries.
1541 *
1542 * @param op union operation
1543 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1544 */
1545static int
1546decode_and_send (struct Operation *op)
1547{
1548 struct IBF_Key key;
1549 struct IBF_Key last_key;
1550 int side;
1551 unsigned int num_decoded;
1552 struct InvertibleBloomFilter *diff_ibf;
1553
1554 GNUNET_assert (PHASE_INVENTORY_ACTIVE == op->phase);
1555
1556 if (GNUNET_OK !=
1557 prepare_ibf (op,
1558 op->remote_ibf->size))
1559 {
1560 GNUNET_break (0);
1561 /* allocation failed */
1562 return GNUNET_SYSERR;
1563 }
1564 diff_ibf = ibf_dup (op->local_ibf);
1565 ibf_subtract (diff_ibf,
1566 op->remote_ibf);
1567
1568 ibf_destroy (op->remote_ibf);
1569 op->remote_ibf = NULL;
1570
1571 LOG (GNUNET_ERROR_TYPE_DEBUG,
1572 "decoding IBF (size=%u)\n",
1573 diff_ibf->size);
1574
1575 num_decoded = 0;
1576 key.key_val = 0; /* just to avoid compiler thinking we use undef'ed variable */
1577
1578 while (1)
1579 {
1580 int res;
1581 int cycle_detected = GNUNET_NO;
1582
1583 last_key = key;
1584
1585 res = ibf_decode (diff_ibf,
1586 &side,
1587 &key);
1588 if (res == GNUNET_OK)
1589 {
1590 LOG (GNUNET_ERROR_TYPE_DEBUG,
1591 "decoded ibf key %lx\n",
1592 (unsigned long) key.key_val);
1593 num_decoded += 1;
1594 if ((num_decoded > diff_ibf->size) ||
1595 ((num_decoded > 1) &&
1596 (last_key.key_val == key.key_val)))
1597 {
1598 LOG (GNUNET_ERROR_TYPE_DEBUG,
1599 "detected cyclic ibf (decoded %u/%u)\n",
1600 num_decoded,
1601 diff_ibf->size);
1602 cycle_detected = GNUNET_YES;
1603 }
1604 }
1605 if ((GNUNET_SYSERR == res) ||
1606 (GNUNET_YES == cycle_detected))
1607 {
1608 int next_order;
1609 next_order = 0;
1610 while (1 << next_order < diff_ibf->size)
1611 next_order++;
1612 next_order++;
1613 if (next_order <= MAX_IBF_ORDER)
1614 {
1615 LOG (GNUNET_ERROR_TYPE_DEBUG,
1616 "decoding failed, sending larger ibf (size %u)\n",
1617 1 << next_order);
1618 GNUNET_STATISTICS_update (_GSS_statistics,
1619 "# of IBF retries",
1620 1,
1621 GNUNET_NO);
1622 op->salt_send++;
1623 if (GNUNET_OK !=
1624 send_ibf (op, next_order))
1625 {
1626 /* Internal error, best we can do is shut the connection */
1627 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1628 "Failed to send IBF, closing connection\n");
1629 fail_union_operation (op);
1630 ibf_destroy (diff_ibf);
1631 return GNUNET_SYSERR;
1632 }
1633 }
1634 else
1635 {
1636 GNUNET_STATISTICS_update (_GSS_statistics,
1637 "# of failed union operations (too large)",
1638 1,
1639 GNUNET_NO);
1640 // XXX: Send the whole set, element-by-element
1641 LOG (GNUNET_ERROR_TYPE_ERROR,
1642 "set union failed: reached ibf limit\n");
1643 fail_union_operation (op);
1644 ibf_destroy (diff_ibf);
1645 return GNUNET_SYSERR;
1646 }
1647 break;
1648 }
1649 if (GNUNET_NO == res)
1650 {
1651 struct GNUNET_MQ_Envelope *ev;
1652
1653 LOG (GNUNET_ERROR_TYPE_DEBUG,
1654 "transmitted all values, sending DONE\n");
1655 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE);
1656 GNUNET_MQ_send (op->mq, ev);
1657 /* We now wait until we get a DONE message back
1658 * and then wait for our MQ to be flushed and all our
1659 * demands be delivered. */
1660 break;
1661 }
1662 if (1 == side)
1663 {
1664 struct IBF_Key unsalted_key;
1665
1666 unsalt_key (&key,
1667 op->salt_receive,
1668 &unsalted_key);
1669 send_offers_for_key (op,
1670 unsalted_key);
1671 }
1672 else if (-1 == side)
1673 {
1674 struct GNUNET_MQ_Envelope *ev;
1675 struct InquiryMessage *msg;
1676
1677 /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
1678 * the effort additional complexity. */
1679 ev = GNUNET_MQ_msg_extra (msg,
1680 sizeof(struct IBF_Key),
1681 GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY);
1682 msg->salt = htonl (op->salt_receive);
1683 GNUNET_memcpy (&msg[1],
1684 &key,
1685 sizeof(struct IBF_Key));
1686 LOG (GNUNET_ERROR_TYPE_DEBUG,
1687 "sending element inquiry for IBF key %lx\n",
1688 (unsigned long) key.key_val);
1689 GNUNET_MQ_send (op->mq, ev);
1690 }
1691 else
1692 {
1693 GNUNET_assert (0);
1694 }
1695 }
1696 ibf_destroy (diff_ibf);
1697 return GNUNET_OK;
1698}
1699
1700
1701/**
1702 * Check an IBF message from a remote peer.
1703 *
1704 * Reassemble the IBF from multiple pieces, and
1705 * process the whole IBF once possible.
1706 *
1707 * @param cls the union operation
1708 * @param msg the header of the message
1709 * @return #GNUNET_OK if @a msg is well-formed
1710 */
1711static int
1712check_union_p2p_ibf (void *cls,
1713 const struct IBFMessage *msg)
1714{
1715 struct Operation *op = cls;
1716 unsigned int buckets_in_message;
1717
1718 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
1719 / IBF_BUCKET_SIZE;
1720 if (0 == buckets_in_message)
1721 {
1722 GNUNET_break_op (0);
1723 return GNUNET_SYSERR;
1724 }
1725 if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message
1726 * IBF_BUCKET_SIZE)
1727 {
1728 GNUNET_break_op (0);
1729 return GNUNET_SYSERR;
1730 }
1731 if (op->phase == PHASE_EXPECT_IBF_CONT)
1732 {
1733 if (ntohl (msg->offset) != op->ibf_buckets_received)
1734 {
1735 GNUNET_break_op (0);
1736 return GNUNET_SYSERR;
1737 }
1738 if (1 << msg->order != op->remote_ibf->size)
1739 {
1740 GNUNET_break_op (0);
1741 return GNUNET_SYSERR;
1742 }
1743 if (ntohl (msg->salt) != op->salt_receive)
1744 {
1745 GNUNET_break_op (0);
1746 return GNUNET_SYSERR;
1747 }
1748 }
1749 else if ((op->phase != PHASE_INVENTORY_PASSIVE) &&
1750 (op->phase != PHASE_EXPECT_IBF))
1751 {
1752 GNUNET_break_op (0);
1753 return GNUNET_SYSERR;
1754 }
1755
1756 return GNUNET_OK;
1757}
1758
1759
1760/**
1761 * Handle an IBF message from a remote peer.
1762 *
1763 * Reassemble the IBF from multiple pieces, and
1764 * process the whole IBF once possible.
1765 *
1766 * @param cls the union operation
1767 * @param msg the header of the message
1768 */
1769static void
1770handle_union_p2p_ibf (void *cls,
1771 const struct IBFMessage *msg)
1772{
1773 struct Operation *op = cls;
1774 unsigned int buckets_in_message;
1775
1776 buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
1777 / IBF_BUCKET_SIZE;
1778 if ((op->phase == PHASE_INVENTORY_PASSIVE) ||
1779 (op->phase == PHASE_EXPECT_IBF))
1780 {
1781 op->phase = PHASE_EXPECT_IBF_CONT;
1782 GNUNET_assert (NULL == op->remote_ibf);
1783 LOG (GNUNET_ERROR_TYPE_DEBUG,
1784 "Creating new ibf of size %u\n",
1785 1 << msg->order);
1786 op->remote_ibf = ibf_create (1 << msg->order, SE_IBF_HASH_NUM);
1787 op->salt_receive = ntohl (msg->salt);
1788 LOG (GNUNET_ERROR_TYPE_DEBUG,
1789 "Receiving new IBF with salt %u\n",
1790 op->salt_receive);
1791 if (NULL == op->remote_ibf)
1792 {
1793 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1794 "Failed to parse remote IBF, closing connection\n");
1795 fail_union_operation (op);
1796 return;
1797 }
1798 op->ibf_buckets_received = 0;
1799 if (0 != ntohl (msg->offset))
1800 {
1801 GNUNET_break_op (0);
1802 fail_union_operation (op);
1803 return;
1804 }
1805 }
1806 else
1807 {
1808 GNUNET_assert (op->phase == PHASE_EXPECT_IBF_CONT);
1809 LOG (GNUNET_ERROR_TYPE_DEBUG,
1810 "Received more of IBF\n");
1811 }
1812 GNUNET_assert (NULL != op->remote_ibf);
1813
1814 ibf_read_slice (&msg[1],
1815 op->ibf_buckets_received,
1816 buckets_in_message,
1817 op->remote_ibf);
1818 op->ibf_buckets_received += buckets_in_message;
1819
1820 if (op->ibf_buckets_received == op->remote_ibf->size)
1821 {
1822 LOG (GNUNET_ERROR_TYPE_DEBUG,
1823 "received full ibf\n");
1824 op->phase = PHASE_INVENTORY_ACTIVE;
1825 if (GNUNET_OK !=
1826 decode_and_send (op))
1827 {
1828 /* Internal error, best we can do is shut down */
1829 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1830 "Failed to decode IBF, closing connection\n");
1831 fail_union_operation (op);
1832 return;
1833 }
1834 }
1835 GNUNET_CADET_receive_done (op->channel);
1836}
1837
1838
1839/**
1840 * Send a result message to the client indicating
1841 * that there is a new element.
1842 *
1843 * @param op union operation
1844 * @param element element to send
1845 * @param status status to send with the new element
1846 */
1847static void
1848send_client_element (struct Operation *op,
1849 const struct GNUNET_SETU_Element *element,
1850 enum GNUNET_SETU_Status status)
1851{
1852 struct GNUNET_MQ_Envelope *ev;
1853 struct GNUNET_SETU_ResultMessage *rm;
1854
1855 LOG (GNUNET_ERROR_TYPE_DEBUG,
1856 "sending element (size %u) to client\n",
1857 element->size);
1858 GNUNET_assert (0 != op->client_request_id);
1859 ev = GNUNET_MQ_msg_extra (rm,
1860 element->size,
1861 GNUNET_MESSAGE_TYPE_SETU_RESULT);
1862 if (NULL == ev)
1863 {
1864 GNUNET_MQ_discard (ev);
1865 GNUNET_break (0);
1866 return;
1867 }
1868 rm->result_status = htons (status);
1869 rm->request_id = htonl (op->client_request_id);
1870 rm->element_type = htons (element->element_type);
1871 rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (
1872 op->key_to_element));
1873 GNUNET_memcpy (&rm[1],
1874 element->data,
1875 element->size);
1876 GNUNET_MQ_send (op->set->cs->mq,
1877 ev);
1878}
1879
1880
1881/**
1882 * Tests if the operation is finished, and if so notify.
1883 *
1884 * @param op operation to check
1885 */
1886static void
1887maybe_finish (struct Operation *op)
1888{
1889 unsigned int num_demanded;
1890
1891 num_demanded = GNUNET_CONTAINER_multihashmap_size (
1892 op->demanded_hashes);
1893
1894 if (PHASE_FINISH_WAITING == op->phase)
1895 {
1896 LOG (GNUNET_ERROR_TYPE_DEBUG,
1897 "In PHASE_FINISH_WAITING, pending %u demands\n",
1898 num_demanded);
1899 if (0 == num_demanded)
1900 {
1901 struct GNUNET_MQ_Envelope *ev;
1902
1903 op->phase = PHASE_DONE;
1904 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE);
1905 GNUNET_MQ_send (op->mq,
1906 ev);
1907 /* We now wait until the other peer sends P2P_OVER
1908 * after it got all elements from us. */
1909 }
1910 }
1911 if (PHASE_FINISH_CLOSING == op->phase)
1912 {
1913 LOG (GNUNET_ERROR_TYPE_DEBUG,
1914 "In PHASE_FINISH_CLOSING, pending %u demands\n",
1915 num_demanded);
1916 if (0 == num_demanded)
1917 {
1918 op->phase = PHASE_DONE;
1919 send_client_done (op);
1920 _GSS_operation_destroy2 (op);
1921 }
1922 }
1923}
1924
1925
1926/**
1927 * Check an element message from a remote peer.
1928 *
1929 * @param cls the union operation
1930 * @param emsg the message
1931 */
1932static int
1933check_union_p2p_elements (void *cls,
1934 const struct GNUNET_SETU_ElementMessage *emsg)
1935{
1936 struct Operation *op = cls;
1937
1938 if (0 == GNUNET_CONTAINER_multihashmap_size (op->demanded_hashes))
1939 {
1940 GNUNET_break_op (0);
1941 return GNUNET_SYSERR;
1942 }
1943 return GNUNET_OK;
1944}
1945
1946
1947/**
1948 * Handle an element message from a remote peer.
1949 * Sent by the other peer either because we decoded an IBF and placed a demand,
1950 * or because the other peer switched to full set transmission.
1951 *
1952 * @param cls the union operation
1953 * @param emsg the message
1954 */
1955static void
1956handle_union_p2p_elements (void *cls,
1957 const struct GNUNET_SETU_ElementMessage *emsg)
1958{
1959 struct Operation *op = cls;
1960 struct ElementEntry *ee;
1961 struct KeyEntry *ke;
1962 uint16_t element_size;
1963
1964 element_size = ntohs (emsg->header.size) - sizeof(struct
1965 GNUNET_SETU_ElementMessage);
1966 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
1967 GNUNET_memcpy (&ee[1],
1968 &emsg[1],
1969 element_size);
1970 ee->element.size = element_size;
1971 ee->element.data = &ee[1];
1972 ee->element.element_type = ntohs (emsg->element_type);
1973 ee->remote = GNUNET_YES;
1974 GNUNET_SETU_element_hash (&ee->element,
1975 &ee->element_hash);
1976 if (GNUNET_NO ==
1977 GNUNET_CONTAINER_multihashmap_remove (op->demanded_hashes,
1978 &ee->element_hash,
1979 NULL))
1980 {
1981 /* We got something we didn't demand, since it's not in our map. */
1982 GNUNET_break_op (0);
1983 fail_union_operation (op);
1984 return;
1985 }
1986
1987 LOG (GNUNET_ERROR_TYPE_DEBUG,
1988 "Got element (size %u, hash %s) from peer\n",
1989 (unsigned int) element_size,
1990 GNUNET_h2s (&ee->element_hash));
1991
1992 GNUNET_STATISTICS_update (_GSS_statistics,
1993 "# received elements",
1994 1,
1995 GNUNET_NO);
1996 GNUNET_STATISTICS_update (_GSS_statistics,
1997 "# exchanged elements",
1998 1,
1999 GNUNET_NO);
2000
2001 op->received_total++;
2002
2003 ke = op_get_element (op,
2004 &ee->element_hash);
2005 if (NULL != ke)
2006 {
2007 /* Got repeated element. Should not happen since
2008 * we track demands. */
2009 GNUNET_STATISTICS_update (_GSS_statistics,
2010 "# repeated elements",
2011 1,
2012 GNUNET_NO);
2013 ke->received = GNUNET_YES;
2014 GNUNET_free (ee);
2015 }
2016 else
2017 {
2018 LOG (GNUNET_ERROR_TYPE_DEBUG,
2019 "Registering new element from remote peer\n");
2020 op->received_fresh++;
2021 op_register_element (op, ee, GNUNET_YES);
2022 /* only send results immediately if the client wants it */
2023 send_client_element (op,
2024 &ee->element,
2025 GNUNET_SETU_STATUS_ADD_LOCAL);
2026 }
2027
2028 if ((op->received_total > 8) &&
2029 (op->received_fresh < op->received_total / 3))
2030 {
2031 /* The other peer gave us lots of old elements, there's something wrong. */
2032 GNUNET_break_op (0);
2033 fail_union_operation (op);
2034 return;
2035 }
2036 GNUNET_CADET_receive_done (op->channel);
2037 maybe_finish (op);
2038}
2039
2040
2041/**
2042 * Check a full element message from a remote peer.
2043 *
2044 * @param cls the union operation
2045 * @param emsg the message
2046 */
2047static int
2048check_union_p2p_full_element (void *cls,
2049 const struct GNUNET_SETU_ElementMessage *emsg)
2050{
2051 struct Operation *op = cls;
2052
2053 (void) op;
2054 // FIXME: check that we expect full elements here?
2055 return GNUNET_OK;
2056}
2057
2058
2059/**
2060 * Handle an element message from a remote peer.
2061 *
2062 * @param cls the union operation
2063 * @param emsg the message
2064 */
2065static void
2066handle_union_p2p_full_element (void *cls,
2067 const struct GNUNET_SETU_ElementMessage *emsg)
2068{
2069 struct Operation *op = cls;
2070 struct ElementEntry *ee;
2071 struct KeyEntry *ke;
2072 uint16_t element_size;
2073
2074 element_size = ntohs (emsg->header.size)
2075 - sizeof(struct GNUNET_SETU_ElementMessage);
2076 ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
2077 GNUNET_memcpy (&ee[1], &emsg[1], element_size);
2078 ee->element.size = element_size;
2079 ee->element.data = &ee[1];
2080 ee->element.element_type = ntohs (emsg->element_type);
2081 ee->remote = GNUNET_YES;
2082 GNUNET_SETU_element_hash (&ee->element,
2083 &ee->element_hash);
2084 LOG (GNUNET_ERROR_TYPE_DEBUG,
2085 "Got element (full diff, size %u, hash %s) from peer\n",
2086 (unsigned int) element_size,
2087 GNUNET_h2s (&ee->element_hash));
2088
2089 GNUNET_STATISTICS_update (_GSS_statistics,
2090 "# received elements",
2091 1,
2092 GNUNET_NO);
2093 GNUNET_STATISTICS_update (_GSS_statistics,
2094 "# exchanged elements",
2095 1,
2096 GNUNET_NO);
2097
2098 op->received_total++;
2099
2100 ke = op_get_element (op,
2101 &ee->element_hash);
2102 if (NULL != ke)
2103 {
2104 /* Got repeated element. Should not happen since
2105 * we track demands. */
2106 GNUNET_STATISTICS_update (_GSS_statistics,
2107 "# repeated elements",
2108 1,
2109 GNUNET_NO);
2110 ke->received = GNUNET_YES;
2111 GNUNET_free (ee);
2112 }
2113 else
2114 {
2115 LOG (GNUNET_ERROR_TYPE_DEBUG,
2116 "Registering new element from remote peer\n");
2117 op->received_fresh++;
2118 op_register_element (op, ee, GNUNET_YES);
2119 /* only send results immediately if the client wants it */
2120 send_client_element (op,
2121 &ee->element,
2122 GNUNET_SETU_STATUS_ADD_LOCAL);
2123 }
2124
2125 if ((GNUNET_YES == op->byzantine) &&
2126 (op->received_total > 384 + op->received_fresh * 4) &&
2127 (op->received_fresh < op->received_total / 6))
2128 {
2129 /* The other peer gave us lots of old elements, there's something wrong. */
2130 LOG (GNUNET_ERROR_TYPE_ERROR,
2131 "Other peer sent only %llu/%llu fresh elements, failing operation\n",
2132 (unsigned long long) op->received_fresh,
2133 (unsigned long long) op->received_total);
2134 GNUNET_break_op (0);
2135 fail_union_operation (op);
2136 return;
2137 }
2138 GNUNET_CADET_receive_done (op->channel);
2139}
2140
2141
2142/**
2143 * Send offers (for GNUNET_Hash-es) in response
2144 * to inquiries (for IBF_Key-s).
2145 *
2146 * @param cls the union operation
2147 * @param msg the message
2148 */
2149static int
2150check_union_p2p_inquiry (void *cls,
2151 const struct InquiryMessage *msg)
2152{
2153 struct Operation *op = cls;
2154 unsigned int num_keys;
2155
2156 if (op->phase != PHASE_INVENTORY_PASSIVE)
2157 {
2158 GNUNET_break_op (0);
2159 return GNUNET_SYSERR;
2160 }
2161 num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
2162 / sizeof(struct IBF_Key);
2163 if ((ntohs (msg->header.size) - sizeof(struct InquiryMessage))
2164 != num_keys * sizeof(struct IBF_Key))
2165 {
2166 GNUNET_break_op (0);
2167 return GNUNET_SYSERR;
2168 }
2169 return GNUNET_OK;
2170}
2171
2172
2173/**
2174 * Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s).
2175 *
2176 * @param cls the union operation
2177 * @param msg the message
2178 */
2179static void
2180handle_union_p2p_inquiry (void *cls,
2181 const struct InquiryMessage *msg)
2182{
2183 struct Operation *op = cls;
2184 const struct IBF_Key *ibf_key;
2185 unsigned int num_keys;
2186
2187 LOG (GNUNET_ERROR_TYPE_DEBUG,
2188 "Received union inquiry\n");
2189 num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
2190 / sizeof(struct IBF_Key);
2191 ibf_key = (const struct IBF_Key *) &msg[1];
2192 while (0 != num_keys--)
2193 {
2194 struct IBF_Key unsalted_key;
2195
2196 unsalt_key (ibf_key,
2197 ntohl (msg->salt),
2198 &unsalted_key);
2199 send_offers_for_key (op,
2200 unsalted_key);
2201 ibf_key++;
2202 }
2203 GNUNET_CADET_receive_done (op->channel);
2204}
2205
2206
2207/**
2208 * Iterator over hash map entries, called to destroy the linked list of
2209 * colliding ibf key entries.
2210 *
2211 * @param cls closure
2212 * @param key current key code
2213 * @param value value in the hash map
2214 * @return #GNUNET_YES if we should continue to iterate,
2215 * #GNUNET_NO if not.
2216 */
2217static int
2218send_missing_full_elements_iter (void *cls,
2219 uint32_t key,
2220 void *value)
2221{
2222 struct Operation *op = cls;
2223 struct KeyEntry *ke = value;
2224 struct GNUNET_MQ_Envelope *ev;
2225 struct GNUNET_SETU_ElementMessage *emsg;
2226 struct ElementEntry *ee = ke->element;
2227
2228 if (GNUNET_YES == ke->received)
2229 return GNUNET_YES;
2230 ev = GNUNET_MQ_msg_extra (emsg,
2231 ee->element.size,
2232 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT);
2233 GNUNET_memcpy (&emsg[1],
2234 ee->element.data,
2235 ee->element.size);
2236 emsg->element_type = htons (ee->element.element_type);
2237 GNUNET_MQ_send (op->mq,
2238 ev);
2239 return GNUNET_YES;
2240}
2241
2242
2243/**
2244 * Handle a request for full set transmission.
2245 *
2246 * @parem cls closure, a set union operation
2247 * @param mh the demand message
2248 */
2249static void
2250handle_union_p2p_request_full (void *cls,
2251 const struct GNUNET_MessageHeader *mh)
2252{
2253 struct Operation *op = cls;
2254
2255 LOG (GNUNET_ERROR_TYPE_DEBUG,
2256 "Received request for full set transmission\n");
2257 if (PHASE_EXPECT_IBF != op->phase)
2258 {
2259 GNUNET_break_op (0);
2260 fail_union_operation (op);
2261 return;
2262 }
2263
2264 // FIXME: we need to check that our set is larger than the
2265 // byzantine_lower_bound by some threshold
2266 send_full_set (op);
2267 GNUNET_CADET_receive_done (op->channel);
2268}
2269
2270
2271/**
2272 * Handle a "full done" message.
2273 *
2274 * @parem cls closure, a set union operation
2275 * @param mh the demand message
2276 */
2277static void
2278handle_union_p2p_full_done (void *cls,
2279 const struct GNUNET_MessageHeader *mh)
2280{
2281 struct Operation *op = cls;
2282
2283 switch (op->phase)
2284 {
2285 case PHASE_EXPECT_IBF:
2286 {
2287 struct GNUNET_MQ_Envelope *ev;
2288
2289 LOG (GNUNET_ERROR_TYPE_DEBUG,
2290 "got FULL DONE, sending elements that other peer is missing\n");
2291
2292 /* send all the elements that did not come from the remote peer */
2293 GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
2294 &send_missing_full_elements_iter,
2295 op);
2296 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE);
2297 GNUNET_MQ_send (op->mq,
2298 ev);
2299 op->phase = PHASE_DONE;
2300 /* we now wait until the other peer sends us the OVER message*/
2301 }
2302 break;
2303
2304 case PHASE_FULL_SENDING:
2305 {
2306 LOG (GNUNET_ERROR_TYPE_DEBUG,
2307 "got FULL DONE, finishing\n");
2308 /* We sent the full set, and got the response for that. We're done. */
2309 op->phase = PHASE_DONE;
2310 GNUNET_CADET_receive_done (op->channel);
2311 send_client_done (op);
2312 _GSS_operation_destroy2 (op);
2313 return;
2314 }
2315 break;
2316
2317 default:
2318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2319 "Handle full done phase is %u\n",
2320 (unsigned) op->phase);
2321 GNUNET_break_op (0);
2322 fail_union_operation (op);
2323 return;
2324 }
2325 GNUNET_CADET_receive_done (op->channel);
2326}
2327
2328
2329/**
2330 * Check a demand by the other peer for elements based on a list
2331 * of `struct GNUNET_HashCode`s.
2332 *
2333 * @parem cls closure, a set union operation
2334 * @param mh the demand message
2335 * @return #GNUNET_OK if @a mh is well-formed
2336 */
2337static int
2338check_union_p2p_demand (void *cls,
2339 const struct GNUNET_MessageHeader *mh)
2340{
2341 struct Operation *op = cls;
2342 unsigned int num_hashes;
2343
2344 (void) op;
2345 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2346 / sizeof(struct GNUNET_HashCode);
2347 if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2348 != num_hashes * sizeof(struct GNUNET_HashCode))
2349 {
2350 GNUNET_break_op (0);
2351 return GNUNET_SYSERR;
2352 }
2353 return GNUNET_OK;
2354}
2355
2356
2357/**
2358 * Handle a demand by the other peer for elements based on a list
2359 * of `struct GNUNET_HashCode`s.
2360 *
2361 * @parem cls closure, a set union operation
2362 * @param mh the demand message
2363 */
2364static void
2365handle_union_p2p_demand (void *cls,
2366 const struct GNUNET_MessageHeader *mh)
2367{
2368 struct Operation *op = cls;
2369 struct ElementEntry *ee;
2370 struct GNUNET_SETU_ElementMessage *emsg;
2371 const struct GNUNET_HashCode *hash;
2372 unsigned int num_hashes;
2373 struct GNUNET_MQ_Envelope *ev;
2374
2375 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2376 / sizeof(struct GNUNET_HashCode);
2377 for (hash = (const struct GNUNET_HashCode *) &mh[1];
2378 num_hashes > 0;
2379 hash++, num_hashes--)
2380 {
2381 ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
2382 hash);
2383 if (NULL == ee)
2384 {
2385 /* Demand for non-existing element. */
2386 GNUNET_break_op (0);
2387 fail_union_operation (op);
2388 return;
2389 }
2390 if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
2391 {
2392 /* Probably confused lazily copied sets. */
2393 GNUNET_break_op (0);
2394 fail_union_operation (op);
2395 return;
2396 }
2397 ev = GNUNET_MQ_msg_extra (emsg,
2398 ee->element.size,
2399 GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS);
2400 GNUNET_memcpy (&emsg[1],
2401 ee->element.data,
2402 ee->element.size);
2403 emsg->reserved = htons (0);
2404 emsg->element_type = htons (ee->element.element_type);
2405 LOG (GNUNET_ERROR_TYPE_DEBUG,
2406 "[OP %x] Sending demanded element (size %u, hash %s) to peer\n",
2407 (void *) op,
2408 (unsigned int) ee->element.size,
2409 GNUNET_h2s (&ee->element_hash));
2410 GNUNET_MQ_send (op->mq, ev);
2411 GNUNET_STATISTICS_update (_GSS_statistics,
2412 "# exchanged elements",
2413 1,
2414 GNUNET_NO);
2415 if (op->symmetric)
2416 send_client_element (op,
2417 &ee->element,
2418 GNUNET_SET_STATUS_ADD_REMOTE);
2419 }
2420 GNUNET_CADET_receive_done (op->channel);
2421}
2422
2423
2424/**
2425 * Check offer (of `struct GNUNET_HashCode`s).
2426 *
2427 * @param cls the union operation
2428 * @param mh the message
2429 * @return #GNUNET_OK if @a mh is well-formed
2430 */
2431static int
2432check_union_p2p_offer (void *cls,
2433 const struct GNUNET_MessageHeader *mh)
2434{
2435 struct Operation *op = cls;
2436 unsigned int num_hashes;
2437
2438 /* look up elements and send them */
2439 if ((op->phase != PHASE_INVENTORY_PASSIVE) &&
2440 (op->phase != PHASE_INVENTORY_ACTIVE))
2441 {
2442 GNUNET_break_op (0);
2443 return GNUNET_SYSERR;
2444 }
2445 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2446 / sizeof(struct GNUNET_HashCode);
2447 if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) !=
2448 num_hashes * sizeof(struct GNUNET_HashCode))
2449 {
2450 GNUNET_break_op (0);
2451 return GNUNET_SYSERR;
2452 }
2453 return GNUNET_OK;
2454}
2455
2456
2457/**
2458 * Handle offers (of `struct GNUNET_HashCode`s) and
2459 * respond with demands (of `struct GNUNET_HashCode`s).
2460 *
2461 * @param cls the union operation
2462 * @param mh the message
2463 */
2464static void
2465handle_union_p2p_offer (void *cls,
2466 const struct GNUNET_MessageHeader *mh)
2467{
2468 struct Operation *op = cls;
2469 const struct GNUNET_HashCode *hash;
2470 unsigned int num_hashes;
2471
2472 num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
2473 / sizeof(struct GNUNET_HashCode);
2474 for (hash = (const struct GNUNET_HashCode *) &mh[1];
2475 num_hashes > 0;
2476 hash++, num_hashes--)
2477 {
2478 struct ElementEntry *ee;
2479 struct GNUNET_MessageHeader *demands;
2480 struct GNUNET_MQ_Envelope *ev;
2481
2482 ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
2483 hash);
2484 if (NULL != ee)
2485 if (GNUNET_YES == _GSS_is_element_of_operation (ee, op))
2486 continue;
2487
2488 if (GNUNET_YES ==
2489 GNUNET_CONTAINER_multihashmap_contains (op->demanded_hashes,
2490 hash))
2491 {
2492 LOG (GNUNET_ERROR_TYPE_DEBUG,
2493 "Skipped sending duplicate demand\n");
2494 continue;
2495 }
2496
2497 GNUNET_assert (GNUNET_OK ==
2498 GNUNET_CONTAINER_multihashmap_put (
2499 op->demanded_hashes,
2500 hash,
2501 NULL,
2502 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
2503
2504 LOG (GNUNET_ERROR_TYPE_DEBUG,
2505 "[OP %x] Requesting element (hash %s)\n",
2506 (void *) op, GNUNET_h2s (hash));
2507 ev = GNUNET_MQ_msg_header_extra (demands,
2508 sizeof(struct GNUNET_HashCode),
2509 GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND);
2510 GNUNET_memcpy (&demands[1],
2511 hash,
2512 sizeof(struct GNUNET_HashCode));
2513 GNUNET_MQ_send (op->mq, ev);
2514 }
2515 GNUNET_CADET_receive_done (op->channel);
2516}
2517
2518
2519/**
2520 * Handle a done message from a remote peer
2521 *
2522 * @param cls the union operation
2523 * @param mh the message
2524 */
2525static void
2526handle_union_p2p_done (void *cls,
2527 const struct GNUNET_MessageHeader *mh)
2528{
2529 struct Operation *op = cls;
2530
2531 switch (op->phase)
2532 {
2533 case PHASE_INVENTORY_PASSIVE:
2534 /* We got all requests, but still have to send our elements in response. */
2535 op->phase = PHASE_FINISH_WAITING;
2536 LOG (GNUNET_ERROR_TYPE_DEBUG,
2537 "got DONE (as passive partner), waiting for our demands to be satisfied\n");
2538 /* The active peer is done sending offers
2539 * and inquiries. This means that all
2540 * our responses to that (demands and offers)
2541 * must be in flight (queued or in mesh).
2542 *
2543 * We should notify the active peer once
2544 * all our demands are satisfied, so that the active
2545 * peer can quit if we gave it everything.
2546 */GNUNET_CADET_receive_done (op->channel);
2547 maybe_finish (op);
2548 return;
2549 case PHASE_INVENTORY_ACTIVE:
2550 LOG (GNUNET_ERROR_TYPE_DEBUG,
2551 "got DONE (as active partner), waiting to finish\n");
2552 /* All demands of the other peer are satisfied,
2553 * and we processed all offers, thus we know
2554 * exactly what our demands must be.
2555 *
2556 * We'll close the channel
2557 * to the other peer once our demands are met.
2558 */op->phase = PHASE_FINISH_CLOSING;
2559 GNUNET_CADET_receive_done (op->channel);
2560 maybe_finish (op);
2561 return;
2562 default:
2563 GNUNET_break_op (0);
2564 fail_union_operation (op);
2565 return;
2566 }
2567}
2568
2569
2570/**
2571 * Handle a over message from a remote peer
2572 *
2573 * @param cls the union operation
2574 * @param mh the message
2575 */
2576static void
2577handle_union_p2p_over (void *cls,
2578 const struct GNUNET_MessageHeader *mh)
2579{
2580 send_client_done (cls);
2581}
2582
2583
2584/**
2585 * Get the incoming socket associated with the given id.
2586 *
2587 * @param listener the listener to look in
2588 * @param id id to look for
2589 * @return the incoming socket associated with the id,
2590 * or NULL if there is none
2591 */
2592static struct Operation *
2593get_incoming (uint32_t id)
2594{
2595 for (struct Listener *listener = listener_head;
2596 NULL != listener;
2597 listener = listener->next)
2598 {
2599 for (struct Operation *op = listener->op_head;
2600 NULL != op;
2601 op = op->next)
2602 if (op->suggest_id == id)
2603 return op;
2604 }
2605 return NULL;
2606}
2607
2608
2609/**
2610 * Callback called when a client connects to the service.
2611 *
2612 * @param cls closure for the service
2613 * @param c the new client that connected to the service
2614 * @param mq the message queue used to send messages to the client
2615 * @return @a `struct ClientState`
2616 */
2617static void *
2618client_connect_cb (void *cls,
2619 struct GNUNET_SERVICE_Client *c,
2620 struct GNUNET_MQ_Handle *mq)
2621{
2622 struct ClientState *cs;
2623
2624 num_clients++;
2625 cs = GNUNET_new (struct ClientState);
2626 cs->client = c;
2627 cs->mq = mq;
2628 return cs;
2629}
2630
2631
2632/**
2633 * Iterator over hash map entries to free element entries.
2634 *
2635 * @param cls closure
2636 * @param key current key code
2637 * @param value a `struct ElementEntry *` to be free'd
2638 * @return #GNUNET_YES (continue to iterate)
2639 */
2640static int
2641destroy_elements_iterator (void *cls,
2642 const struct GNUNET_HashCode *key,
2643 void *value)
2644{
2645 struct ElementEntry *ee = value;
2646
2647 GNUNET_free (ee);
2648 return GNUNET_YES;
2649}
2650
2651
2652/**
2653 * Clean up after a client has disconnected
2654 *
2655 * @param cls closure, unused
2656 * @param client the client to clean up after
2657 * @param internal_cls the `struct ClientState`
2658 */
2659static void
2660client_disconnect_cb (void *cls,
2661 struct GNUNET_SERVICE_Client *client,
2662 void *internal_cls)
2663{
2664 struct ClientState *cs = internal_cls;
2665 struct Operation *op;
2666 struct Listener *listener;
2667 struct Set *set;
2668
2669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2670 "Client disconnected, cleaning up\n");
2671 if (NULL != (set = cs->set))
2672 {
2673 struct SetContent *content = set->content;
2674
2675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2676 "Destroying client's set\n");
2677 /* Destroy pending set operations */
2678 while (NULL != set->ops_head)
2679 _GSS_operation_destroy (set->ops_head);
2680
2681 /* Destroy operation-specific state */
2682 if (NULL != set->se)
2683 {
2684 strata_estimator_destroy (set->se);
2685 set->se = NULL;
2686 }
2687 /* free set content (or at least decrement RC) */
2688 set->content = NULL;
2689 GNUNET_assert (0 != content->refcount);
2690 content->refcount--;
2691 if (0 == content->refcount)
2692 {
2693 GNUNET_assert (NULL != content->elements);
2694 GNUNET_CONTAINER_multihashmap_iterate (content->elements,
2695 &destroy_elements_iterator,
2696 NULL);
2697 GNUNET_CONTAINER_multihashmap_destroy (content->elements);
2698 content->elements = NULL;
2699 GNUNET_free (content);
2700 }
2701 GNUNET_free (set);
2702 }
2703
2704 if (NULL != (listener = cs->listener))
2705 {
2706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2707 "Destroying client's listener\n");
2708 GNUNET_CADET_close_port (listener->open_port);
2709 listener->open_port = NULL;
2710 while (NULL != (op = listener->op_head))
2711 {
2712 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2713 "Destroying incoming operation `%u' from peer `%s'\n",
2714 (unsigned int) op->client_request_id,
2715 GNUNET_i2s (&op->peer));
2716 incoming_destroy (op);
2717 }
2718 GNUNET_CONTAINER_DLL_remove (listener_head,
2719 listener_tail,
2720 listener);
2721 GNUNET_free (listener);
2722 }
2723 GNUNET_free (cs);
2724 num_clients--;
2725 if ( (GNUNET_YES == in_shutdown) &&
2726 (0 == num_clients) )
2727 {
2728 if (NULL != cadet)
2729 {
2730 GNUNET_CADET_disconnect (cadet);
2731 cadet = NULL;
2732 }
2733 }
2734}
2735
2736
2737/**
2738 * Check a request for a set operation from another peer.
2739 *
2740 * @param cls the operation state
2741 * @param msg the received message
2742 * @return #GNUNET_OK if the channel should be kept alive,
2743 * #GNUNET_SYSERR to destroy the channel
2744 */
2745static int
2746check_incoming_msg (void *cls,
2747 const struct OperationRequestMessage *msg)
2748{
2749 struct Operation *op = cls;
2750 struct Listener *listener = op->listener;
2751 const struct GNUNET_MessageHeader *nested_context;
2752
2753 /* double operation request */
2754 if (0 != op->suggest_id)
2755 {
2756 GNUNET_break_op (0);
2757 return GNUNET_SYSERR;
2758 }
2759 /* This should be equivalent to the previous condition, but can't hurt to check twice */
2760 if (NULL == listener)
2761 {
2762 GNUNET_break (0);
2763 return GNUNET_SYSERR;
2764 }
2765 nested_context = GNUNET_MQ_extract_nested_mh (msg);
2766 if ((NULL != nested_context) &&
2767 (ntohs (nested_context->size) > GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE))
2768 {
2769 GNUNET_break_op (0);
2770 return GNUNET_SYSERR;
2771 }
2772 return GNUNET_OK;
2773}
2774
2775
2776/**
2777 * Handle a request for a set operation from another peer. Checks if we
2778 * have a listener waiting for such a request (and in that case initiates
2779 * asking the listener about accepting the connection). If no listener
2780 * is waiting, we queue the operation request in hope that a listener
2781 * shows up soon (before timeout).
2782 *
2783 * This msg is expected as the first and only msg handled through the
2784 * non-operation bound virtual table, acceptance of this operation replaces
2785 * our virtual table and subsequent msgs would be routed differently (as
2786 * we then know what type of operation this is).
2787 *
2788 * @param cls the operation state
2789 * @param msg the received message
2790 * @return #GNUNET_OK if the channel should be kept alive,
2791 * #GNUNET_SYSERR to destroy the channel
2792 */
2793static void
2794handle_incoming_msg (void *cls,
2795 const struct OperationRequestMessage *msg)
2796{
2797 struct Operation *op = cls;
2798 struct Listener *listener = op->listener;
2799 const struct GNUNET_MessageHeader *nested_context;
2800 struct GNUNET_MQ_Envelope *env;
2801 struct GNUNET_SETU_RequestMessage *cmsg;
2802
2803 nested_context = GNUNET_MQ_extract_nested_mh (msg);
2804 /* Make a copy of the nested_context (application-specific context
2805 information that is opaque to set) so we can pass it to the
2806 listener later on */
2807 if (NULL != nested_context)
2808 op->context_msg = GNUNET_copy_message (nested_context);
2809 op->remote_element_count = ntohl (msg->element_count);
2810 GNUNET_log (
2811 GNUNET_ERROR_TYPE_DEBUG,
2812 "Received P2P operation request (port %s) for active listener\n",
2813 GNUNET_h2s (&op->listener->app_id));
2814 GNUNET_assert (0 == op->suggest_id);
2815 if (0 == suggest_id)
2816 suggest_id++;
2817 op->suggest_id = suggest_id++;
2818 GNUNET_assert (NULL != op->timeout_task);
2819 GNUNET_SCHEDULER_cancel (op->timeout_task);
2820 op->timeout_task = NULL;
2821 env = GNUNET_MQ_msg_nested_mh (cmsg,
2822 GNUNET_MESSAGE_TYPE_SETU_REQUEST,
2823 op->context_msg);
2824 GNUNET_log (
2825 GNUNET_ERROR_TYPE_DEBUG,
2826 "Suggesting incoming request with accept id %u to listener %p of client %p\n",
2827 op->suggest_id,
2828 listener,
2829 listener->cs);
2830 cmsg->accept_id = htonl (op->suggest_id);
2831 cmsg->peer_id = op->peer;
2832 GNUNET_MQ_send (listener->cs->mq,
2833 env);
2834 /* NOTE: GNUNET_CADET_receive_done() will be called in
2835 #handle_client_accept() */
2836}
2837
2838
2839/**
2840 * Called when a client wants to create a new set. This is typically
2841 * the first request from a client, and includes the type of set
2842 * operation to be performed.
2843 *
2844 * @param cls client that sent the message
2845 * @param m message sent by the client
2846 */
2847static void
2848handle_client_create_set (void *cls,
2849 const struct GNUNET_SETU_CreateMessage *msg)
2850{
2851 struct ClientState *cs = cls;
2852 struct Set *set;
2853
2854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2855 "Client created new set for union operation\n");
2856 if (NULL != cs->set)
2857 {
2858 /* There can only be one set per client */
2859 GNUNET_break (0);
2860 GNUNET_SERVICE_client_drop (cs->client);
2861 return;
2862 }
2863 set = GNUNET_new (struct Set);
2864 {
2865 struct StrataEstimator *se;
2866
2867 se = strata_estimator_create (SE_STRATA_COUNT,
2868 SE_IBF_SIZE,
2869 SE_IBF_HASH_NUM);
2870 if (NULL == se)
2871 {
2872 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2873 "Failed to allocate strata estimator\n");
2874 GNUNET_free (set);
2875 GNUNET_SERVICE_client_drop (cs->client);
2876 return;
2877 }
2878 set->se = se;
2879 }
2880 set->content = GNUNET_new (struct SetContent);
2881 set->content->refcount = 1;
2882 set->content->elements = GNUNET_CONTAINER_multihashmap_create (1,
2883 GNUNET_YES);
2884 set->cs = cs;
2885 cs->set = set;
2886 GNUNET_SERVICE_client_continue (cs->client);
2887}
2888
2889
2890/**
2891 * Timeout happens iff:
2892 * - we suggested an operation to our listener,
2893 * but did not receive a response in time
2894 * - we got the channel from a peer but no #GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST
2895 *
2896 * @param cls channel context
2897 * @param tc context information (why was this task triggered now)
2898 */
2899static void
2900incoming_timeout_cb (void *cls)
2901{
2902 struct Operation *op = cls;
2903
2904 op->timeout_task = NULL;
2905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2906 "Remote peer's incoming request timed out\n");
2907 incoming_destroy (op);
2908}
2909
2910
2911/**
2912 * Method called whenever another peer has added us to a channel the
2913 * other peer initiated. Only called (once) upon reception of data
2914 * from a channel we listen on.
2915 *
2916 * The channel context represents the operation itself and gets added
2917 * to a DLL, from where it gets looked up when our local listener
2918 * client responds to a proposed/suggested operation or connects and
2919 * associates with this operation.
2920 *
2921 * @param cls closure
2922 * @param channel new handle to the channel
2923 * @param source peer that started the channel
2924 * @return initial channel context for the channel
2925 * returns NULL on error
2926 */
2927static void *
2928channel_new_cb (void *cls,
2929 struct GNUNET_CADET_Channel *channel,
2930 const struct GNUNET_PeerIdentity *source)
2931{
2932 struct Listener *listener = cls;
2933 struct Operation *op;
2934
2935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2936 "New incoming channel\n");
2937 op = GNUNET_new (struct Operation);
2938 op->listener = listener;
2939 op->peer = *source;
2940 op->channel = channel;
2941 op->mq = GNUNET_CADET_get_mq (op->channel);
2942 op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
2943 UINT32_MAX);
2944 op->timeout_task = GNUNET_SCHEDULER_add_delayed (INCOMING_CHANNEL_TIMEOUT,
2945 &incoming_timeout_cb,
2946 op);
2947 GNUNET_CONTAINER_DLL_insert (listener->op_head,
2948 listener->op_tail,
2949 op);
2950 return op;
2951}
2952
2953
2954/**
2955 * Function called whenever a channel is destroyed. Should clean up
2956 * any associated state. It must NOT call
2957 * GNUNET_CADET_channel_destroy() on the channel.
2958 *
2959 * The peer_disconnect function is part of a a virtual table set initially either
2960 * when a peer creates a new channel with us, or once we create
2961 * a new channel ourselves (evaluate).
2962 *
2963 * Once we know the exact type of operation (union/intersection), the vt is
2964 * replaced with an operation specific instance (_GSS_[op]_vt).
2965 *
2966 * @param channel_ctx place where local state associated
2967 * with the channel is stored
2968 * @param channel connection to the other end (henceforth invalid)
2969 */
2970static void
2971channel_end_cb (void *channel_ctx,
2972 const struct GNUNET_CADET_Channel *channel)
2973{
2974 struct Operation *op = channel_ctx;
2975
2976 op->channel = NULL;
2977 _GSS_operation_destroy2 (op);
2978}
2979
2980
2981/**
2982 * Function called whenever an MQ-channel's transmission window size changes.
2983 *
2984 * The first callback in an outgoing channel will be with a non-zero value
2985 * and will mean the channel is connected to the destination.
2986 *
2987 * For an incoming channel it will be called immediately after the
2988 * #GNUNET_CADET_ConnectEventHandler, also with a non-zero value.
2989 *
2990 * @param cls Channel closure.
2991 * @param channel Connection to the other end (henceforth invalid).
2992 * @param window_size New window size. If the is more messages than buffer size
2993 * this value will be negative..
2994 */
2995static void
2996channel_window_cb (void *cls,
2997 const struct GNUNET_CADET_Channel *channel,
2998 int window_size)
2999{
3000 /* FIXME: not implemented, we could do flow control here... */
3001}
3002
3003
3004/**
3005 * Called when a client wants to create a new listener.
3006 *
3007 * @param cls client that sent the message
3008 * @param msg message sent by the client
3009 */
3010static void
3011handle_client_listen (void *cls,
3012 const struct GNUNET_SETU_ListenMessage *msg)
3013{
3014 struct ClientState *cs = cls;
3015 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
3016 GNUNET_MQ_hd_var_size (incoming_msg,
3017 GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
3018 struct OperationRequestMessage,
3019 NULL),
3020 GNUNET_MQ_hd_var_size (union_p2p_ibf,
3021 GNUNET_MESSAGE_TYPE_SETU_P2P_IBF,
3022 struct IBFMessage,
3023 NULL),
3024 GNUNET_MQ_hd_var_size (union_p2p_elements,
3025 GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS,
3026 struct GNUNET_SETU_ElementMessage,
3027 NULL),
3028 GNUNET_MQ_hd_var_size (union_p2p_offer,
3029 GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER,
3030 struct GNUNET_MessageHeader,
3031 NULL),
3032 GNUNET_MQ_hd_var_size (union_p2p_inquiry,
3033 GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY,
3034 struct InquiryMessage,
3035 NULL),
3036 GNUNET_MQ_hd_var_size (union_p2p_demand,
3037 GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND,
3038 struct GNUNET_MessageHeader,
3039 NULL),
3040 GNUNET_MQ_hd_fixed_size (union_p2p_done,
3041 GNUNET_MESSAGE_TYPE_SETU_P2P_DONE,
3042 struct GNUNET_MessageHeader,
3043 NULL),
3044 GNUNET_MQ_hd_fixed_size (union_p2p_over,
3045 GNUNET_MESSAGE_TYPE_SETU_P2P_OVER,
3046 struct GNUNET_MessageHeader,
3047 NULL),
3048 GNUNET_MQ_hd_fixed_size (union_p2p_full_done,
3049 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE,
3050 struct GNUNET_MessageHeader,
3051 NULL),
3052 GNUNET_MQ_hd_fixed_size (union_p2p_request_full,
3053 GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL,
3054 struct GNUNET_MessageHeader,
3055 NULL),
3056 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
3057 GNUNET_MESSAGE_TYPE_SETU_P2P_SE,
3058 struct StrataEstimatorMessage,
3059 NULL),
3060 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
3061 GNUNET_MESSAGE_TYPE_SETU_P2P_SEC,
3062 struct StrataEstimatorMessage,
3063 NULL),
3064 GNUNET_MQ_hd_var_size (union_p2p_full_element,
3065 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT,
3066 struct GNUNET_SETU_ElementMessage,
3067 NULL),
3068 GNUNET_MQ_handler_end ()
3069 };
3070 struct Listener *listener;
3071
3072 if (NULL != cs->listener)
3073 {
3074 /* max. one active listener per client! */
3075 GNUNET_break (0);
3076 GNUNET_SERVICE_client_drop (cs->client);
3077 return;
3078 }
3079 listener = GNUNET_new (struct Listener);
3080 listener->cs = cs;
3081 cs->listener = listener;
3082 listener->app_id = msg->app_id;
3083 GNUNET_CONTAINER_DLL_insert (listener_head,
3084 listener_tail,
3085 listener);
3086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3087 "New listener created (port %s)\n",
3088 GNUNET_h2s (&listener->app_id));
3089 listener->open_port = GNUNET_CADET_open_port (cadet,
3090 &msg->app_id,
3091 &channel_new_cb,
3092 listener,
3093 &channel_window_cb,
3094 &channel_end_cb,
3095 cadet_handlers);
3096 GNUNET_SERVICE_client_continue (cs->client);
3097}
3098
3099
3100/**
3101 * Called when the listening client rejects an operation
3102 * request by another peer.
3103 *
3104 * @param cls client that sent the message
3105 * @param msg message sent by the client
3106 */
3107static void
3108handle_client_reject (void *cls,
3109 const struct GNUNET_SETU_RejectMessage *msg)
3110{
3111 struct ClientState *cs = cls;
3112 struct Operation *op;
3113
3114 op = get_incoming (ntohl (msg->accept_reject_id));
3115 if (NULL == op)
3116 {
3117 /* no matching incoming operation for this reject;
3118 could be that the other peer already disconnected... */
3119 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3120 "Client rejected unknown operation %u\n",
3121 (unsigned int) ntohl (msg->accept_reject_id));
3122 GNUNET_SERVICE_client_continue (cs->client);
3123 return;
3124 }
3125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3126 "Peer request (app %s) rejected by client\n",
3127 GNUNET_h2s (&cs->listener->app_id));
3128 _GSS_operation_destroy2 (op);
3129 GNUNET_SERVICE_client_continue (cs->client);
3130}
3131
3132
3133/**
3134 * Called when a client wants to add or remove an element to a set it inhabits.
3135 *
3136 * @param cls client that sent the message
3137 * @param msg message sent by the client
3138 */
3139static int
3140check_client_set_add (void *cls,
3141 const struct GNUNET_SETU_ElementMessage *msg)
3142{
3143 /* NOTE: Technically, we should probably check with the
3144 block library whether the element we are given is well-formed */
3145 return GNUNET_OK;
3146}
3147
3148
3149/**
3150 * Called when a client wants to add or remove an element to a set it inhabits.
3151 *
3152 * @param cls client that sent the message
3153 * @param msg message sent by the client
3154 */
3155static void
3156handle_client_set_add (void *cls,
3157 const struct GNUNET_SETU_ElementMessage *msg)
3158{
3159 struct ClientState *cs = cls;
3160 struct Set *set;
3161 struct GNUNET_SETU_Element el;
3162 struct ElementEntry *ee;
3163 struct GNUNET_HashCode hash;
3164
3165 if (NULL == (set = cs->set))
3166 {
3167 /* client without a set requested an operation */
3168 GNUNET_break (0);
3169 GNUNET_SERVICE_client_drop (cs->client);
3170 return;
3171 }
3172 GNUNET_SERVICE_client_continue (cs->client);
3173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing mutation on set\n");
3174 el.size = ntohs (msg->header.size) - sizeof(*msg);
3175 el.data = &msg[1];
3176 el.element_type = ntohs (msg->element_type);
3177 GNUNET_SETU_element_hash (&el,
3178 &hash);
3179 ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
3180 &hash);
3181 if (NULL == ee)
3182 {
3183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3184 "Client inserts element %s of size %u\n",
3185 GNUNET_h2s (&hash),
3186 el.size);
3187 ee = GNUNET_malloc (el.size + sizeof(*ee));
3188 ee->element.size = el.size;
3189 GNUNET_memcpy (&ee[1], el.data, el.size);
3190 ee->element.data = &ee[1];
3191 ee->element.element_type = el.element_type;
3192 ee->remote = GNUNET_NO;
3193 ee->generation = set->current_generation;
3194 ee->element_hash = hash;
3195 GNUNET_break (GNUNET_YES ==
3196 GNUNET_CONTAINER_multihashmap_put (
3197 set->content->elements,
3198 &ee->element_hash,
3199 ee,
3200 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
3201 }
3202 else
3203 {
3204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3205 "Client inserted element %s of size %u twice (ignored)\n",
3206 GNUNET_h2s (&hash),
3207 el.size);
3208 /* same element inserted twice */
3209 return;
3210 }
3211 strata_estimator_insert (set->se,
3212 get_ibf_key (&ee->element_hash));
3213}
3214
3215
3216/**
3217 * Advance the current generation of a set,
3218 * adding exclusion ranges if necessary.
3219 *
3220 * @param set the set where we want to advance the generation
3221 */
3222static void
3223advance_generation (struct Set *set)
3224{
3225 set->content->latest_generation++;
3226 set->current_generation++;
3227}
3228
3229
3230/**
3231 * Called when a client wants to initiate a set operation with another
3232 * peer. Initiates the CADET connection to the listener and sends the
3233 * request.
3234 *
3235 * @param cls client that sent the message
3236 * @param msg message sent by the client
3237 * @return #GNUNET_OK if the message is well-formed
3238 */
3239static int
3240check_client_evaluate (void *cls,
3241 const struct GNUNET_SETU_EvaluateMessage *msg)
3242{
3243 /* FIXME: suboptimal, even if the context below could be NULL,
3244 there are malformed messages this does not check for... */
3245 return GNUNET_OK;
3246}
3247
3248
3249/**
3250 * Called when a client wants to initiate a set operation with another
3251 * peer. Initiates the CADET connection to the listener and sends the
3252 * request.
3253 *
3254 * @param cls client that sent the message
3255 * @param msg message sent by the client
3256 */
3257static void
3258handle_client_evaluate (void *cls,
3259 const struct GNUNET_SETU_EvaluateMessage *msg)
3260{
3261 struct ClientState *cs = cls;
3262 struct Operation *op = GNUNET_new (struct Operation);
3263 const struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
3264 GNUNET_MQ_hd_var_size (incoming_msg,
3265 GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
3266 struct OperationRequestMessage,
3267 op),
3268 GNUNET_MQ_hd_var_size (union_p2p_ibf,
3269 GNUNET_MESSAGE_TYPE_SETU_P2P_IBF,
3270 struct IBFMessage,
3271 op),
3272 GNUNET_MQ_hd_var_size (union_p2p_elements,
3273 GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS,
3274 struct GNUNET_SETU_ElementMessage,
3275 op),
3276 GNUNET_MQ_hd_var_size (union_p2p_offer,
3277 GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER,
3278 struct GNUNET_MessageHeader,
3279 op),
3280 GNUNET_MQ_hd_var_size (union_p2p_inquiry,
3281 GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY,
3282 struct InquiryMessage,
3283 op),
3284 GNUNET_MQ_hd_var_size (union_p2p_demand,
3285 GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND,
3286 struct GNUNET_MessageHeader,
3287 op),
3288 GNUNET_MQ_hd_fixed_size (union_p2p_done,
3289 GNUNET_MESSAGE_TYPE_SETU_P2P_DONE,
3290 struct GNUNET_MessageHeader,
3291 op),
3292 GNUNET_MQ_hd_fixed_size (union_p2p_over,
3293 GNUNET_MESSAGE_TYPE_SETU_P2P_OVER,
3294 struct GNUNET_MessageHeader,
3295 op),
3296 GNUNET_MQ_hd_fixed_size (union_p2p_full_done,
3297 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE,
3298 struct GNUNET_MessageHeader,
3299 op),
3300 GNUNET_MQ_hd_fixed_size (union_p2p_request_full,
3301 GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL,
3302 struct GNUNET_MessageHeader,
3303 op),
3304 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
3305 GNUNET_MESSAGE_TYPE_SETU_P2P_SE,
3306 struct StrataEstimatorMessage,
3307 op),
3308 GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
3309 GNUNET_MESSAGE_TYPE_SETU_P2P_SEC,
3310 struct StrataEstimatorMessage,
3311 op),
3312 GNUNET_MQ_hd_var_size (union_p2p_full_element,
3313 GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT,
3314 struct GNUNET_SETU_ElementMessage,
3315 op),
3316 GNUNET_MQ_handler_end ()
3317 };
3318 struct Set *set;
3319 const struct GNUNET_MessageHeader *context;
3320
3321 if (NULL == (set = cs->set))
3322 {
3323 GNUNET_break (0);
3324 GNUNET_free (op);
3325 GNUNET_SERVICE_client_drop (cs->client);
3326 return;
3327 }
3328 op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
3329 UINT32_MAX);
3330 op->peer = msg->target_peer;
3331 op->client_request_id = ntohl (msg->request_id);
3332 op->byzantine = msg->byzantine;
3333 op->byzantine_lower_bound = ntohl (msg->byzantine_lower_bound);
3334 op->force_full = msg->force_full;
3335 op->force_delta = msg->force_delta;
3336 op->symmetric = msg->symmetric;
3337 context = GNUNET_MQ_extract_nested_mh (msg);
3338
3339 /* Advance generation values, so that
3340 mutations won't interfer with the running operation. */
3341 op->set = set;
3342 op->generation_created = set->current_generation;
3343 advance_generation (set);
3344 GNUNET_CONTAINER_DLL_insert (set->ops_head,
3345 set->ops_tail,
3346 op);
3347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3348 "Creating new CADET channel to port %s for set union\n",
3349 GNUNET_h2s (&msg->app_id));
3350 op->channel = GNUNET_CADET_channel_create (cadet,
3351 op,
3352 &msg->target_peer,
3353 &msg->app_id,
3354 &channel_window_cb,
3355 &channel_end_cb,
3356 cadet_handlers);
3357 op->mq = GNUNET_CADET_get_mq (op->channel);
3358 {
3359 struct GNUNET_MQ_Envelope *ev;
3360 struct OperationRequestMessage *msg;
3361
3362 ev = GNUNET_MQ_msg_nested_mh (msg,
3363 GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
3364 context);
3365 if (NULL == ev)
3366 {
3367 /* the context message is too large */
3368 GNUNET_break (0);
3369 GNUNET_SERVICE_client_drop (cs->client);
3370 return;
3371 }
3372 op->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32,
3373 GNUNET_NO);
3374 /* copy the current generation's strata estimator for this operation */
3375 op->se = strata_estimator_dup (op->set->se);
3376 /* we started the operation, thus we have to send the operation request */
3377 op->phase = PHASE_EXPECT_SE;
3378 op->salt_receive = op->salt_send = 42; // FIXME?????
3379 LOG (GNUNET_ERROR_TYPE_DEBUG,
3380 "Initiating union operation evaluation\n");
3381 GNUNET_STATISTICS_update (_GSS_statistics,
3382 "# of total union operations",
3383 1,
3384 GNUNET_NO);
3385 GNUNET_STATISTICS_update (_GSS_statistics,
3386 "# of initiated union operations",
3387 1,
3388 GNUNET_NO);
3389 GNUNET_MQ_send (op->mq,
3390 ev);
3391 if (NULL != context)
3392 LOG (GNUNET_ERROR_TYPE_DEBUG,
3393 "sent op request with context message\n");
3394 else
3395 LOG (GNUNET_ERROR_TYPE_DEBUG,
3396 "sent op request without context message\n");
3397 initialize_key_to_element (op);
3398 op->initial_size = GNUNET_CONTAINER_multihashmap32_size (
3399 op->key_to_element);
3400
3401 }
3402 GNUNET_SERVICE_client_continue (cs->client);
3403}
3404
3405
3406/**
3407 * Handle a request from the client to cancel a running set operation.
3408 *
3409 * @param cls the client
3410 * @param msg the message
3411 */
3412static void
3413handle_client_cancel (void *cls,
3414 const struct GNUNET_SETU_CancelMessage *msg)
3415{
3416 struct ClientState *cs = cls;
3417 struct Set *set;
3418 struct Operation *op;
3419 int found;
3420
3421 if (NULL == (set = cs->set))
3422 {
3423 /* client without a set requested an operation */
3424 GNUNET_break (0);
3425 GNUNET_SERVICE_client_drop (cs->client);
3426 return;
3427 }
3428 found = GNUNET_NO;
3429 for (op = set->ops_head; NULL != op; op = op->next)
3430 {
3431 if (op->client_request_id == ntohl (msg->request_id))
3432 {
3433 found = GNUNET_YES;
3434 break;
3435 }
3436 }
3437 if (GNUNET_NO == found)
3438 {
3439 /* It may happen that the operation was already destroyed due to
3440 * the other peer disconnecting. The client may not know about this
3441 * yet and try to cancel the (just barely non-existent) operation.
3442 * So this is not a hard error.
3443 *///
3444 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3445 "Client canceled non-existent op %u\n",
3446 (uint32_t) ntohl (msg->request_id));
3447 }
3448 else
3449 {
3450 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3451 "Client requested cancel for op %u\n",
3452 (uint32_t) ntohl (msg->request_id));
3453 _GSS_operation_destroy (op);
3454 }
3455 GNUNET_SERVICE_client_continue (cs->client);
3456}
3457
3458
3459/**
3460 * Handle a request from the client to accept a set operation that
3461 * came from a remote peer. We forward the accept to the associated
3462 * operation for handling
3463 *
3464 * @param cls the client
3465 * @param msg the message
3466 */
3467static void
3468handle_client_accept (void *cls,
3469 const struct GNUNET_SETU_AcceptMessage *msg)
3470{
3471 struct ClientState *cs = cls;
3472 struct Set *set;
3473 struct Operation *op;
3474 struct GNUNET_SETU_ResultMessage *result_message;
3475 struct GNUNET_MQ_Envelope *ev;
3476 struct Listener *listener;
3477
3478 if (NULL == (set = cs->set))
3479 {
3480 /* client without a set requested to accept */
3481 GNUNET_break (0);
3482 GNUNET_SERVICE_client_drop (cs->client);
3483 return;
3484 }
3485 op = get_incoming (ntohl (msg->accept_reject_id));
3486 if (NULL == op)
3487 {
3488 /* It is not an error if the set op does not exist -- it may
3489 * have been destroyed when the partner peer disconnected. */
3490 GNUNET_log (
3491 GNUNET_ERROR_TYPE_INFO,
3492 "Client %p accepted request %u of listener %p that is no longer active\n",
3493 cs,
3494 ntohl (msg->accept_reject_id),
3495 cs->listener);
3496 ev = GNUNET_MQ_msg (result_message,
3497 GNUNET_MESSAGE_TYPE_SETU_RESULT);
3498 result_message->request_id = msg->request_id;
3499 result_message->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
3500 GNUNET_MQ_send (set->cs->mq, ev);
3501 GNUNET_SERVICE_client_continue (cs->client);
3502 return;
3503 }
3504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3505 "Client accepting request %u\n",
3506 (uint32_t) ntohl (msg->accept_reject_id));
3507 listener = op->listener;
3508 op->listener = NULL;
3509 GNUNET_CONTAINER_DLL_remove (listener->op_head,
3510 listener->op_tail,
3511 op);
3512 op->set = set;
3513 GNUNET_CONTAINER_DLL_insert (set->ops_head,
3514 set->ops_tail,
3515 op);
3516 op->client_request_id = ntohl (msg->request_id);
3517 op->byzantine = msg->byzantine;
3518 op->byzantine_lower_bound = ntohl (msg->byzantine_lower_bound);
3519 op->force_full = msg->force_full;
3520 op->force_delta = msg->force_delta;
3521 op->symmetric = msg->symmetric;
3522
3523 /* Advance generation values, so that future mutations do not
3524 interfer with the running operation. */
3525 op->generation_created = set->current_generation;
3526 advance_generation (set);
3527 GNUNET_assert (NULL == op->se);
3528
3529 LOG (GNUNET_ERROR_TYPE_DEBUG,
3530 "accepting set union operation\n");
3531 GNUNET_STATISTICS_update (_GSS_statistics,
3532 "# of accepted union operations",
3533 1,
3534 GNUNET_NO);
3535 GNUNET_STATISTICS_update (_GSS_statistics,
3536 "# of total union operations",
3537 1,
3538 GNUNET_NO);
3539 {
3540 const struct StrataEstimator *se;
3541 struct GNUNET_MQ_Envelope *ev;
3542 struct StrataEstimatorMessage *strata_msg;
3543 char *buf;
3544 size_t len;
3545 uint16_t type;
3546
3547 op->se = strata_estimator_dup (op->set->se);
3548 op->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32,
3549 GNUNET_NO);
3550 op->salt_receive = op->salt_send = 42; // FIXME?????
3551 initialize_key_to_element (op);
3552 op->initial_size = GNUNET_CONTAINER_multihashmap32_size (
3553 op->key_to_element);
3554
3555 /* kick off the operation */
3556 se = op->se;
3557 buf = GNUNET_malloc (se->strata_count * IBF_BUCKET_SIZE * se->ibf_size);
3558 len = strata_estimator_write (se,
3559 buf);
3560 if (len < se->strata_count * IBF_BUCKET_SIZE * se->ibf_size)
3561 type = GNUNET_MESSAGE_TYPE_SETU_P2P_SEC;
3562 else
3563 type = GNUNET_MESSAGE_TYPE_SETU_P2P_SE;
3564 ev = GNUNET_MQ_msg_extra (strata_msg,
3565 len,
3566 type);
3567 GNUNET_memcpy (&strata_msg[1],
3568 buf,
3569 len);
3570 GNUNET_free (buf);
3571 strata_msg->set_size
3572 = GNUNET_htonll (GNUNET_CONTAINER_multihashmap_size (
3573 op->set->content->elements));
3574 GNUNET_MQ_send (op->mq,
3575 ev);
3576 op->phase = PHASE_EXPECT_IBF;
3577 }
3578 /* Now allow CADET to continue, as we did not do this in
3579 #handle_incoming_msg (as we wanted to first see if the
3580 local client would accept the request). */
3581 GNUNET_CADET_receive_done (op->channel);
3582 GNUNET_SERVICE_client_continue (cs->client);
3583}
3584
3585
3586/**
3587 * Called to clean up, after a shutdown has been requested.
3588 *
3589 * @param cls closure, NULL
3590 */
3591static void
3592shutdown_task (void *cls)
3593{
3594 /* Delay actual shutdown to allow service to disconnect clients */
3595 in_shutdown = GNUNET_YES;
3596 if (0 == num_clients)
3597 {
3598 if (NULL != cadet)
3599 {
3600 GNUNET_CADET_disconnect (cadet);
3601 cadet = NULL;
3602 }
3603 }
3604 GNUNET_STATISTICS_destroy (_GSS_statistics,
3605 GNUNET_YES);
3606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3607 "handled shutdown request\n");
3608}
3609
3610
3611/**
3612 * Function called by the service's run
3613 * method to run service-specific setup code.
3614 *
3615 * @param cls closure
3616 * @param cfg configuration to use
3617 * @param service the initialized service
3618 */
3619static void
3620run (void *cls,
3621 const struct GNUNET_CONFIGURATION_Handle *cfg,
3622 struct GNUNET_SERVICE_Handle *service)
3623{
3624 /* FIXME: need to modify SERVICE (!) API to allow
3625 us to run a shutdown task *after* clients were
3626 forcefully disconnected! */
3627 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
3628 NULL);
3629 _GSS_statistics = GNUNET_STATISTICS_create ("setu",
3630 cfg);
3631 cadet = GNUNET_CADET_connect (cfg);
3632 if (NULL == cadet)
3633 {
3634 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3635 _ ("Could not connect to CADET service\n"));
3636 GNUNET_SCHEDULER_shutdown ();
3637 return;
3638 }
3639}
3640
3641
3642/**
3643 * Define "main" method using service macro.
3644 */
3645GNUNET_SERVICE_MAIN (
3646 "set",
3647 GNUNET_SERVICE_OPTION_NONE,
3648 &run,
3649 &client_connect_cb,
3650 &client_disconnect_cb,
3651 NULL,
3652 GNUNET_MQ_hd_fixed_size (client_accept,
3653 GNUNET_MESSAGE_TYPE_SETU_ACCEPT,
3654 struct GNUNET_SETU_AcceptMessage,
3655 NULL),
3656 GNUNET_MQ_hd_var_size (client_set_add,
3657 GNUNET_MESSAGE_TYPE_SETU_ADD,
3658 struct GNUNET_SETU_ElementMessage,
3659 NULL),
3660 GNUNET_MQ_hd_fixed_size (client_create_set,
3661 GNUNET_MESSAGE_TYPE_SETU_CREATE,
3662 struct GNUNET_SETU_CreateMessage,
3663 NULL),
3664 GNUNET_MQ_hd_var_size (client_evaluate,
3665 GNUNET_MESSAGE_TYPE_SETU_EVALUATE,
3666 struct GNUNET_SETU_EvaluateMessage,
3667 NULL),
3668 GNUNET_MQ_hd_fixed_size (client_listen,
3669 GNUNET_MESSAGE_TYPE_SETU_LISTEN,
3670 struct GNUNET_SETU_ListenMessage,
3671 NULL),
3672 GNUNET_MQ_hd_fixed_size (client_reject,
3673 GNUNET_MESSAGE_TYPE_SETU_REJECT,
3674 struct GNUNET_SETU_RejectMessage,
3675 NULL),
3676 GNUNET_MQ_hd_fixed_size (client_cancel,
3677 GNUNET_MESSAGE_TYPE_SETU_CANCEL,
3678 struct GNUNET_SETU_CancelMessage,
3679 NULL),
3680 GNUNET_MQ_handler_end ());
3681
3682
3683/* end of gnunet-service-setu.c */
diff --git a/src/setu/gnunet-service-setu_protocol.h b/src/setu/gnunet-service-setu_protocol.h
new file mode 100644
index 000000000..a2803ee47
--- /dev/null
+++ b/src/setu/gnunet-service-setu_protocol.h
@@ -0,0 +1,226 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Florian Dold
22 * @author Christian Grothoff
23 * @file set/gnunet-service-set_protocol.h
24 * @brief Peer-to-Peer messages for gnunet set
25 */
26#ifndef SET_PROTOCOL_H
27#define SET_PROTOCOL_H
28
29#include "platform.h"
30#include "gnunet_common.h"
31
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35struct OperationRequestMessage
36{
37 /**
38 * Type: #GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
39 */
40 struct GNUNET_MessageHeader header;
41
42 /**
43 * Operation to request, values from `enum GNUNET_SET_OperationType`
44 */
45 uint32_t operation GNUNET_PACKED;
46
47 /**
48 * For Intersection: my element count
49 */
50 uint32_t element_count GNUNET_PACKED;
51
52 /**
53 * Application-specific identifier of the request.
54 */
55 struct GNUNET_HashCode app_idX;
56
57 /* rest: optional message */
58};
59
60
61/**
62 * Message containing buckets of an invertible bloom filter.
63 *
64 * If an IBF has too many buckets for an IBF message,
65 * it is split into multiple messages.
66 */
67struct IBFMessage
68{
69 /**
70 * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
71 */
72 struct GNUNET_MessageHeader header;
73
74 /**
75 * Order of the whole ibf, where
76 * num_buckets = 2^order
77 */
78 uint8_t order;
79
80 /**
81 * Padding, must be 0.
82 */
83 uint8_t reserved1;
84
85 /**
86 * Padding, must be 0.
87 */
88 uint16_t reserved2 GNUNET_PACKED;
89
90 /**
91 * Offset of the strata in the rest of the message
92 */
93 uint32_t offset GNUNET_PACKED;
94
95 /**
96 * Salt used when hashing elements for this IBF.
97 */
98 uint32_t salt GNUNET_PACKED;
99
100 /* rest: buckets */
101};
102
103
104struct InquiryMessage
105{
106 /**
107 * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
108 */
109 struct GNUNET_MessageHeader header;
110
111 /**
112 * Salt used when hashing elements for this inquiry.
113 */
114 uint32_t salt GNUNET_PACKED;
115
116 /**
117 * Reserved, set to 0.
118 */
119 uint32_t reserved GNUNET_PACKED;
120
121 /* rest: inquiry IBF keys */
122};
123
124
125/**
126 * During intersection, the first (and possibly second) message
127 * send it the number of elements in the set, to allow the peers
128 * to decide who should start with the Bloom filter.
129 */
130struct IntersectionElementInfoMessage
131{
132 /**
133 * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO
134 */
135 struct GNUNET_MessageHeader header;
136
137 /**
138 * mutator used with this bloomfilter.
139 */
140 uint32_t sender_element_count GNUNET_PACKED;
141};
142
143
144/**
145 * Bloom filter messages exchanged for set intersection calculation.
146 */
147struct BFMessage
148{
149 /**
150 * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF
151 */
152 struct GNUNET_MessageHeader header;
153
154 /**
155 * Number of elements the sender still has in the set.
156 */
157 uint32_t sender_element_count GNUNET_PACKED;
158
159 /**
160 * XOR of all hashes over all elements remaining in the set.
161 * Used to determine termination.
162 */
163 struct GNUNET_HashCode element_xor_hash;
164
165 /**
166 * Mutator used with this bloomfilter.
167 */
168 uint32_t sender_mutator GNUNET_PACKED;
169
170 /**
171 * Total length of the bloomfilter data.
172 */
173 uint32_t bloomfilter_total_length GNUNET_PACKED;
174
175 /**
176 * Number of bits (k-value) used in encoding the bloomfilter.
177 */
178 uint32_t bits_per_element GNUNET_PACKED;
179
180 /**
181 * rest: the sender's bloomfilter
182 */
183};
184
185
186/**
187 * Last message, send to confirm the final set. Contains the element
188 * count as it is possible that the peer determined that we were done
189 * by getting the empty set, which in that case also needs to be
190 * communicated.
191 */
192struct IntersectionDoneMessage
193{
194 /**
195 * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE
196 */
197 struct GNUNET_MessageHeader header;
198
199 /**
200 * Final number of elements in intersection.
201 */
202 uint32_t final_element_count GNUNET_PACKED;
203
204 /**
205 * XOR of all hashes over all elements remaining in the set.
206 */
207 struct GNUNET_HashCode element_xor_hash;
208};
209
210
211/**
212 * Strata estimator together with the peer's overall set size.
213 */
214struct StrataEstimatorMessage
215{
216 /**
217 * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
218 */
219 struct GNUNET_MessageHeader header;
220
221 uint64_t set_size;
222};
223
224GNUNET_NETWORK_STRUCT_END
225
226#endif
diff --git a/src/setu/gnunet-service-setu_strata_estimator.c b/src/setu/gnunet-service-setu_strata_estimator.c
new file mode 100644
index 000000000..0fa6a6f17
--- /dev/null
+++ b/src/setu/gnunet-service-setu_strata_estimator.c
@@ -0,0 +1,303 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file set/gnunet-service-setu_strata_estimator.c
22 * @brief invertible bloom filter
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "ibf.h"
29#include "gnunet-service-setu_strata_estimator.h"
30
31
32/**
33 * Should we try compressing the strata estimator? This will
34 * break compatibility with the 0.10.1-network.
35 */
36#define FAIL_10_1_COMPATIBILTIY 1
37
38
39/**
40 * Write the given strata estimator to the buffer.
41 *
42 * @param se strata estimator to serialize
43 * @param[out] buf buffer to write to, must be of appropriate size
44 * @return number of bytes written to @a buf
45 */
46size_t
47strata_estimator_write (const struct StrataEstimator *se,
48 void *buf)
49{
50 char *sbuf = buf;
51 unsigned int i;
52 size_t osize;
53
54 GNUNET_assert (NULL != se);
55 for (i = 0; i < se->strata_count; i++)
56 {
57 ibf_write_slice (se->strata[i],
58 0,
59 se->ibf_size,
60 &sbuf[se->ibf_size * IBF_BUCKET_SIZE * i]);
61 }
62 osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
63#if FAIL_10_1_COMPATIBILTIY
64 {
65 char *cbuf;
66 size_t nsize;
67
68 if (GNUNET_YES ==
69 GNUNET_try_compression (buf,
70 osize,
71 &cbuf,
72 &nsize))
73 {
74 GNUNET_memcpy (buf, cbuf, nsize);
75 osize = nsize;
76 GNUNET_free (cbuf);
77 }
78 }
79#endif
80 return osize;
81}
82
83
84/**
85 * Read strata from the buffer into the given strata
86 * estimator. The strata estimator must already be allocated.
87 *
88 * @param buf buffer to read from
89 * @param buf_len number of bytes in @a buf
90 * @param is_compressed is the data compressed?
91 * @param[out] se strata estimator to write to
92 * @return #GNUNET_OK on success
93 */
94int
95strata_estimator_read (const void *buf,
96 size_t buf_len,
97 int is_compressed,
98 struct StrataEstimator *se)
99{
100 unsigned int i;
101 size_t osize;
102 char *dbuf;
103
104 dbuf = NULL;
105 if (GNUNET_YES == is_compressed)
106 {
107 osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
108 dbuf = GNUNET_decompress (buf,
109 buf_len,
110 osize);
111 if (NULL == dbuf)
112 {
113 GNUNET_break_op (0); /* bad compressed input data */
114 return GNUNET_SYSERR;
115 }
116 buf = dbuf;
117 buf_len = osize;
118 }
119
120 if (buf_len != se->strata_count * se->ibf_size * IBF_BUCKET_SIZE)
121 {
122 GNUNET_break (0); /* very odd error */
123 GNUNET_free (dbuf);
124 return GNUNET_SYSERR;
125 }
126
127 for (i = 0; i < se->strata_count; i++)
128 {
129 ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]);
130 buf += se->ibf_size * IBF_BUCKET_SIZE;
131 }
132 GNUNET_free (dbuf);
133 return GNUNET_OK;
134}
135
136
137/**
138 * Add a key to the strata estimator.
139 *
140 * @param se strata estimator to add the key to
141 * @param key key to add
142 */
143void
144strata_estimator_insert (struct StrataEstimator *se,
145 struct IBF_Key key)
146{
147 uint64_t v;
148 unsigned int i;
149
150 v = key.key_val;
151 /* count trailing '1'-bits of v */
152 for (i = 0; v & 1; v >>= 1, i++)
153 /* empty */;
154 ibf_insert (se->strata[i], key);
155}
156
157
158/**
159 * Remove a key from the strata estimator.
160 *
161 * @param se strata estimator to remove the key from
162 * @param key key to remove
163 */
164void
165strata_estimator_remove (struct StrataEstimator *se,
166 struct IBF_Key key)
167{
168 uint64_t v;
169 unsigned int i;
170
171 v = key.key_val;
172 /* count trailing '1'-bits of v */
173 for (i = 0; v & 1; v >>= 1, i++)
174 /* empty */;
175 ibf_remove (se->strata[i], key);
176}
177
178
179/**
180 * Create a new strata estimator with the given parameters.
181 *
182 * @param strata_count number of stratas, that is, number of ibfs in the estimator
183 * @param ibf_size size of each ibf stratum
184 * @param ibf_hashnum hashnum parameter of each ibf
185 * @return a freshly allocated, empty strata estimator, NULL on error
186 */
187struct StrataEstimator *
188strata_estimator_create (unsigned int strata_count,
189 uint32_t ibf_size,
190 uint8_t ibf_hashnum)
191{
192 struct StrataEstimator *se;
193 unsigned int i;
194 unsigned int j;
195
196 se = GNUNET_new (struct StrataEstimator);
197 se->strata_count = strata_count;
198 se->ibf_size = ibf_size;
199 se->strata = GNUNET_new_array (strata_count,
200 struct InvertibleBloomFilter *);
201 for (i = 0; i < strata_count; i++)
202 {
203 se->strata[i] = ibf_create (ibf_size, ibf_hashnum);
204 if (NULL == se->strata[i])
205 {
206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
207 "Failed to allocate memory for strata estimator\n");
208 for (j = 0; j < i; j++)
209 ibf_destroy (se->strata[i]);
210 GNUNET_free (se);
211 return NULL;
212 }
213 }
214 return se;
215}
216
217
218/**
219 * Estimate set difference with two strata estimators,
220 * i.e. arrays of IBFs.
221 * Does not not modify its arguments.
222 *
223 * @param se1 first strata estimator
224 * @param se2 second strata estimator
225 * @return the estimated difference
226 */
227unsigned int
228strata_estimator_difference (const struct StrataEstimator *se1,
229 const struct StrataEstimator *se2)
230{
231 unsigned int count;
232
233 GNUNET_assert (se1->strata_count == se2->strata_count);
234 count = 0;
235 for (int i = se1->strata_count - 1; i >= 0; i--)
236 {
237 struct InvertibleBloomFilter *diff;
238 /* number of keys decoded from the ibf */
239
240 /* FIXME: implement this without always allocating new IBFs */
241 diff = ibf_dup (se1->strata[i]);
242 ibf_subtract (diff, se2->strata[i]);
243 for (int ibf_count = 0; GNUNET_YES; ibf_count++)
244 {
245 int more;
246
247 more = ibf_decode (diff, NULL, NULL);
248 if (GNUNET_NO == more)
249 {
250 count += ibf_count;
251 break;
252 }
253 /* Estimate if decoding fails or would not terminate */
254 if ((GNUNET_SYSERR == more) || (ibf_count > diff->size))
255 {
256 ibf_destroy (diff);
257 return count * (1 << (i + 1));
258 }
259 }
260 ibf_destroy (diff);
261 }
262 return count;
263}
264
265
266/**
267 * Make a copy of a strata estimator.
268 *
269 * @param se the strata estimator to copy
270 * @return the copy
271 */
272struct StrataEstimator *
273strata_estimator_dup (struct StrataEstimator *se)
274{
275 struct StrataEstimator *c;
276 unsigned int i;
277
278 c = GNUNET_new (struct StrataEstimator);
279 c->strata_count = se->strata_count;
280 c->ibf_size = se->ibf_size;
281 c->strata = GNUNET_new_array (se->strata_count,
282 struct InvertibleBloomFilter *);
283 for (i = 0; i < se->strata_count; i++)
284 c->strata[i] = ibf_dup (se->strata[i]);
285 return c;
286}
287
288
289/**
290 * Destroy a strata estimator, free all of its resources.
291 *
292 * @param se strata estimator to destroy.
293 */
294void
295strata_estimator_destroy (struct StrataEstimator *se)
296{
297 unsigned int i;
298
299 for (i = 0; i < se->strata_count; i++)
300 ibf_destroy (se->strata[i]);
301 GNUNET_free (se->strata);
302 GNUNET_free (se);
303}
diff --git a/src/setu/gnunet-service-setu_strata_estimator.h b/src/setu/gnunet-service-setu_strata_estimator.h
new file mode 100644
index 000000000..afdbcdbbf
--- /dev/null
+++ b/src/setu/gnunet-service-setu_strata_estimator.h
@@ -0,0 +1,169 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/gnunet-service-setu_strata_estimator.h
23 * @brief estimator of set difference
24 * @author Florian Dold
25 */
26
27#ifndef GNUNET_SERVICE_SETU_STRATA_ESTIMATOR_H
28#define GNUNET_SERVICE_SETU_STRATA_ESTIMATOR_H
29
30#include "platform.h"
31#include "gnunet_common.h"
32#include "gnunet_util_lib.h"
33
34#ifdef __cplusplus
35extern "C"
36{
37#if 0 /* keep Emacsens' auto-indent happy */
38}
39#endif
40#endif
41
42
43/**
44 * A handle to a strata estimator.
45 */
46struct StrataEstimator
47{
48 /**
49 * The IBFs of this strata estimator.
50 */
51 struct InvertibleBloomFilter **strata;
52
53 /**
54 * Size of the IBF array in @e strata
55 */
56 unsigned int strata_count;
57
58 /**
59 * Size of each IBF stratum (in bytes)
60 */
61 unsigned int ibf_size;
62};
63
64
65/**
66 * Write the given strata estimator to the buffer.
67 *
68 * @param se strata estimator to serialize
69 * @param[out] buf buffer to write to, must be of appropriate size
70 * @return number of bytes written to @a buf
71 */
72size_t
73strata_estimator_write (const struct StrataEstimator *se,
74 void *buf);
75
76
77/**
78 * Read strata from the buffer into the given strata
79 * estimator. The strata estimator must already be allocated.
80 *
81 * @param buf buffer to read from
82 * @param buf_len number of bytes in @a buf
83 * @param is_compressed is the data compressed?
84 * @param[out] se strata estimator to write to
85 * @return #GNUNET_OK on success
86 */
87int
88strata_estimator_read (const void *buf,
89 size_t buf_len,
90 int is_compressed,
91 struct StrataEstimator *se);
92
93
94/**
95 * Create a new strata estimator with the given parameters.
96 *
97 * @param strata_count number of stratas, that is, number of ibfs in the estimator
98 * @param ibf_size size of each ibf stratum
99 * @param ibf_hashnum hashnum parameter of each ibf
100 * @return a freshly allocated, empty strata estimator, NULL on error
101 */
102struct StrataEstimator *
103strata_estimator_create (unsigned int strata_count,
104 uint32_t ibf_size,
105 uint8_t ibf_hashnum);
106
107
108/**
109 * Get an estimation of the symmetric difference of the elements
110 * contained in both strata estimators.
111 *
112 * @param se1 first strata estimator
113 * @param se2 second strata estimator
114 * @return abs(|se1| - |se2|)
115 */
116unsigned int
117strata_estimator_difference (const struct StrataEstimator *se1,
118 const struct StrataEstimator *se2);
119
120
121/**
122 * Add a key to the strata estimator.
123 *
124 * @param se strata estimator to add the key to
125 * @param key key to add
126 */
127void
128strata_estimator_insert (struct StrataEstimator *se,
129 struct IBF_Key key);
130
131
132/**
133 * Remove a key from the strata estimator.
134 *
135 * @param se strata estimator to remove the key from
136 * @param key key to remove
137 */
138void
139strata_estimator_remove (struct StrataEstimator *se,
140 struct IBF_Key key);
141
142
143/**
144 * Destroy a strata estimator, free all of its resources.
145 *
146 * @param se strata estimator to destroy.
147 */
148void
149strata_estimator_destroy (struct StrataEstimator *se);
150
151
152/**
153 * Make a copy of a strata estimator.
154 *
155 * @param se the strata estimator to copy
156 * @return the copy
157 */
158struct StrataEstimator *
159strata_estimator_dup (struct StrataEstimator *se);
160
161
162#if 0 /* keep Emacsens' auto-indent happy */
163{
164#endif
165#ifdef __cplusplus
166}
167#endif
168
169#endif
diff --git a/src/setu/gnunet-setu-ibf-profiler.c b/src/setu/gnunet-setu-ibf-profiler.c
new file mode 100644
index 000000000..944b63d30
--- /dev/null
+++ b/src/setu/gnunet-setu-ibf-profiler.c
@@ -0,0 +1,308 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/gnunet-set-ibf-profiler.c
23 * @brief tool for profiling the invertible bloom filter implementation
24 * @author Florian Dold
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30#include "ibf.h"
31
32static unsigned int asize = 10;
33static unsigned int bsize = 10;
34static unsigned int csize = 10;
35static unsigned int hash_num = 4;
36static unsigned int ibf_size = 80;
37
38/* FIXME: add parameter for this */
39static enum GNUNET_CRYPTO_Quality random_quality = GNUNET_CRYPTO_QUALITY_WEAK;
40
41static struct GNUNET_CONTAINER_MultiHashMap *set_a;
42static struct GNUNET_CONTAINER_MultiHashMap *set_b;
43/* common elements in a and b */
44static struct GNUNET_CONTAINER_MultiHashMap *set_c;
45
46static struct GNUNET_CONTAINER_MultiHashMap *key_to_hashcode;
47
48static struct InvertibleBloomFilter *ibf_a;
49static struct InvertibleBloomFilter *ibf_b;
50
51
52static void
53register_hashcode (struct GNUNET_HashCode *hash)
54{
55 struct GNUNET_HashCode replicated;
56 struct IBF_Key key;
57
58 key = ibf_key_from_hashcode (hash);
59 ibf_hashcode_from_key (key, &replicated);
60 (void) GNUNET_CONTAINER_multihashmap_put (
61 key_to_hashcode,
62 &replicated,
63 GNUNET_memdup (hash, sizeof *hash),
64 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
65}
66
67
68static void
69iter_hashcodes (struct IBF_Key key,
70 GNUNET_CONTAINER_MulitHashMapIteratorCallback iter,
71 void *cls)
72{
73 struct GNUNET_HashCode replicated;
74
75 ibf_hashcode_from_key (key, &replicated);
76 GNUNET_CONTAINER_multihashmap_get_multiple (key_to_hashcode,
77 &replicated,
78 iter,
79 cls);
80}
81
82
83static int
84insert_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
85{
86 struct InvertibleBloomFilter *ibf = cls;
87
88 ibf_insert (ibf, ibf_key_from_hashcode (key));
89 return GNUNET_YES;
90}
91
92
93static int
94remove_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
95{
96 struct GNUNET_CONTAINER_MultiHashMap *hashmap = cls;
97
98 /* if remove fails, there just was a collision with another key */
99 (void) GNUNET_CONTAINER_multihashmap_remove (hashmap, value, NULL);
100 return GNUNET_YES;
101}
102
103
104static void
105run (void *cls,
106 char *const *args,
107 const char *cfgfile,
108 const struct GNUNET_CONFIGURATION_Handle *cfg)
109{
110 struct GNUNET_HashCode id;
111 struct IBF_Key ibf_key;
112 int i;
113 int side;
114 int res;
115 struct GNUNET_TIME_Absolute start_time;
116 struct GNUNET_TIME_Relative delta_time;
117
118 set_a =
119 GNUNET_CONTAINER_multihashmap_create (((asize == 0) ? 1 : (asize + csize)),
120 GNUNET_NO);
121 set_b =
122 GNUNET_CONTAINER_multihashmap_create (((bsize == 0) ? 1 : (bsize + csize)),
123 GNUNET_NO);
124 set_c = GNUNET_CONTAINER_multihashmap_create (((csize == 0) ? 1 : csize),
125 GNUNET_NO);
126
127 key_to_hashcode =
128 GNUNET_CONTAINER_multihashmap_create (((asize + bsize + csize == 0)
129 ? 1
130 : (asize + bsize + csize)),
131 GNUNET_NO);
132
133 printf ("hash-num=%u, size=%u, #(A-B)=%u, #(B-A)=%u, #(A&B)=%u\n",
134 hash_num,
135 ibf_size,
136 asize,
137 bsize,
138 csize);
139
140 i = 0;
141 while (i < asize)
142 {
143 GNUNET_CRYPTO_hash_create_random (random_quality, &id);
144 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
145 continue;
146 GNUNET_break (GNUNET_OK ==
147 GNUNET_CONTAINER_multihashmap_put (
148 set_a,
149 &id,
150 NULL,
151 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
152 register_hashcode (&id);
153 i++;
154 }
155 i = 0;
156 while (i < bsize)
157 {
158 GNUNET_CRYPTO_hash_create_random (random_quality, &id);
159 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
160 continue;
161 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id))
162 continue;
163 GNUNET_break (GNUNET_OK ==
164 GNUNET_CONTAINER_multihashmap_put (
165 set_b,
166 &id,
167 NULL,
168 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
169 register_hashcode (&id);
170 i++;
171 }
172 i = 0;
173 while (i < csize)
174 {
175 GNUNET_CRYPTO_hash_create_random (random_quality, &id);
176 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
177 continue;
178 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id))
179 continue;
180 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_c, &id))
181 continue;
182 GNUNET_break (GNUNET_OK ==
183 GNUNET_CONTAINER_multihashmap_put (
184 set_c,
185 &id,
186 NULL,
187 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
188 register_hashcode (&id);
189 i++;
190 }
191
192 ibf_a = ibf_create (ibf_size, hash_num);
193 ibf_b = ibf_create (ibf_size, hash_num);
194 if ((NULL == ibf_a) || (NULL == ibf_b))
195 {
196 /* insufficient memory */
197 GNUNET_break (0);
198 GNUNET_SCHEDULER_shutdown ();
199 return;
200 }
201
202
203 printf ("generated sets\n");
204
205 start_time = GNUNET_TIME_absolute_get ();
206
207 GNUNET_CONTAINER_multihashmap_iterate (set_a, &insert_iterator, ibf_a);
208 GNUNET_CONTAINER_multihashmap_iterate (set_b, &insert_iterator, ibf_b);
209 GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_a);
210 GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_b);
211
212 delta_time = GNUNET_TIME_absolute_get_duration (start_time);
213
214 printf ("encoded in: %s\n",
215 GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO));
216
217 ibf_subtract (ibf_a, ibf_b);
218
219
220 start_time = GNUNET_TIME_absolute_get ();
221
222 for (i = 0; i <= asize + bsize; i++)
223 {
224 res = ibf_decode (ibf_a, &side, &ibf_key);
225 if (GNUNET_SYSERR == res)
226 {
227 printf ("decode failed, %u/%u elements left\n",
228 GNUNET_CONTAINER_multihashmap_size (set_a)
229 + GNUNET_CONTAINER_multihashmap_size (set_b),
230 asize + bsize);
231 return;
232 }
233 if (GNUNET_NO == res)
234 {
235 if ((0 == GNUNET_CONTAINER_multihashmap_size (set_b)) &&
236 (0 == GNUNET_CONTAINER_multihashmap_size (set_a)))
237 {
238 delta_time = GNUNET_TIME_absolute_get_duration (start_time);
239 printf ("decoded successfully in: %s\n",
240 GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO));
241 }
242 else
243 {
244 printf ("decode missed elements (should never happen)\n");
245 }
246 return;
247 }
248
249 if (side == 1)
250 iter_hashcodes (ibf_key, remove_iterator, set_a);
251 if (side == -1)
252 iter_hashcodes (ibf_key, remove_iterator, set_b);
253 }
254 printf ("cyclic IBF, %u/%u elements left\n",
255 GNUNET_CONTAINER_multihashmap_size (set_a)
256 + GNUNET_CONTAINER_multihashmap_size (set_b),
257 asize + bsize);
258}
259
260
261int
262main (int argc, char **argv)
263{
264 struct GNUNET_GETOPT_CommandLineOption options[] = {
265 GNUNET_GETOPT_option_uint ('A',
266 "asize",
267 NULL,
268 gettext_noop ("number of element in set A-B"),
269 &asize),
270
271 GNUNET_GETOPT_option_uint ('B',
272 "bsize",
273 NULL,
274 gettext_noop ("number of element in set B-A"),
275 &bsize),
276
277 GNUNET_GETOPT_option_uint ('C',
278 "csize",
279 NULL,
280 gettext_noop (
281 "number of common elements in A and B"),
282 &csize),
283
284 GNUNET_GETOPT_option_uint ('k',
285 "hash-num",
286 NULL,
287 gettext_noop ("hash num"),
288 &hash_num),
289
290 GNUNET_GETOPT_option_uint ('s',
291 "ibf-size",
292 NULL,
293 gettext_noop ("ibf size"),
294 &ibf_size),
295
296 GNUNET_GETOPT_OPTION_END
297 };
298
299 GNUNET_PROGRAM_run2 (argc,
300 argv,
301 "gnunet-consensus-ibf",
302 "help",
303 options,
304 &run,
305 NULL,
306 GNUNET_YES);
307 return 0;
308}
diff --git a/src/setu/gnunet-setu-profiler.c b/src/setu/gnunet-setu-profiler.c
new file mode 100644
index 000000000..8d6a2dc8c
--- /dev/null
+++ b/src/setu/gnunet-setu-profiler.c
@@ -0,0 +1,499 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file setu/gnunet-setu-profiler.c
23 * @brief profiling tool for set
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_statistics_service.h"
29#include "gnunet_setu_service.h"
30#include "gnunet_testbed_service.h"
31
32
33static int ret;
34
35static unsigned int num_a = 5;
36static unsigned int num_b = 5;
37static unsigned int num_c = 20;
38
39static char *op_str = "union";
40
41const static struct GNUNET_CONFIGURATION_Handle *config;
42
43struct SetInfo
44{
45 char *id;
46 struct GNUNET_SETU_Handle *set;
47 struct GNUNET_SETU_OperationHandle *oh;
48 struct GNUNET_CONTAINER_MultiHashMap *sent;
49 struct GNUNET_CONTAINER_MultiHashMap *received;
50 int done;
51} info1, info2;
52
53static struct GNUNET_CONTAINER_MultiHashMap *common_sent;
54
55static struct GNUNET_HashCode app_id;
56
57static struct GNUNET_PeerIdentity local_peer;
58
59static struct GNUNET_SETU_ListenHandle *set_listener;
60
61static int byzantine;
62static unsigned int force_delta;
63static unsigned int force_full;
64static unsigned int element_size = 32;
65
66/**
67 * Handle to the statistics service.
68 */
69static struct GNUNET_STATISTICS_Handle *statistics;
70
71/**
72 * The profiler will write statistics
73 * for all peers to the file with this name.
74 */
75static char *statistics_filename;
76
77/**
78 * The profiler will write statistics
79 * for all peers to this file.
80 */
81static FILE *statistics_file;
82
83
84static int
85map_remove_iterator (void *cls,
86 const struct GNUNET_HashCode *key,
87 void *value)
88{
89 struct GNUNET_CONTAINER_MultiHashMap *m = cls;
90 int ret;
91
92 GNUNET_assert (NULL != key);
93
94 ret = GNUNET_CONTAINER_multihashmap_remove_all (m, key);
95 if (GNUNET_OK != ret)
96 printf ("spurious element\n");
97 return GNUNET_YES;
98}
99
100
101/**
102 * Callback function to process statistic values.
103 *
104 * @param cls closure
105 * @param subsystem name of subsystem that created the statistic
106 * @param name the name of the datum
107 * @param value the current value
108 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
109 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
110 */
111static int
112statistics_result (void *cls,
113 const char *subsystem,
114 const char *name,
115 uint64_t value,
116 int is_persistent)
117{
118 if (NULL != statistics_file)
119 {
120 fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
121 long) value);
122 }
123 return GNUNET_OK;
124}
125
126
127static void
128statistics_done (void *cls,
129 int success)
130{
131 GNUNET_assert (GNUNET_YES == success);
132 if (NULL != statistics_file)
133 fclose (statistics_file);
134 GNUNET_SCHEDULER_shutdown ();
135}
136
137
138static void
139check_all_done (void)
140{
141 if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
142 return;
143
144 GNUNET_CONTAINER_multihashmap_iterate (info1.received, map_remove_iterator,
145 info2.sent);
146 GNUNET_CONTAINER_multihashmap_iterate (info2.received, map_remove_iterator,
147 info1.sent);
148
149 printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
150 info1.sent));
151 printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
152 info2.sent));
153
154 if (NULL == statistics_filename)
155 {
156 GNUNET_SCHEDULER_shutdown ();
157 return;
158 }
159
160 statistics_file = fopen (statistics_filename, "w");
161 GNUNET_STATISTICS_get (statistics, NULL, NULL,
162 &statistics_done,
163 &statistics_result, NULL);
164}
165
166
167static void
168set_result_cb (void *cls,
169 const struct GNUNET_SETU_Element *element,
170 uint64_t current_size,
171 enum GNUNET_SETU_Status status)
172{
173 struct SetInfo *info = cls;
174
175 GNUNET_assert (GNUNET_NO == info->done);
176 switch (status)
177 {
178 case GNUNET_SETU_STATUS_DONE:
179 info->done = GNUNET_YES;
180 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id);
181 check_all_done ();
182 info->oh = NULL;
183 return;
184
185 case GNUNET_SETU_STATUS_FAILURE:
186 info->oh = NULL;
187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n");
188 GNUNET_SCHEDULER_shutdown ();
189 return;
190
191 case GNUNET_SETU_STATUS_ADD_LOCAL:
192 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: local element\n", info->id);
193 break;
194 default:
195 GNUNET_assert (0);
196 }
197
198 if (element->size != element_size)
199 {
200 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
201 "wrong element size: %u, expected %u\n",
202 element->size,
203 (unsigned int) sizeof(struct GNUNET_HashCode));
204 GNUNET_assert (0);
205 }
206
207 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n",
208 info->id, GNUNET_h2s (element->data));
209 GNUNET_assert (NULL != element->data);
210 struct GNUNET_HashCode data_hash;
211 GNUNET_CRYPTO_hash (element->data, element_size, &data_hash);
212 GNUNET_CONTAINER_multihashmap_put (info->received,
213 &data_hash, NULL,
214 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
215}
216
217
218static void
219set_listen_cb (void *cls,
220 const struct GNUNET_PeerIdentity *other_peer,
221 const struct GNUNET_MessageHeader *context_msg,
222 struct GNUNET_SETU_Request *request)
223{
224 /* max. 2 options plus terminator */
225 struct GNUNET_SETU_Option opts[3] = { { 0 } };
226 unsigned int n_opts = 0;
227
228 if (NULL == request)
229 {
230 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
231 "listener failed\n");
232 return;
233 }
234 GNUNET_assert (NULL == info2.oh);
235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
236 "set listen cb called\n");
237 if (byzantine)
238 {
239 opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
240 GNUNET_SETU_OPTION_BYZANTINE };
241 }
242 GNUNET_assert (! (force_full && force_delta));
243 if (force_full)
244 {
245 opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
246 GNUNET_SETU_OPTION_FORCE_FULL };
247 }
248 if (force_delta)
249 {
250 opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
251 GNUNET_SETU_OPTION_FORCE_DELTA };
252 }
253
254 opts[n_opts].type = 0;
255 info2.oh = GNUNET_SETU_accept (request,
256 opts,
257 set_result_cb, &info2);
258 GNUNET_SETU_commit (info2.oh, info2.set);
259}
260
261
262static int
263set_insert_iterator (void *cls,
264 const struct GNUNET_HashCode *key,
265 void *value)
266{
267 struct GNUNET_SETU_Handle *set = cls;
268 struct GNUNET_SETU_Element el;
269
270 el.element_type = 0;
271 el.data = value;
272 el.size = element_size;
273 GNUNET_SETU_add_element (set, &el, NULL, NULL);
274 return GNUNET_YES;
275}
276
277
278static void
279handle_shutdown (void *cls)
280{
281 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
282 "Shutting down set profiler\n");
283 if (NULL != set_listener)
284 {
285 GNUNET_SETU_listen_cancel (set_listener);
286 set_listener = NULL;
287 }
288 if (NULL != info1.oh)
289 {
290 GNUNET_SETU_operation_cancel (info1.oh);
291 info1.oh = NULL;
292 }
293 if (NULL != info2.oh)
294 {
295 GNUNET_SETU_operation_cancel (info2.oh);
296 info2.oh = NULL;
297 }
298 if (NULL != info1.set)
299 {
300 GNUNET_SETU_destroy (info1.set);
301 info1.set = NULL;
302 }
303 if (NULL != info2.set)
304 {
305 GNUNET_SETU_destroy (info2.set);
306 info2.set = NULL;
307 }
308 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
309}
310
311
312static void
313run (void *cls,
314 const struct GNUNET_CONFIGURATION_Handle *cfg,
315 struct GNUNET_TESTING_Peer *peer)
316{
317 unsigned int i;
318 struct GNUNET_HashCode hash;
319 /* max. 2 options plus terminator */
320 struct GNUNET_SETU_Option opts[3] = { { 0 } };
321 unsigned int n_opts = 0;
322
323 config = cfg;
324
325 GNUNET_assert (element_size > 0);
326
327 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer))
328 {
329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
330 ret = 0;
331 return;
332 }
333
334 statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
335
336 GNUNET_SCHEDULER_add_shutdown (&handle_shutdown, NULL);
337
338 info1.id = "a";
339 info2.id = "b";
340
341 info1.sent = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
342 info2.sent = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
343 common_sent = GNUNET_CONTAINER_multihashmap_create (num_c + 1, GNUNET_NO);
344
345 info1.received = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
346 info2.received = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
347
348 for (i = 0; i < num_a; i++)
349 {
350 char *data = GNUNET_malloc (element_size);
351 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
352 GNUNET_CRYPTO_hash (data, element_size, &hash);
353 GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, data,
354 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
355 }
356
357 for (i = 0; i < num_b; i++)
358 {
359 char *data = GNUNET_malloc (element_size);
360 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
361 GNUNET_CRYPTO_hash (data, element_size, &hash);
362 GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, data,
363 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
364 }
365
366 for (i = 0; i < num_c; i++)
367 {
368 char *data = GNUNET_malloc (element_size);
369 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
370 GNUNET_CRYPTO_hash (data, element_size, &hash);
371 GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
372 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
373 }
374
375 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &app_id);
376
377 /* FIXME: also implement intersection etc. */
378 info1.set = GNUNET_SETU_create (config);
379 info2.set = GNUNET_SETU_create (config);
380
381 GNUNET_CONTAINER_multihashmap_iterate (info1.sent, set_insert_iterator,
382 info1.set);
383 GNUNET_CONTAINER_multihashmap_iterate (info2.sent, set_insert_iterator,
384 info2.set);
385 GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator,
386 info1.set);
387 GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator,
388 info2.set);
389
390 set_listener = GNUNET_SETU_listen (config,
391 &app_id,
392 &set_listen_cb,
393 NULL);
394
395
396 if (byzantine)
397 {
398 opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
399 GNUNET_SETU_OPTION_BYZANTINE };
400 }
401 GNUNET_assert (! (force_full && force_delta));
402 if (force_full)
403 {
404 opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
405 GNUNET_SETU_OPTION_FORCE_FULL };
406 }
407 if (force_delta)
408 {
409 opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
410 GNUNET_SETU_OPTION_FORCE_DELTA };
411 }
412
413 opts[n_opts].type = 0;
414
415 info1.oh = GNUNET_SETU_prepare (&local_peer, &app_id, NULL,
416 opts,
417 set_result_cb, &info1);
418 GNUNET_SETU_commit (info1.oh, info1.set);
419 GNUNET_SETU_destroy (info1.set);
420 info1.set = NULL;
421}
422
423
424static void
425pre_run (void *cls, char *const *args, const char *cfgfile,
426 const struct GNUNET_CONFIGURATION_Handle *cfg)
427{
428 if (0 != GNUNET_TESTING_peer_run ("set-profiler",
429 cfgfile,
430 &run, NULL))
431 ret = 2;
432}
433
434
435int
436main (int argc, char **argv)
437{
438 struct GNUNET_GETOPT_CommandLineOption options[] = {
439 GNUNET_GETOPT_option_uint ('A',
440 "num-first",
441 NULL,
442 gettext_noop ("number of values"),
443 &num_a),
444
445 GNUNET_GETOPT_option_uint ('B',
446 "num-second",
447 NULL,
448 gettext_noop ("number of values"),
449 &num_b),
450
451 GNUNET_GETOPT_option_flag ('b',
452 "byzantine",
453 gettext_noop ("use byzantine mode"),
454 &byzantine),
455
456 GNUNET_GETOPT_option_uint ('f',
457 "force-full",
458 NULL,
459 gettext_noop ("force sending full set"),
460 &force_full),
461
462 GNUNET_GETOPT_option_uint ('d',
463 "force-delta",
464 NULL,
465 gettext_noop ("number delta operation"),
466 &force_delta),
467
468 GNUNET_GETOPT_option_uint ('C',
469 "num-common",
470 NULL,
471 gettext_noop ("number of values"),
472 &num_c),
473
474 GNUNET_GETOPT_option_string ('x',
475 "operation",
476 NULL,
477 gettext_noop ("operation to execute"),
478 &op_str),
479
480 GNUNET_GETOPT_option_uint ('w',
481 "element-size",
482 NULL,
483 gettext_noop ("element size"),
484 &element_size),
485
486 GNUNET_GETOPT_option_filename ('s',
487 "statistics",
488 "FILENAME",
489 gettext_noop ("write statistics to file"),
490 &statistics_filename),
491
492 GNUNET_GETOPT_OPTION_END
493 };
494
495 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set-profiler",
496 "help",
497 options, &pre_run, NULL, GNUNET_YES);
498 return ret;
499}
diff --git a/src/setu/ibf.c b/src/setu/ibf.c
new file mode 100644
index 000000000..1532afceb
--- /dev/null
+++ b/src/setu/ibf.c
@@ -0,0 +1,409 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/ibf.c
23 * @brief implementation of the invertible bloom filter
24 * @author Florian Dold
25 */
26
27#include "ibf.h"
28
29/**
30 * Compute the key's hash from the key.
31 * Redefine to use a different hash function.
32 */
33#define IBF_KEY_HASH_VAL(k) (GNUNET_CRYPTO_crc32_n (&(k), sizeof(struct \
34 IBF_KeyHash)))
35
36/**
37 * Create a key from a hashcode.
38 *
39 * @param hash the hashcode
40 * @return a key
41 */
42struct IBF_Key
43ibf_key_from_hashcode (const struct GNUNET_HashCode *hash)
44{
45 return *(struct IBF_Key *) hash;
46}
47
48
49/**
50 * Create a hashcode from a key, by replicating the key
51 * until the hascode is filled
52 *
53 * @param key the key
54 * @param dst hashcode to store the result in
55 */
56void
57ibf_hashcode_from_key (struct IBF_Key key,
58 struct GNUNET_HashCode *dst)
59{
60 struct IBF_Key *p;
61 unsigned int i;
62 const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode)
63 / sizeof(struct IBF_Key);
64
65 p = (struct IBF_Key *) dst;
66 for (i = 0; i < keys_per_hashcode; i++)
67 *p++ = key;
68}
69
70
71/**
72 * Create an invertible bloom filter.
73 *
74 * @param size number of IBF buckets
75 * @param hash_num number of buckets one element is hashed in
76 * @return the newly created invertible bloom filter, NULL on error
77 */
78struct InvertibleBloomFilter *
79ibf_create (uint32_t size, uint8_t hash_num)
80{
81 struct InvertibleBloomFilter *ibf;
82
83 GNUNET_assert (0 != size);
84
85 ibf = GNUNET_new (struct InvertibleBloomFilter);
86 ibf->count = GNUNET_malloc_large (size * sizeof(uint8_t));
87 if (NULL == ibf->count)
88 {
89 GNUNET_free (ibf);
90 return NULL;
91 }
92 ibf->key_sum = GNUNET_malloc_large (size * sizeof(struct IBF_Key));
93 if (NULL == ibf->key_sum)
94 {
95 GNUNET_free (ibf->count);
96 GNUNET_free (ibf);
97 return NULL;
98 }
99 ibf->key_hash_sum = GNUNET_malloc_large (size * sizeof(struct IBF_KeyHash));
100 if (NULL == ibf->key_hash_sum)
101 {
102 GNUNET_free (ibf->key_sum);
103 GNUNET_free (ibf->count);
104 GNUNET_free (ibf);
105 return NULL;
106 }
107 ibf->size = size;
108 ibf->hash_num = hash_num;
109
110 return ibf;
111}
112
113
114/**
115 * Store unique bucket indices for the specified key in dst.
116 */
117static void
118ibf_get_indices (const struct InvertibleBloomFilter *ibf,
119 struct IBF_Key key,
120 int *dst)
121{
122 uint32_t filled;
123 uint32_t i;
124 uint32_t bucket;
125
126 bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key);
127 for (i = 0, filled = 0; filled < ibf->hash_num; i++)
128 {
129 unsigned int j;
130 uint64_t x;
131 for (j = 0; j < filled; j++)
132 if (dst[j] == bucket)
133 goto try_next;
134 dst[filled++] = bucket % ibf->size;
135try_next:;
136 x = ((uint64_t) bucket << 32) | i;
137 bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x);
138 }
139}
140
141
142static void
143ibf_insert_into (struct InvertibleBloomFilter *ibf,
144 struct IBF_Key key,
145 const int *buckets, int side)
146{
147 int i;
148
149 for (i = 0; i < ibf->hash_num; i++)
150 {
151 const int bucket = buckets[i];
152 ibf->count[bucket].count_val += side;
153 ibf->key_sum[bucket].key_val ^= key.key_val;
154 ibf->key_hash_sum[bucket].key_hash_val
155 ^= IBF_KEY_HASH_VAL (key);
156 }
157}
158
159
160/**
161 * Insert a key into an IBF.
162 *
163 * @param ibf the IBF
164 * @param key the element's hash code
165 */
166void
167ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
168{
169 int buckets[ibf->hash_num];
170
171 GNUNET_assert (ibf->hash_num <= ibf->size);
172 ibf_get_indices (ibf, key, buckets);
173 ibf_insert_into (ibf, key, buckets, 1);
174}
175
176
177/**
178 * Remove a key from an IBF.
179 *
180 * @param ibf the IBF
181 * @param key the element's hash code
182 */
183void
184ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
185{
186 int buckets[ibf->hash_num];
187
188 GNUNET_assert (ibf->hash_num <= ibf->size);
189 ibf_get_indices (ibf, key, buckets);
190 ibf_insert_into (ibf, key, buckets, -1);
191}
192
193
194/**
195 * Test is the IBF is empty, i.e. all counts, keys and key hashes are zero.
196 */
197static int
198ibf_is_empty (struct InvertibleBloomFilter *ibf)
199{
200 int i;
201
202 for (i = 0; i < ibf->size; i++)
203 {
204 if (0 != ibf->count[i].count_val)
205 return GNUNET_NO;
206 if (0 != ibf->key_hash_sum[i].key_hash_val)
207 return GNUNET_NO;
208 if (0 != ibf->key_sum[i].key_val)
209 return GNUNET_NO;
210 }
211 return GNUNET_YES;
212}
213
214
215/**
216 * Decode and remove an element from the IBF, if possible.
217 *
218 * @param ibf the invertible bloom filter to decode
219 * @param ret_side sign of the cell's count where the decoded element came from.
220 * A negative sign indicates that the element was recovered
221 * resides in an IBF that was previously subtracted from.
222 * @param ret_id receives the hash code of the decoded element, if successful
223 * @return GNUNET_YES if decoding an element was successful,
224 * GNUNET_NO if the IBF is empty,
225 * GNUNET_SYSERR if the decoding has failed
226 */
227int
228ibf_decode (struct InvertibleBloomFilter *ibf,
229 int *ret_side, struct IBF_Key *ret_id)
230{
231 struct IBF_KeyHash hash;
232 int i;
233 int buckets[ibf->hash_num];
234
235 GNUNET_assert (NULL != ibf);
236
237 for (i = 0; i < ibf->size; i++)
238 {
239 int j;
240 int hit;
241
242 /* we can only decode from pure buckets */
243 if ((1 != ibf->count[i].count_val) && (-1 != ibf->count[i].count_val))
244 continue;
245
246 hash.key_hash_val = IBF_KEY_HASH_VAL (ibf->key_sum[i]);
247
248 /* test if the hash matches the key */
249 if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val)
250 continue;
251
252 /* test if key in bucket hits its own location,
253 * if not, the key hash was subject to collision */
254 hit = GNUNET_NO;
255 ibf_get_indices (ibf, ibf->key_sum[i], buckets);
256 for (j = 0; j < ibf->hash_num; j++)
257 if (buckets[j] == i)
258 hit = GNUNET_YES;
259
260 if (GNUNET_NO == hit)
261 continue;
262
263 if (NULL != ret_side)
264 *ret_side = ibf->count[i].count_val;
265 if (NULL != ret_id)
266 *ret_id = ibf->key_sum[i];
267
268 /* insert on the opposite side, effectively removing the element */
269 ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val);
270
271 return GNUNET_YES;
272 }
273
274 if (GNUNET_YES == ibf_is_empty (ibf))
275 return GNUNET_NO;
276 return GNUNET_SYSERR;
277}
278
279
280/**
281 * Write buckets from an ibf to a buffer.
282 * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.
283 *
284 * @param ibf the ibf to write
285 * @param start with which bucket to start
286 * @param count how many buckets to write
287 * @param buf buffer to write the data to
288 */
289void
290ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start,
291 uint32_t count, void *buf)
292{
293 struct IBF_Key *key_dst;
294 struct IBF_KeyHash *key_hash_dst;
295 struct IBF_Count *count_dst;
296
297 GNUNET_assert (start + count <= ibf->size);
298
299 /* copy keys */
300 key_dst = (struct IBF_Key *) buf;
301 GNUNET_memcpy (key_dst, ibf->key_sum + start, count * sizeof *key_dst);
302 key_dst += count;
303 /* copy key hashes */
304 key_hash_dst = (struct IBF_KeyHash *) key_dst;
305 GNUNET_memcpy (key_hash_dst, ibf->key_hash_sum + start, count
306 * sizeof *key_hash_dst);
307 key_hash_dst += count;
308 /* copy counts */
309 count_dst = (struct IBF_Count *) key_hash_dst;
310 GNUNET_memcpy (count_dst, ibf->count + start, count * sizeof *count_dst);
311}
312
313
314/**
315 * Read buckets from a buffer into an ibf.
316 *
317 * @param buf pointer to the buffer to read from
318 * @param start which bucket to start at
319 * @param count how many buckets to read
320 * @param ibf the ibf to read from
321 */
322void
323ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct
324 InvertibleBloomFilter *ibf)
325{
326 struct IBF_Key *key_src;
327 struct IBF_KeyHash *key_hash_src;
328 struct IBF_Count *count_src;
329
330 GNUNET_assert (count > 0);
331 GNUNET_assert (start + count <= ibf->size);
332
333 /* copy keys */
334 key_src = (struct IBF_Key *) buf;
335 GNUNET_memcpy (ibf->key_sum + start, key_src, count * sizeof *key_src);
336 key_src += count;
337 /* copy key hashes */
338 key_hash_src = (struct IBF_KeyHash *) key_src;
339 GNUNET_memcpy (ibf->key_hash_sum + start, key_hash_src, count
340 * sizeof *key_hash_src);
341 key_hash_src += count;
342 /* copy counts */
343 count_src = (struct IBF_Count *) key_hash_src;
344 GNUNET_memcpy (ibf->count + start, count_src, count * sizeof *count_src);
345}
346
347
348/**
349 * Subtract ibf2 from ibf1, storing the result in ibf1.
350 * The two IBF's must have the same parameters size and hash_num.
351 *
352 * @param ibf1 IBF that is subtracted from
353 * @param ibf2 IBF that will be subtracted from ibf1
354 */
355void
356ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct
357 InvertibleBloomFilter *ibf2)
358{
359 int i;
360
361 GNUNET_assert (ibf1->size == ibf2->size);
362 GNUNET_assert (ibf1->hash_num == ibf2->hash_num);
363
364 for (i = 0; i < ibf1->size; i++)
365 {
366 ibf1->count[i].count_val -= ibf2->count[i].count_val;
367 ibf1->key_hash_sum[i].key_hash_val ^= ibf2->key_hash_sum[i].key_hash_val;
368 ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val;
369 }
370}
371
372
373/**
374 * Create a copy of an IBF, the copy has to be destroyed properly.
375 *
376 * @param ibf the IBF to copy
377 */
378struct InvertibleBloomFilter *
379ibf_dup (const struct InvertibleBloomFilter *ibf)
380{
381 struct InvertibleBloomFilter *copy;
382
383 copy = GNUNET_malloc (sizeof *copy);
384 copy->hash_num = ibf->hash_num;
385 copy->size = ibf->size;
386 copy->key_hash_sum = GNUNET_memdup (ibf->key_hash_sum, ibf->size
387 * sizeof(struct IBF_KeyHash));
388 copy->key_sum = GNUNET_memdup (ibf->key_sum, ibf->size * sizeof(struct
389 IBF_Key));
390 copy->count = GNUNET_memdup (ibf->count, ibf->size * sizeof(struct
391 IBF_Count));
392 return copy;
393}
394
395
396/**
397 * Destroy all resources associated with the invertible bloom filter.
398 * No more ibf_*-functions may be called on ibf after calling destroy.
399 *
400 * @param ibf the intertible bloom filter to destroy
401 */
402void
403ibf_destroy (struct InvertibleBloomFilter *ibf)
404{
405 GNUNET_free (ibf->key_sum);
406 GNUNET_free (ibf->key_hash_sum);
407 GNUNET_free (ibf->count);
408 GNUNET_free (ibf);
409}
diff --git a/src/setu/ibf.h b/src/setu/ibf.h
new file mode 100644
index 000000000..7c2ab33b1
--- /dev/null
+++ b/src/setu/ibf.h
@@ -0,0 +1,255 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/ibf.h
23 * @brief invertible bloom filter
24 * @author Florian Dold
25 */
26
27#ifndef GNUNET_CONSENSUS_IBF_H
28#define GNUNET_CONSENSUS_IBF_H
29
30#include "platform.h"
31#include "gnunet_util_lib.h"
32
33#ifdef __cplusplus
34extern "C"
35{
36#if 0 /* keep Emacsens' auto-indent happy */
37}
38#endif
39#endif
40
41
42/**
43 * Keys that can be inserted into and removed from an IBF.
44 */
45struct IBF_Key
46{
47 uint64_t key_val;
48};
49
50
51/**
52 * Hash of an IBF key.
53 */
54struct IBF_KeyHash
55{
56 uint32_t key_hash_val;
57};
58
59
60/**
61 * Type of the count field of IBF buckets.
62 */
63struct IBF_Count
64{
65 int8_t count_val;
66};
67
68
69/**
70 * Size of one ibf bucket in bytes
71 */
72#define IBF_BUCKET_SIZE (sizeof(struct IBF_Count) + sizeof(struct IBF_Key) \
73 + sizeof(struct IBF_KeyHash))
74
75
76/**
77 * Invertible bloom filter (IBF).
78 *
79 * An IBF is a counting bloom filter that has the ability to restore
80 * the hashes of its stored elements with high probability.
81 */
82struct InvertibleBloomFilter
83{
84 /**
85 * How many cells does this IBF have?
86 */
87 uint32_t size;
88
89 /**
90 * In how many cells do we hash one element?
91 * Usually 4 or 3.
92 */
93 uint8_t hash_num;
94
95 /**
96 * Xor sums of the elements' keys, used to identify the elements.
97 * Array of 'size' elements.
98 */
99 struct IBF_Key *key_sum;
100
101 /**
102 * Xor sums of the hashes of the keys of inserted elements.
103 * Array of 'size' elements.
104 */
105 struct IBF_KeyHash *key_hash_sum;
106
107 /**
108 * How many times has a bucket been hit?
109 * Can be negative, as a result of IBF subtraction.
110 * Array of 'size' elements.
111 */
112 struct IBF_Count *count;
113};
114
115
116/**
117 * Write buckets from an ibf to a buffer.
118 * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.
119 *
120 * @param ibf the ibf to write
121 * @param start with which bucket to start
122 * @param count how many buckets to write
123 * @param buf buffer to write the data to
124 */
125void
126ibf_write_slice (const struct InvertibleBloomFilter *ibf,
127 uint32_t start,
128 uint32_t count,
129 void *buf);
130
131
132/**
133 * Read buckets from a buffer into an ibf.
134 *
135 * @param buf pointer to the buffer to read from
136 * @param start which bucket to start at
137 * @param count how many buckets to read
138 * @param ibf the ibf to write to
139 */
140void
141ibf_read_slice (const void *buf,
142 uint32_t start,
143 uint32_t count,
144 struct InvertibleBloomFilter *ibf);
145
146
147/**
148 * Create a key from a hashcode.
149 *
150 * @param hash the hashcode
151 * @return a key
152 */
153struct IBF_Key
154ibf_key_from_hashcode (const struct GNUNET_HashCode *hash);
155
156
157/**
158 * Create a hashcode from a key, by replicating the key
159 * until the hascode is filled
160 *
161 * @param key the key
162 * @param dst hashcode to store the result in
163 */
164void
165ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst);
166
167
168/**
169 * Create an invertible bloom filter.
170 *
171 * @param size number of IBF buckets
172 * @param hash_num number of buckets one element is hashed in, usually 3 or 4
173 * @return the newly created invertible bloom filter, NULL on error
174 */
175struct InvertibleBloomFilter *
176ibf_create (uint32_t size, uint8_t hash_num);
177
178
179/**
180 * Insert a key into an IBF.
181 *
182 * @param ibf the IBF
183 * @param key the element's hash code
184 */
185void
186ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key);
187
188
189/**
190 * Remove a key from an IBF.
191 *
192 * @param ibf the IBF
193 * @param key the element's hash code
194 */
195void
196ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key);
197
198
199/**
200 * Subtract ibf2 from ibf1, storing the result in ibf1.
201 * The two IBF's must have the same parameters size and hash_num.
202 *
203 * @param ibf1 IBF that is subtracted from
204 * @param ibf2 IBF that will be subtracted from ibf1
205 */
206void
207ibf_subtract (struct InvertibleBloomFilter *ibf1,
208 const struct InvertibleBloomFilter *ibf2);
209
210
211/**
212 * Decode and remove an element from the IBF, if possible.
213 *
214 * @param ibf the invertible bloom filter to decode
215 * @param ret_side sign of the cell's count where the decoded element came from.
216 * A negative sign indicates that the element was recovered
217 * resides in an IBF that was previously subtracted from.
218 * @param ret_id receives the hash code of the decoded element, if successful
219 * @return #GNUNET_YES if decoding an element was successful,
220 * #GNUNET_NO if the IBF is empty,
221 * #GNUNET_SYSERR if the decoding has failed
222 */
223int
224ibf_decode (struct InvertibleBloomFilter *ibf,
225 int *ret_side,
226 struct IBF_Key *ret_id);
227
228
229/**
230 * Create a copy of an IBF, the copy has to be destroyed properly.
231 *
232 * @param ibf the IBF to copy
233 */
234struct InvertibleBloomFilter *
235ibf_dup (const struct InvertibleBloomFilter *ibf);
236
237
238/**
239 * Destroy all resources associated with the invertible bloom filter.
240 * No more ibf_*-functions may be called on ibf after calling destroy.
241 *
242 * @param ibf the intertible bloom filter to destroy
243 */
244void
245ibf_destroy (struct InvertibleBloomFilter *ibf);
246
247
248#if 0 /* keep Emacsens' auto-indent happy */
249{
250#endif
251#ifdef __cplusplus
252}
253#endif
254
255#endif
diff --git a/src/setu/ibf_sim.c b/src/setu/ibf_sim.c
new file mode 100644
index 000000000..6415d00e1
--- /dev/null
+++ b/src/setu/ibf_sim.c
@@ -0,0 +1,142 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/ibf_sim.c
23 * @brief implementation of simulation for invertible bloom filter
24 * @author Florian Dold
25 *
26 * This code was used for some internal experiments, it is not
27 * build or shipped as part of the GNUnet system.
28 */
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32
33#define MAX_IBF_DECODE 16
34
35/* report average over how many rounds? */
36#define ROUNDS 100000
37
38/* enable one of the three below */
39// simple fix
40#define FIX1 0
41// possibly slightly better fix for large IBF_DECODE values
42#define FIX2 1
43
44// SIGCOMM algorithm
45#define STRATA 0
46
47// print each value?
48#define VERBOSE 0
49// avoid assembly? (ASM is about 50% faster)
50#define SLOW 0
51
52int
53main (int argc, char **argv)
54{
55 unsigned int round;
56 unsigned int buckets[31]; // max is 2^31 as 'random' returns only between 0 and 2^31
57 unsigned int i;
58 int j;
59 unsigned int r;
60 unsigned int ret;
61 unsigned long long total;
62 unsigned int want;
63 double predict;
64
65 srandom (time (NULL));
66 total = 0;
67 want = atoi (argv[1]);
68 for (round = 0; round < ROUNDS; round++)
69 {
70 memset (buckets, 0, sizeof(buckets));
71 for (i = 0; i < want; i++)
72 {
73 /* FIXME: might want to use 'better' PRNG to avoid
74 PRNG-induced biases */
75 r = random ();
76 if (0 == r)
77 continue;
78#if SLOW
79 for (j = 0; (j < 31) && (0 == (r & (1 << j))); j++)
80 ;
81#else
82 /* use assembly / gcc */
83 j = __builtin_ffs (r) - 1;
84#endif
85 buckets[j]++;
86 }
87 ret = 0;
88 predict = 0.0;
89 for (j = 31; j >= 0; j--)
90 {
91#if FIX1
92 /* improved algorithm, for 1000 elements with IBF-DECODE 8, I
93 get 990/1000 elements on average over 1 million runs; key
94 idea being to stop short of the 'last' possible IBF as
95 otherwise a "lowball" per-chance would unduely influence the
96 result */if ((j > 0) &&
97 (buckets[j - 1] > MAX_IBF_DECODE))
98 {
99 ret *= (1 << (j + 1));
100 break;
101 }
102#endif
103#if FIX2
104 /* another improvement: don't just always cut off the last one,
105 but rather try to predict based on all previous values where
106 that "last" one is; additional prediction can only really
107 work if MAX_IBF_DECODE is sufficiently high */
108 if ((j > 0) &&
109 ((buckets[j - 1] > MAX_IBF_DECODE) ||
110 (predict > MAX_IBF_DECODE)))
111 {
112 ret *= (1 << (j + 1));
113 break;
114 }
115#endif
116#if STRATA
117 /* original algorithm, for 1000 elements with IBF-DECODE 8,
118 I get 920/1000 elements on average over 1 million runs */
119 if (buckets[j] > MAX_IBF_DECODE)
120 {
121 ret *= (1 << (j + 1));
122 break;
123 }
124#endif
125 ret += buckets[j];
126 predict = (buckets[j] + 2.0 * predict) / 2.0;
127 }
128#if VERBOSE
129 fprintf (stderr, "%u ", ret);
130#endif
131 total += ret;
132 }
133 fprintf (stderr, "\n");
134 fprintf (stdout, "average %llu\n", total / ROUNDS);
135 return 0;
136}
137
138
139/* TODO: should calculate stddev of the results to also be able to
140 say something about the stability of the results, outside of
141 large-scale averages -- gaining 8% precision at the expense of
142 50% additional variance might not be worth it... */
diff --git a/src/setu/plugin_block_setu_test.c b/src/setu/plugin_block_setu_test.c
new file mode 100644
index 000000000..fd0c8a680
--- /dev/null
+++ b/src/setu/plugin_block_setu_test.c
@@ -0,0 +1,123 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file setu/plugin_block_setu_test.c
23 * @brief set test block, recognizes elements with non-zero first byte as invalid
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_block_plugin.h"
29#include "gnunet_block_group_lib.h"
30
31
32/**
33 * Function called to validate a reply or a request. For
34 * request evaluation, simply pass "NULL" for the reply_block.
35 *
36 * @param cls closure
37 * @param ctx block context
38 * @param type block type
39 * @param group block group to use
40 * @param eo control flags
41 * @param query original query (hash)
42 * @param xquery extrended query data (can be NULL, depending on type)
43 * @param xquery_size number of bytes in xquery
44 * @param reply_block response to validate
45 * @param reply_block_size number of bytes in reply block
46 * @return characterization of result
47 */
48static enum GNUNET_BLOCK_EvaluationResult
49block_plugin_setu_test_evaluate (void *cls,
50 struct GNUNET_BLOCK_Context *ctx,
51 enum GNUNET_BLOCK_Type type,
52 struct GNUNET_BLOCK_Group *group,
53 enum GNUNET_BLOCK_EvaluationOptions eo,
54 const struct GNUNET_HashCode *query,
55 const void *xquery,
56 size_t xquery_size,
57 const void *reply_block,
58 size_t reply_block_size)
59{
60 if ((NULL == reply_block) ||
61 (reply_block_size == 0) ||
62 (0 != ((char *) reply_block)[0]))
63 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
64 return GNUNET_BLOCK_EVALUATION_OK_MORE;
65}
66
67
68/**
69 * Function called to obtain the key for a block.
70 *
71 * @param cls closure
72 * @param type block type
73 * @param block block to get the key for
74 * @param block_size number of bytes in block
75 * @param key set to the key (query) for the given block
76 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
77 * (or if extracting a key from a block of this type does not work)
78 */
79static int
80block_plugin_setu_test_get_key (void *cls,
81 enum GNUNET_BLOCK_Type type,
82 const void *block,
83 size_t block_size,
84 struct GNUNET_HashCode *key)
85{
86 return GNUNET_SYSERR;
87}
88
89
90/**
91 * Entry point for the plugin.
92 */
93void *
94libgnunet_plugin_block_setu_test_init (void *cls)
95{
96 static enum GNUNET_BLOCK_Type types[] = {
97 GNUNET_BLOCK_TYPE_SETU_TEST,
98 GNUNET_BLOCK_TYPE_ANY /* end of list */
99 };
100 struct GNUNET_BLOCK_PluginFunctions *api;
101
102 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
103 api->evaluate = &block_plugin_setu_test_evaluate;
104 api->get_key = &block_plugin_setu_test_get_key;
105 api->types = types;
106 return api;
107}
108
109
110/**
111 * Exit point from the plugin.
112 */
113void *
114libgnunet_plugin_block_setu_test_done (void *cls)
115{
116 struct GNUNET_BLOCK_PluginFunctions *api = cls;
117
118 GNUNET_free (api);
119 return NULL;
120}
121
122
123/* end of plugin_block_setu_test.c */
diff --git a/src/setu/setu.conf.in b/src/setu/setu.conf.in
new file mode 100644
index 000000000..6c48f6156
--- /dev/null
+++ b/src/setu/setu.conf.in
@@ -0,0 +1,12 @@
1[setu]
2START_ON_DEMAND = @START_ON_DEMAND@
3@UNIXONLY@PORT = 2106
4HOSTNAME = localhost
5BINARY = gnunet-service-setu
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-setu.sock
9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES
11
12#PREFIX = valgrind
diff --git a/src/setu/setu.h b/src/setu/setu.h
new file mode 100644
index 000000000..e9a0def95
--- /dev/null
+++ b/src/setu/setu.h
@@ -0,0 +1,315 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2014, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file set/set.h
22 * @brief messages used for the set union api
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#ifndef SET_H
27#define SET_H
28
29#include "platform.h"
30#include "gnunet_common.h"
31#include "gnunet_set_service.h"
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35/**
36 * Message sent by the client to the service to ask starting
37 * a new set to perform operations with. Includes the desired
38 * set operation type.
39 */
40struct GNUNET_SETU_CreateMessage
41{
42 /**
43 * Type: #GNUNET_MESSAGE_TYPE_SETU_CREATE
44 */
45 struct GNUNET_MessageHeader header;
46
47};
48
49
50/**
51 * Message sent by the client to the service to start listening for
52 * incoming requests to perform a certain type of set operation for a
53 * certain type of application.
54 */
55struct GNUNET_SETU_ListenMessage
56{
57 /**
58 * Type: #GNUNET_MESSAGE_TYPE_SETU_LISTEN
59 */
60 struct GNUNET_MessageHeader header;
61
62 /**
63 * Always zero.
64 */
65 uint32_t reserved GNUNET_PACKED;
66
67 /**
68 * application id
69 */
70 struct GNUNET_HashCode app_id;
71};
72
73
74/**
75 * Message sent by a listening client to the service to accept
76 * performing the operation with the other peer.
77 */
78struct GNUNET_SETU_AcceptMessage
79{
80 /**
81 * Type: #GNUNET_MESSAGE_TYPE_SETU_ACCEPT
82 */
83 struct GNUNET_MessageHeader header;
84
85 /**
86 * ID of the incoming request we want to accept.
87 */
88 uint32_t accept_reject_id GNUNET_PACKED;
89
90 /**
91 * Request ID to identify responses.
92 */
93 uint32_t request_id GNUNET_PACKED;
94
95 /**
96 * Always use delta operation instead of sending full sets,
97 * even it it's less efficient.
98 */
99 uint8_t force_delta;
100
101 /**
102 * Always send full sets, even if delta operations would
103 * be more efficient.
104 */
105 uint8_t force_full;
106
107 /**
108 * #GNUNET_YES to fail operations where Byzantine faults
109 * are suspected
110 */
111 uint8_t byzantine;
112
113 /**
114 * #GNUNET_YES to also send back set elements we are sending to
115 * the remote peer.
116 */
117 uint8_t symmetric;
118
119 /**
120 * Lower bound for the set size, used only when
121 * byzantine mode is enabled.
122 */
123 uint32_t byzantine_lower_bound;
124};
125
126
127/**
128 * Message sent by a listening client to the service to reject
129 * performing the operation with the other peer.
130 */
131struct GNUNET_SETU_RejectMessage
132{
133 /**
134 * Type: #GNUNET_MESSAGE_TYPE_SETU_REJECT
135 */
136 struct GNUNET_MessageHeader header;
137
138 /**
139 * ID of the incoming request we want to reject.
140 */
141 uint32_t accept_reject_id GNUNET_PACKED;
142};
143
144
145/**
146 * A request for an operation with another client.
147 */
148struct GNUNET_SETU_RequestMessage
149{
150 /**
151 * Type: #GNUNET_MESSAGE_TYPE_SETU_REQUEST.
152 */
153 struct GNUNET_MessageHeader header;
154
155 /**
156 * ID of the to identify the request when accepting or
157 * rejecting it.
158 */
159 uint32_t accept_id GNUNET_PACKED;
160
161 /**
162 * Identity of the requesting peer.
163 */
164 struct GNUNET_PeerIdentity peer_id;
165
166 /* rest: context message, that is, application-specific
167 message to convince listener to pick up */
168};
169
170
171/**
172 * Message sent by client to service to initiate a set operation as a
173 * client (not as listener). A set (which determines the operation
174 * type) must already exist in association with this client.
175 */
176struct GNUNET_SETU_EvaluateMessage
177{
178 /**
179 * Type: #GNUNET_MESSAGE_TYPE_SETU_EVALUATE
180 */
181 struct GNUNET_MessageHeader header;
182
183 /**
184 * Id of our set to evaluate, chosen implicitly by the client when it
185 * calls #GNUNET_SETU_commit().
186 */
187 uint32_t request_id GNUNET_PACKED;
188
189 /**
190 * Peer to evaluate the operation with
191 */
192 struct GNUNET_PeerIdentity target_peer;
193
194 /**
195 * Application id
196 */
197 struct GNUNET_HashCode app_id;
198
199 /**
200 * Always use delta operation instead of sending full sets,
201 * even it it's less efficient.
202 */
203 uint8_t force_delta;
204
205 /**
206 * Always send full sets, even if delta operations would
207 * be more efficient.
208 */
209 uint8_t force_full;
210
211 /**
212 * #GNUNET_YES to fail operations where Byzantine faults
213 * are suspected
214 */
215 uint8_t byzantine;
216
217 /**
218 * Also return set elements we are sending to the remote peer.
219 */
220 uint8_t symmetric;
221
222 /**
223 * Lower bound for the set size, used only when
224 * byzantine mode is enabled.
225 */
226 uint32_t byzantine_lower_bound;
227
228 /* rest: context message, that is, application-specific
229 message to convince listener to pick up */
230};
231
232
233/**
234 * Message sent by the service to the client to indicate an
235 * element that is removed (set intersection) or added
236 * (set union) or part of the final result, depending on
237 * options specified for the operation.
238 */
239struct GNUNET_SETU_ResultMessage
240{
241 /**
242 * Type: #GNUNET_MESSAGE_TYPE_SETU_RESULT
243 */
244 struct GNUNET_MessageHeader header;
245
246 /**
247 * Current set size.
248 */
249 uint64_t current_size;
250
251 /**
252 * id the result belongs to
253 */
254 uint32_t request_id GNUNET_PACKED;
255
256 /**
257 * Was the evaluation successful? Contains
258 * an `enum GNUNET_SETU_Status` in NBO.
259 */
260 uint16_t result_status GNUNET_PACKED;
261
262 /**
263 * Type of the element attachted to the message, if any.
264 */
265 uint16_t element_type GNUNET_PACKED;
266
267 /* rest: the actual element */
268};
269
270
271/**
272 * Message sent by client to the service to add
273 * an element to the set.
274 */
275struct GNUNET_SETU_ElementMessage
276{
277 /**
278 * Type: #GNUNET_MESSAGE_TYPE_SETU_ADD
279 */
280 struct GNUNET_MessageHeader header;
281
282 /**
283 * Type of the element to add or remove.
284 */
285 uint16_t element_type GNUNET_PACKED;
286
287 /**
288 * For alignment, always zero.
289 */
290 uint16_t reserved GNUNET_PACKED;
291
292 /* rest: the actual element */
293};
294
295
296/**
297 * Sent to the service by the client in order to cancel a set operation.
298 */
299struct GNUNET_SETU_CancelMessage
300{
301 /**
302 * Type: #GNUNET_MESSAGE_TYPE_SETU_CANCEL
303 */
304 struct GNUNET_MessageHeader header;
305
306 /**
307 * ID of the request we want to cancel.
308 */
309 uint32_t request_id GNUNET_PACKED;
310};
311
312
313GNUNET_NETWORK_STRUCT_END
314
315#endif
diff --git a/src/setu/setu_api.c b/src/setu/setu_api.c
new file mode 100644
index 000000000..dd3a4a769
--- /dev/null
+++ b/src/setu/setu_api.c
@@ -0,0 +1,897 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2016, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file set/setu_api.c
22 * @brief api for the set union service
23 * @author Florian Dold
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_protocols.h"
29#include "gnunet_setu_service.h"
30#include "setu.h"
31
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "set-api", __VA_ARGS__)
34
35/**
36 * Opaque handle to a set.
37 */
38struct GNUNET_SETU_Handle
39{
40 /**
41 * Message queue for @e client.
42 */
43 struct GNUNET_MQ_Handle *mq;
44
45 /**
46 * Linked list of operations on the set.
47 */
48 struct GNUNET_SETU_OperationHandle *ops_head;
49
50 /**
51 * Linked list of operations on the set.
52 */
53 struct GNUNET_SETU_OperationHandle *ops_tail;
54
55 /**
56 * Should the set be destroyed once all operations are gone?
57 * #GNUNET_SYSERR if #GNUNET_SETU_destroy() must raise this flag,
58 * #GNUNET_YES if #GNUNET_SETU_destroy() did raise this flag.
59 */
60 int destroy_requested;
61
62 /**
63 * Has the set become invalid (e.g. service died)?
64 */
65 int invalid;
66
67};
68
69
70/**
71 * Handle for a set operation request from another peer.
72 */
73struct GNUNET_SETU_Request
74{
75 /**
76 * Id of the request, used to identify the request when
77 * accepting/rejecting it.
78 */
79 uint32_t accept_id;
80
81 /**
82 * Has the request been accepted already?
83 * #GNUNET_YES/#GNUNET_NO
84 */
85 int accepted;
86};
87
88
89/**
90 * Handle to an operation. Only known to the service after committing
91 * the handle with a set.
92 */
93struct GNUNET_SETU_OperationHandle
94{
95 /**
96 * Function to be called when we have a result,
97 * or an error.
98 */
99 GNUNET_SETU_ResultIterator result_cb;
100
101 /**
102 * Closure for @e result_cb.
103 */
104 void *result_cls;
105
106 /**
107 * Local set used for the operation,
108 * NULL if no set has been provided by conclude yet.
109 */
110 struct GNUNET_SETU_Handle *set;
111
112 /**
113 * Message sent to the server on calling conclude,
114 * NULL if conclude has been called.
115 */
116 struct GNUNET_MQ_Envelope *conclude_mqm;
117
118 /**
119 * Address of the request if in the conclude message,
120 * used to patch the request id into the message when the set is known.
121 */
122 uint32_t *request_id_addr;
123
124 /**
125 * Handles are kept in a linked list.
126 */
127 struct GNUNET_SETU_OperationHandle *prev;
128
129 /**
130 * Handles are kept in a linked list.
131 */
132 struct GNUNET_SETU_OperationHandle *next;
133
134 /**
135 * Request ID to identify the operation within the set.
136 */
137 uint32_t request_id;
138};
139
140
141/**
142 * Opaque handle to a listen operation.
143 */
144struct GNUNET_SETU_ListenHandle
145{
146 /**
147 * Message queue for the client.
148 */
149 struct GNUNET_MQ_Handle*mq;
150
151 /**
152 * Configuration handle for the listener, stored
153 * here to be able to reconnect transparently on
154 * connection failure.
155 */
156 const struct GNUNET_CONFIGURATION_Handle *cfg;
157
158 /**
159 * Function to call on a new incoming request,
160 * or on error.
161 */
162 GNUNET_SETU_ListenCallback listen_cb;
163
164 /**
165 * Closure for @e listen_cb.
166 */
167 void *listen_cls;
168
169 /**
170 * Application ID we listen for.
171 */
172 struct GNUNET_HashCode app_id;
173
174 /**
175 * Time to wait until we try to reconnect on failure.
176 */
177 struct GNUNET_TIME_Relative reconnect_backoff;
178
179 /**
180 * Task for reconnecting when the listener fails.
181 */
182 struct GNUNET_SCHEDULER_Task *reconnect_task;
183
184};
185
186
187/**
188 * Check that the given @a msg is well-formed.
189 *
190 * @param cls closure
191 * @param msg message to check
192 * @return #GNUNET_OK if message is well-formed
193 */
194static int
195check_result (void *cls,
196 const struct GNUNET_SETU_ResultMessage *msg)
197{
198 /* minimum size was already checked, everything else is OK! */
199 return GNUNET_OK;
200}
201
202
203/**
204 * Handle result message for a set operation.
205 *
206 * @param cls the set
207 * @param mh the message
208 */
209static void
210handle_result (void *cls,
211 const struct GNUNET_SETU_ResultMessage *msg)
212{
213 struct GNUNET_SETU_Handle *set = cls;
214 struct GNUNET_SETU_OperationHandle *oh;
215 struct GNUNET_SETU_Element e;
216 enum GNUNET_SETU_Status result_status;
217 int destroy_set;
218
219 GNUNET_assert (NULL != set->mq);
220 result_status = (enum GNUNET_SETU_Status) ntohs (msg->result_status);
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "Got result message with status %d\n",
223 result_status);
224 oh = GNUNET_MQ_assoc_get (set->mq,
225 ntohl (msg->request_id));
226 if (NULL == oh)
227 {
228 /* 'oh' can be NULL if we canceled the operation, but the service
229 did not get the cancel message yet. */
230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231 "Ignoring result from canceled operation\n");
232 return;
233 }
234
235 switch (result_status)
236 {
237 case GNUNET_SETU_STATUS_ADD_LOCAL:
238 case GNUNET_SETU_STATUS_ADD_REMOTE:
239 e.data = &msg[1];
240 e.size = ntohs (msg->header.size)
241 - sizeof(struct GNUNET_SETU_ResultMessage);
242 e.element_type = ntohs (msg->element_type);
243 if (NULL != oh->result_cb)
244 oh->result_cb (oh->result_cls,
245 &e,
246 GNUNET_ntohll (msg->current_size),
247 result_status);
248 return;
249 case GNUNET_SETU_STATUS_FAILURE:
250 case GNUNET_SETU_STATUS_DONE:
251 LOG (GNUNET_ERROR_TYPE_DEBUG,
252 "Treating result as final status\n");
253 GNUNET_MQ_assoc_remove (set->mq,
254 ntohl (msg->request_id));
255 GNUNET_CONTAINER_DLL_remove (set->ops_head,
256 set->ops_tail,
257 oh);
258 /* Need to do this calculation _before_ the result callback,
259 as IF the application still has a valid set handle, it
260 may trigger destruction of the set during the callback. */
261 destroy_set = (GNUNET_YES == set->destroy_requested) &&
262 (NULL == set->ops_head);
263 if (NULL != oh->result_cb)
264 {
265 oh->result_cb (oh->result_cls,
266 NULL,
267 GNUNET_ntohll (msg->current_size),
268 result_status);
269 }
270 else
271 {
272 LOG (GNUNET_ERROR_TYPE_DEBUG,
273 "No callback for final status\n");
274 }
275 if (destroy_set)
276 GNUNET_SETU_destroy (set);
277 GNUNET_free (oh);
278 return;
279 }
280}
281
282
283/**
284 * Destroy the given set operation.
285 *
286 * @param oh set operation to destroy
287 */
288static void
289set_operation_destroy (struct GNUNET_SETU_OperationHandle *oh)
290{
291 struct GNUNET_SETU_Handle *set = oh->set;
292 struct GNUNET_SETU_OperationHandle *h_assoc;
293
294 if (NULL != oh->conclude_mqm)
295 GNUNET_MQ_discard (oh->conclude_mqm);
296 /* is the operation already commited? */
297 if (NULL != set)
298 {
299 GNUNET_CONTAINER_DLL_remove (set->ops_head,
300 set->ops_tail,
301 oh);
302 h_assoc = GNUNET_MQ_assoc_remove (set->mq,
303 oh->request_id);
304 GNUNET_assert ((NULL == h_assoc) ||
305 (h_assoc == oh));
306 }
307 GNUNET_free (oh);
308}
309
310
311/**
312 * Cancel the given set operation. We need to send an explicit cancel
313 * message, as all operations one one set communicate using one
314 * handle.
315 *
316 * @param oh set operation to cancel
317 */
318void
319GNUNET_SETU_operation_cancel (struct GNUNET_SETU_OperationHandle *oh)
320{
321 struct GNUNET_SETU_Handle *set = oh->set;
322 struct GNUNET_SETU_CancelMessage *m;
323 struct GNUNET_MQ_Envelope *mqm;
324
325 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Cancelling SET operation\n");
327 if (NULL != set)
328 {
329 mqm = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SETU_CANCEL);
330 m->request_id = htonl (oh->request_id);
331 GNUNET_MQ_send (set->mq, mqm);
332 }
333 set_operation_destroy (oh);
334 if ((NULL != set) &&
335 (GNUNET_YES == set->destroy_requested) &&
336 (NULL == set->ops_head))
337 {
338 LOG (GNUNET_ERROR_TYPE_DEBUG,
339 "Destroying set after operation cancel\n");
340 GNUNET_SETU_destroy (set);
341 }
342}
343
344
345/**
346 * We encountered an error communicating with the set service while
347 * performing a set operation. Report to the application.
348 *
349 * @param cls the `struct GNUNET_SETU_Handle`
350 * @param error error code
351 */
352static void
353handle_client_set_error (void *cls,
354 enum GNUNET_MQ_Error error)
355{
356 struct GNUNET_SETU_Handle *set = cls;
357
358 LOG (GNUNET_ERROR_TYPE_ERROR,
359 "Handling client set error %d\n",
360 error);
361 while (NULL != set->ops_head)
362 {
363 if ((NULL != set->ops_head->result_cb) &&
364 (GNUNET_NO == set->destroy_requested))
365 set->ops_head->result_cb (set->ops_head->result_cls,
366 NULL,
367 0,
368 GNUNET_SETU_STATUS_FAILURE);
369 set_operation_destroy (set->ops_head);
370 }
371 set->invalid = GNUNET_YES;
372}
373
374
375/**
376 * Create an empty set, supporting the specified operation.
377 *
378 * @param cfg configuration to use for connecting to the
379 * set service
380 * @return a handle to the set
381 */
382struct GNUNET_SETU_Handle *
383GNUNET_SETU_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
384{
385 struct GNUNET_SETU_Handle *set = GNUNET_new (struct GNUNET_SETU_Handle);
386 struct GNUNET_MQ_MessageHandler mq_handlers[] = {
387 GNUNET_MQ_hd_var_size (result,
388 GNUNET_MESSAGE_TYPE_SETU_RESULT,
389 struct GNUNET_SETU_ResultMessage,
390 set),
391 GNUNET_MQ_handler_end ()
392 };
393 struct GNUNET_MQ_Envelope *mqm;
394 struct GNUNET_SETU_CreateMessage *create_msg;
395
396 set->mq = GNUNET_CLIENT_connect (cfg,
397 "setu",
398 mq_handlers,
399 &handle_client_set_error,
400 set);
401 if (NULL == set->mq)
402 {
403 GNUNET_free (set);
404 return NULL;
405 }
406 mqm = GNUNET_MQ_msg (create_msg,
407 GNUNET_MESSAGE_TYPE_SETU_CREATE);
408 GNUNET_MQ_send (set->mq,
409 mqm);
410 return set;
411}
412
413
414/**
415 * Add an element to the given set. After the element has been added
416 * (in the sense of being transmitted to the set service), @a cont
417 * will be called. Multiple calls to GNUNET_SETU_add_element() can be
418 * queued.
419 *
420 * @param set set to add element to
421 * @param element element to add to the set
422 * @param cb continuation called after the element has been added
423 * @param cb_cls closure for @a cb
424 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
425 * set is invalid (e.g. the set service crashed)
426 */
427int
428GNUNET_SETU_add_element (struct GNUNET_SETU_Handle *set,
429 const struct GNUNET_SETU_Element *element,
430 GNUNET_SCHEDULER_TaskCallback cb,
431 void *cb_cls)
432{
433 struct GNUNET_MQ_Envelope *mqm;
434 struct GNUNET_SETU_ElementMessage *msg;
435
436 LOG (GNUNET_ERROR_TYPE_DEBUG,
437 "adding element of type %u to set %p\n",
438 (unsigned int) element->element_type,
439 set);
440 GNUNET_assert (NULL != set);
441 if (GNUNET_YES == set->invalid)
442 {
443 if (NULL != cb)
444 cb (cb_cls);
445 return GNUNET_SYSERR;
446 }
447 mqm = GNUNET_MQ_msg_extra (msg,
448 element->size,
449 GNUNET_MESSAGE_TYPE_SETU_ADD);
450 msg->element_type = htons (element->element_type);
451 GNUNET_memcpy (&msg[1],
452 element->data,
453 element->size);
454 GNUNET_MQ_notify_sent (mqm,
455 cb,
456 cb_cls);
457 GNUNET_MQ_send (set->mq,
458 mqm);
459 return GNUNET_OK;
460}
461
462
463/**
464 * Destroy the set handle if no operations are left, mark the set
465 * for destruction otherwise.
466 *
467 * @param set set handle to destroy
468 */
469void
470GNUNET_SETU_destroy (struct GNUNET_SETU_Handle *set)
471{
472 /* destroying set while iterator is active is currently
473 not supported; we should expand the API to allow
474 clients to explicitly cancel the iteration! */
475 GNUNET_assert (NULL != set);
476 if ((NULL != set->ops_head) ||
477 (GNUNET_SYSERR == set->destroy_requested))
478 {
479 LOG (GNUNET_ERROR_TYPE_DEBUG,
480 "Set operations are pending, delaying set destruction\n");
481 set->destroy_requested = GNUNET_YES;
482 return;
483 }
484 LOG (GNUNET_ERROR_TYPE_DEBUG,
485 "Really destroying set\n");
486 if (NULL != set->mq)
487 {
488 GNUNET_MQ_destroy (set->mq);
489 set->mq = NULL;
490 }
491 GNUNET_free (set);
492}
493
494
495/**
496 * Prepare a set operation to be evaluated with another peer.
497 * The evaluation will not start until the client provides
498 * a local set with #GNUNET_SETU_commit().
499 *
500 * @param other_peer peer with the other set
501 * @param app_id hash for the application using the set
502 * @param context_msg additional information for the request
503 * @param result_cb called on error or success
504 * @param result_cls closure for @e result_cb
505 * @return a handle to cancel the operation
506 */
507struct GNUNET_SETU_OperationHandle *
508GNUNET_SETU_prepare (const struct GNUNET_PeerIdentity *other_peer,
509 const struct GNUNET_HashCode *app_id,
510 const struct GNUNET_MessageHeader *context_msg,
511 const struct GNUNET_SETU_Option options[],
512 GNUNET_SETU_ResultIterator result_cb,
513 void *result_cls)
514{
515 struct GNUNET_MQ_Envelope *mqm;
516 struct GNUNET_SETU_OperationHandle *oh;
517 struct GNUNET_SETU_EvaluateMessage *msg;
518
519 LOG (GNUNET_ERROR_TYPE_DEBUG,
520 "Client prepares set union operation\n");
521 oh = GNUNET_new (struct GNUNET_SETU_OperationHandle);
522 oh->result_cb = result_cb;
523 oh->result_cls = result_cls;
524 mqm = GNUNET_MQ_msg_nested_mh (msg,
525 GNUNET_MESSAGE_TYPE_SETU_EVALUATE,
526 context_msg);
527 msg->app_id = *app_id;
528 msg->target_peer = *other_peer;
529 for (const struct GNUNET_SETU_Option *opt = options; opt->type != 0; opt++)
530 {
531 switch (opt->type)
532 {
533 case GNUNET_SETU_OPTION_BYZANTINE:
534 msg->byzantine = GNUNET_YES;
535 msg->byzantine_lower_bound = htonl (opt->v.num);
536 break;
537 case GNUNET_SETU_OPTION_FORCE_FULL:
538 msg->force_full = GNUNET_YES;
539 break;
540 case GNUNET_SETU_OPTION_FORCE_DELTA:
541 msg->force_delta = GNUNET_YES;
542 break;
543 case GNUNET_SETU_OPTION_SYMMETRIC:
544 msg->symmetric = GNUNET_YES;
545 break;
546 default:
547 LOG (GNUNET_ERROR_TYPE_ERROR,
548 "Option with type %d not recognized\n",
549 (int) opt->type);
550 }
551 }
552 oh->conclude_mqm = mqm;
553 oh->request_id_addr = &msg->request_id;
554 return oh;
555}
556
557
558/**
559 * Connect to the set service in order to listen for requests.
560 *
561 * @param cls the `struct GNUNET_SETU_ListenHandle *` to connect
562 */
563static void
564listen_connect (void *cls);
565
566
567/**
568 * Check validity of request message for a listen operation
569 *
570 * @param cls the listen handle
571 * @param msg the message
572 * @return #GNUNET_OK if the message is well-formed
573 */
574static int
575check_request (void *cls,
576 const struct GNUNET_SETU_RequestMessage *msg)
577{
578 const struct GNUNET_MessageHeader *context_msg;
579
580 if (ntohs (msg->header.size) == sizeof(*msg))
581 return GNUNET_OK; /* no context message is OK */
582 context_msg = GNUNET_MQ_extract_nested_mh (msg);
583 if (NULL == context_msg)
584 {
585 /* malformed context message is NOT ok */
586 GNUNET_break_op (0);
587 return GNUNET_SYSERR;
588 }
589 return GNUNET_OK;
590}
591
592
593/**
594 * Handle request message for a listen operation
595 *
596 * @param cls the listen handle
597 * @param msg the message
598 */
599static void
600handle_request (void *cls,
601 const struct GNUNET_SETU_RequestMessage *msg)
602{
603 struct GNUNET_SETU_ListenHandle *lh = cls;
604 struct GNUNET_SETU_Request req;
605 const struct GNUNET_MessageHeader *context_msg;
606 struct GNUNET_MQ_Envelope *mqm;
607 struct GNUNET_SETU_RejectMessage *rmsg;
608
609 LOG (GNUNET_ERROR_TYPE_DEBUG,
610 "Processing incoming operation request with id %u\n",
611 ntohl (msg->accept_id));
612 /* we got another valid request => reset the backoff */
613 lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
614 req.accept_id = ntohl (msg->accept_id);
615 req.accepted = GNUNET_NO;
616 context_msg = GNUNET_MQ_extract_nested_mh (msg);
617 /* calling #GNUNET_SETU_accept() in the listen cb will set req->accepted */
618 lh->listen_cb (lh->listen_cls,
619 &msg->peer_id,
620 context_msg,
621 &req);
622 if (GNUNET_YES == req.accepted)
623 return; /* the accept-case is handled in #GNUNET_SETU_accept() */
624 LOG (GNUNET_ERROR_TYPE_DEBUG,
625 "Rejected request %u\n",
626 ntohl (msg->accept_id));
627 mqm = GNUNET_MQ_msg (rmsg,
628 GNUNET_MESSAGE_TYPE_SETU_REJECT);
629 rmsg->accept_reject_id = msg->accept_id;
630 GNUNET_MQ_send (lh->mq,
631 mqm);
632}
633
634
635/**
636 * Our connection with the set service encountered an error,
637 * re-initialize with exponential back-off.
638 *
639 * @param cls the `struct GNUNET_SETU_ListenHandle *`
640 * @param error reason for the disconnect
641 */
642static void
643handle_client_listener_error (void *cls,
644 enum GNUNET_MQ_Error error)
645{
646 struct GNUNET_SETU_ListenHandle *lh = cls;
647
648 LOG (GNUNET_ERROR_TYPE_DEBUG,
649 "Listener broke down (%d), re-connecting\n",
650 (int) error);
651 GNUNET_MQ_destroy (lh->mq);
652 lh->mq = NULL;
653 lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff,
654 &listen_connect,
655 lh);
656 lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff);
657}
658
659
660/**
661 * Connect to the set service in order to listen for requests.
662 *
663 * @param cls the `struct GNUNET_SETU_ListenHandle *` to connect
664 */
665static void
666listen_connect (void *cls)
667{
668 struct GNUNET_SETU_ListenHandle *lh = cls;
669 struct GNUNET_MQ_MessageHandler mq_handlers[] = {
670 GNUNET_MQ_hd_var_size (request,
671 GNUNET_MESSAGE_TYPE_SETU_REQUEST,
672 struct GNUNET_SETU_RequestMessage,
673 lh),
674 GNUNET_MQ_handler_end ()
675 };
676 struct GNUNET_MQ_Envelope *mqm;
677 struct GNUNET_SETU_ListenMessage *msg;
678
679 lh->reconnect_task = NULL;
680 GNUNET_assert (NULL == lh->mq);
681 lh->mq = GNUNET_CLIENT_connect (lh->cfg,
682 "setu",
683 mq_handlers,
684 &handle_client_listener_error,
685 lh);
686 if (NULL == lh->mq)
687 return;
688 mqm = GNUNET_MQ_msg (msg,
689 GNUNET_MESSAGE_TYPE_SETU_LISTEN);
690 msg->app_id = lh->app_id;
691 GNUNET_MQ_send (lh->mq,
692 mqm);
693}
694
695
696/**
697 * Wait for set operation requests for the given application id
698 *
699 * @param cfg configuration to use for connecting to
700 * the set service, needs to be valid for the lifetime of the listen handle
701 * @param app_id id of the application that handles set operation requests
702 * @param listen_cb called for each incoming request matching the operation
703 * and application id
704 * @param listen_cls handle for @a listen_cb
705 * @return a handle that can be used to cancel the listen operation
706 */
707struct GNUNET_SETU_ListenHandle *
708GNUNET_SETU_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
709 const struct GNUNET_HashCode *app_id,
710 GNUNET_SETU_ListenCallback listen_cb,
711 void *listen_cls)
712{
713 struct GNUNET_SETU_ListenHandle *lh;
714
715 LOG (GNUNET_ERROR_TYPE_DEBUG,
716 "Starting listener for app %s\n",
717 GNUNET_h2s (app_id));
718 lh = GNUNET_new (struct GNUNET_SETU_ListenHandle);
719 lh->listen_cb = listen_cb;
720 lh->listen_cls = listen_cls;
721 lh->cfg = cfg;
722 lh->app_id = *app_id;
723 lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
724 listen_connect (lh);
725 if (NULL == lh->mq)
726 {
727 GNUNET_free (lh);
728 return NULL;
729 }
730 return lh;
731}
732
733
734/**
735 * Cancel the given listen operation.
736 *
737 * @param lh handle for the listen operation
738 */
739void
740GNUNET_SETU_listen_cancel (struct GNUNET_SETU_ListenHandle *lh)
741{
742 LOG (GNUNET_ERROR_TYPE_DEBUG,
743 "Canceling listener %s\n",
744 GNUNET_h2s (&lh->app_id));
745 if (NULL != lh->mq)
746 {
747 GNUNET_MQ_destroy (lh->mq);
748 lh->mq = NULL;
749 }
750 if (NULL != lh->reconnect_task)
751 {
752 GNUNET_SCHEDULER_cancel (lh->reconnect_task);
753 lh->reconnect_task = NULL;
754 }
755 GNUNET_free (lh);
756}
757
758
759/**
760 * Accept a request we got via #GNUNET_SETU_listen. Must be called during
761 * #GNUNET_SETU_listen, as the 'struct GNUNET_SETU_Request' becomes invalid
762 * afterwards.
763 * Call #GNUNET_SETU_commit to provide the local set to use for the operation,
764 * and to begin the exchange with the remote peer.
765 *
766 * @param request request to accept
767 * @param result_mode specified how results will be returned,
768 * see `enum GNUNET_SETU_ResultMode`.
769 * @param result_cb callback for the results
770 * @param result_cls closure for @a result_cb
771 * @return a handle to cancel the operation
772 */
773struct GNUNET_SETU_OperationHandle *
774GNUNET_SETU_accept (struct GNUNET_SETU_Request *request,
775 const struct GNUNET_SETU_Option options[],
776 GNUNET_SETU_ResultIterator result_cb,
777 void *result_cls)
778{
779 struct GNUNET_MQ_Envelope *mqm;
780 struct GNUNET_SETU_OperationHandle *oh;
781 struct GNUNET_SETU_AcceptMessage *msg;
782
783 GNUNET_assert (GNUNET_NO == request->accepted);
784 LOG (GNUNET_ERROR_TYPE_DEBUG,
785 "Client accepts set union operation with id %u\n",
786 request->accept_id);
787 request->accepted = GNUNET_YES;
788 mqm = GNUNET_MQ_msg (msg,
789 GNUNET_MESSAGE_TYPE_SETU_ACCEPT);
790 msg->accept_reject_id = htonl (request->accept_id);
791 for (const struct GNUNET_SETU_Option *opt = options; opt->type != 0; opt++)
792 {
793 switch (opt->type)
794 {
795 case GNUNET_SETU_OPTION_BYZANTINE:
796 msg->byzantine = GNUNET_YES;
797 msg->byzantine_lower_bound = htonl (opt->v.num);
798 break;
799 case GNUNET_SETU_OPTION_FORCE_FULL:
800 msg->force_full = GNUNET_YES;
801 break;
802 case GNUNET_SETU_OPTION_FORCE_DELTA:
803 msg->force_delta = GNUNET_YES;
804 break;
805 case GNUNET_SETU_OPTION_SYMMETRIC:
806 msg->symmetric = GNUNET_YES;
807 break;
808 default:
809 LOG (GNUNET_ERROR_TYPE_ERROR,
810 "Option with type %d not recognized\n",
811 (int) opt->type);
812 }
813 }
814 oh = GNUNET_new (struct GNUNET_SETU_OperationHandle);
815 oh->result_cb = result_cb;
816 oh->result_cls = result_cls;
817 oh->conclude_mqm = mqm;
818 oh->request_id_addr = &msg->request_id;
819 return oh;
820}
821
822
823/**
824 * Commit a set to be used with a set operation.
825 * This function is called once we have fully constructed
826 * the set that we want to use for the operation. At this
827 * time, the P2P protocol can then begin to exchange the
828 * set information and call the result callback with the
829 * result information.
830 *
831 * @param oh handle to the set operation
832 * @param set the set to use for the operation
833 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
834 * set is invalid (e.g. the set service crashed)
835 */
836int
837GNUNET_SETU_commit (struct GNUNET_SETU_OperationHandle *oh,
838 struct GNUNET_SETU_Handle *set)
839{
840 if (NULL != oh->set)
841 {
842 /* Some other set was already committed for this
843 * operation, there is a logic bug in the client of this API */
844 GNUNET_break (0);
845 return GNUNET_OK;
846 }
847 GNUNET_assert (NULL != set);
848 if (GNUNET_YES == set->invalid)
849 return GNUNET_SYSERR;
850 LOG (GNUNET_ERROR_TYPE_DEBUG,
851 "Client commits to SET\n");
852 GNUNET_assert (NULL != oh->conclude_mqm);
853 oh->set = set;
854 GNUNET_CONTAINER_DLL_insert (set->ops_head,
855 set->ops_tail,
856 oh);
857 oh->request_id = GNUNET_MQ_assoc_add (set->mq,
858 oh);
859 *oh->request_id_addr = htonl (oh->request_id);
860 GNUNET_MQ_send (set->mq,
861 oh->conclude_mqm);
862 oh->conclude_mqm = NULL;
863 oh->request_id_addr = NULL;
864 return GNUNET_OK;
865}
866
867
868/**
869 * Hash a set element.
870 *
871 * @param element the element that should be hashed
872 * @param[out] ret_hash a pointer to where the hash of @a element
873 * should be stored
874 */
875void
876GNUNET_SETU_element_hash (const struct GNUNET_SETU_Element *element,
877 struct GNUNET_HashCode *ret_hash)
878{
879 struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
880
881 /* It's not guaranteed that the element data is always after the element header,
882 so we need to hash the chunks separately. */
883 GNUNET_CRYPTO_hash_context_read (ctx,
884 &element->size,
885 sizeof(uint16_t));
886 GNUNET_CRYPTO_hash_context_read (ctx,
887 &element->element_type,
888 sizeof(uint16_t));
889 GNUNET_CRYPTO_hash_context_read (ctx,
890 element->data,
891 element->size);
892 GNUNET_CRYPTO_hash_context_finish (ctx,
893 ret_hash);
894}
895
896
897/* end of setu_api.c */
diff --git a/src/setu/test_setu_api.c b/src/setu/test_setu_api.c
new file mode 100644
index 000000000..95119873c
--- /dev/null
+++ b/src/setu/test_setu_api.c
@@ -0,0 +1,360 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file set/test_setu_api.c
23 * @brief testcase for setu_api.c
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_setu_service.h"
30
31
32static struct GNUNET_PeerIdentity local_id;
33
34static struct GNUNET_HashCode app_id;
35
36static struct GNUNET_SETU_Handle *set1;
37
38static struct GNUNET_SETU_Handle *set2;
39
40static struct GNUNET_SETU_ListenHandle *listen_handle;
41
42static struct GNUNET_SETU_OperationHandle *oh1;
43
44static struct GNUNET_SETU_OperationHandle *oh2;
45
46static const struct GNUNET_CONFIGURATION_Handle *config;
47
48static int ret;
49
50static struct GNUNET_SCHEDULER_Task *tt;
51
52
53static void
54result_cb_set1 (void *cls,
55 const struct GNUNET_SETU_Element *element,
56 uint64_t size,
57 enum GNUNET_SETU_Status status)
58{
59 switch (status)
60 {
61 case GNUNET_SETU_STATUS_ADD_LOCAL:
62 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: got element\n");
63 break;
64
65 case GNUNET_SETU_STATUS_FAILURE:
66 GNUNET_break (0);
67 oh1 = NULL;
68 fprintf (stderr, "set 1: received failure status!\n");
69 ret = 1;
70 if (NULL != tt)
71 {
72 GNUNET_SCHEDULER_cancel (tt);
73 tt = NULL;
74 }
75 GNUNET_SCHEDULER_shutdown ();
76 break;
77
78 case GNUNET_SETU_STATUS_DONE:
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: done\n");
80 oh1 = NULL;
81 if (NULL != set1)
82 {
83 GNUNET_SETU_destroy (set1);
84 set1 = NULL;
85 }
86 if (NULL == set2)
87 {
88 GNUNET_SCHEDULER_cancel (tt);
89 tt = NULL;
90 GNUNET_SCHEDULER_shutdown ();
91 }
92 break;
93
94 default:
95 GNUNET_assert (0);
96 }
97}
98
99
100static void
101result_cb_set2 (void *cls,
102 const struct GNUNET_SETU_Element *element,
103 uint64_t size,
104 enum GNUNET_SETU_Status status)
105{
106 switch (status)
107 {
108 case GNUNET_SETU_STATUS_ADD_LOCAL:
109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: got element\n");
110 break;
111
112 case GNUNET_SETU_STATUS_FAILURE:
113 GNUNET_break (0);
114 oh2 = NULL;
115 fprintf (stderr, "set 2: received failure status\n");
116 GNUNET_SCHEDULER_shutdown ();
117 ret = 1;
118 break;
119
120 case GNUNET_SETU_STATUS_DONE:
121 oh2 = NULL;
122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: done\n");
123 GNUNET_SETU_destroy (set2);
124 set2 = NULL;
125 if (NULL == set1)
126 {
127 GNUNET_SCHEDULER_cancel (tt);
128 tt = NULL;
129 GNUNET_SCHEDULER_shutdown ();
130 }
131 break;
132
133 default:
134 GNUNET_assert (0);
135 }
136}
137
138
139static void
140listen_cb (void *cls,
141 const struct GNUNET_PeerIdentity *other_peer,
142 const struct GNUNET_MessageHeader *context_msg,
143 struct GNUNET_SETU_Request *request)
144{
145 GNUNET_assert (NULL != context_msg);
146 GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "listen cb called\n");
148 oh2 = GNUNET_SETU_accept (request,
149 (struct GNUNET_SETU_Option[]){ 0 },
150 &result_cb_set2,
151 NULL);
152 GNUNET_SETU_commit (oh2, set2);
153}
154
155
156/**
157 * Start the set operation.
158 *
159 * @param cls closure, unused
160 */
161static void
162start (void *cls)
163{
164 struct GNUNET_MessageHeader context_msg;
165
166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting reconciliation\n");
167 context_msg.size = htons (sizeof context_msg);
168 context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
169 listen_handle = GNUNET_SETU_listen (config,
170 &app_id,
171 &listen_cb,
172 NULL);
173 oh1 = GNUNET_SETU_prepare (&local_id,
174 &app_id,
175 &context_msg,
176 (struct GNUNET_SETU_Option[]){ 0 },
177 &result_cb_set1,
178 NULL);
179 GNUNET_SETU_commit (oh1, set1);
180}
181
182
183/**
184 * Initialize the second set, continue
185 *
186 * @param cls closure, unused
187 */
188static void
189init_set2 (void *cls)
190{
191 struct GNUNET_SETU_Element element;
192
193 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n");
194
195 element.element_type = 0;
196 element.data = "hello";
197 element.size = strlen (element.data);
198 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
199 element.data = "quux";
200 element.size = strlen (element.data);
201 GNUNET_SETU_add_element (set2, &element, NULL, NULL);
202 element.data = "baz";
203 element.size = strlen (element.data);
204 GNUNET_SETU_add_element (set2, &element, &start, NULL);
205}
206
207
208/**
209 * Initialize the first set, continue.
210 */
211static void
212init_set1 (void)
213{
214 struct GNUNET_SETU_Element element;
215
216 element.element_type = 0;
217 element.data = "hello";
218 element.size = strlen (element.data);
219 GNUNET_SETU_add_element (set1, &element, NULL, NULL);
220 element.data = "bar";
221 element.size = strlen (element.data);
222 GNUNET_SETU_add_element (set1, &element, &init_set2, NULL);
223 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized set 1\n");
224}
225
226
227/**
228 * Function run on timeout.
229 *
230 * @param cls closure
231 */
232static void
233timeout_fail (void *cls)
234{
235 tt = NULL;
236 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Testcase failed with timeout\n");
237 GNUNET_SCHEDULER_shutdown ();
238 ret = 1;
239}
240
241
242/**
243 * Function run on shutdown.
244 *
245 * @param cls closure
246 */
247static void
248do_shutdown (void *cls)
249{
250 if (NULL != tt)
251 {
252 GNUNET_SCHEDULER_cancel (tt);
253 tt = NULL;
254 }
255 if (NULL != oh1)
256 {
257 GNUNET_SETU_operation_cancel (oh1);
258 oh1 = NULL;
259 }
260 if (NULL != oh2)
261 {
262 GNUNET_SETU_operation_cancel (oh2);
263 oh2 = NULL;
264 }
265 if (NULL != set1)
266 {
267 GNUNET_SETU_destroy (set1);
268 set1 = NULL;
269 }
270 if (NULL != set2)
271 {
272 GNUNET_SETU_destroy (set2);
273 set2 = NULL;
274 }
275 if (NULL != listen_handle)
276 {
277 GNUNET_SETU_listen_cancel (listen_handle);
278 listen_handle = NULL;
279 }
280}
281
282
283/**
284 * Signature of the 'main' function for a (single-peer) testcase that
285 * is run using 'GNUNET_TESTING_peer_run'.
286 *
287 * @param cls closure
288 * @param cfg configuration of the peer that was started
289 * @param peer identity of the peer that was created
290 */
291static void
292run (void *cls,
293 const struct GNUNET_CONFIGURATION_Handle *cfg,
294 struct GNUNET_TESTING_Peer *peer)
295{
296 struct GNUNET_SETU_OperationHandle *my_oh;
297
298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
299 "Running preparatory tests\n");
300 tt = GNUNET_SCHEDULER_add_delayed (
301 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
302 &timeout_fail,
303 NULL);
304 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
305
306 config = cfg;
307 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_get_peer_identity (cfg,
308 &local_id));
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
310 "my id (from CRYPTO): %s\n",
311 GNUNET_i2s (&local_id));
312 GNUNET_TESTING_peer_get_identity (peer,
313 &local_id);
314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 "my id (from TESTING): %s\n",
316 GNUNET_i2s (&local_id));
317 set1 = GNUNET_SETU_create (cfg);
318 set2 = GNUNET_SETU_create (cfg);
319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
320 "Created sets %p and %p for union operation\n",
321 set1,
322 set2);
323 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
324
325 /* test if canceling an uncommited request works! */
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327 "Launching and instantly stopping set operation\n");
328 my_oh = GNUNET_SETU_prepare (&local_id,
329 &app_id,
330 NULL,
331 (struct GNUNET_SETU_Option[]){ 0 },
332 NULL,
333 NULL);
334 GNUNET_SETU_operation_cancel (my_oh);
335
336 /* test the real set reconciliation */
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Running real set-reconciliation\n");
339 init_set1 ();
340}
341
342
343int
344main (int argc, char **argv)
345{
346 GNUNET_log_setup ("test_setu_api",
347 "WARNING",
348 NULL);
349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
350 "Launching peer\n");
351 if (0 !=
352 GNUNET_TESTING_peer_run ("test_setu_api",
353 "test_setu.conf",
354 &run,
355 NULL))
356 {
357 return 1;
358 }
359 return ret;
360}
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index baefdfa88..2f6e17f3b 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -3209,7 +3209,7 @@ notify_monitors (const struct GNUNET_PeerIdentity *peer,
3209 continue; 3209 continue;
3210 if (tc->details.monitor.one_shot) 3210 if (tc->details.monitor.one_shot)
3211 continue; 3211 continue;
3212 if ((0 != GNUNET_is_zero (&tc->details.monitor.peer)) && 3212 if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
3213 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer))) 3213 (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
3214 continue; 3214 continue;
3215 notify_monitor (tc, peer, address, nt, me); 3215 notify_monitor (tc, peer, address, nt, me);
diff --git a/src/util/.gitignore b/src/util/.gitignore
index 05f187869..8556ee7b8 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -71,9 +71,10 @@ perf_crypto_hash
71perf_crypto_symmetric 71perf_crypto_symmetric
72perf_crypto_rsa 72perf_crypto_rsa
73perf_crypto_ecc_dlog 73perf_crypto_ecc_dlog
74test_hexcoder 74test_hexcoder
75test_regex 75test_regex
76test_tun 76test_tun
77test_uri
77gnunet-timeout 78gnunet-timeout
78python27_location 79python27_location
79perf_malloc 80perf_malloc
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 83b3b9c3d..c5059bbb1 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -96,6 +96,7 @@ libgnunetutil_la_SOURCES = \
96 strings.c \ 96 strings.c \
97 time.c \ 97 time.c \
98 tun.c \ 98 tun.c \
99 uri.c \
99 speedup.c speedup.h \ 100 speedup.c speedup.h \
100 proc_compat.c 101 proc_compat.c
101 102
@@ -302,6 +303,7 @@ check_PROGRAMS = \
302 test_speedup \ 303 test_speedup \
303 test_time \ 304 test_time \
304 test_tun \ 305 test_tun \
306 test_uri \
305 $(BENCHMARKS) \ 307 $(BENCHMARKS) \
306 test_os_start_process \ 308 test_os_start_process \
307 test_common_logging_runtime_loglevels 309 test_common_logging_runtime_loglevels
@@ -573,6 +575,11 @@ test_speedup_SOURCES = \
573test_speedup_LDADD = \ 575test_speedup_LDADD = \
574 libgnunetutil.la 576 libgnunetutil.la
575 577
578test_uri_SOURCES = \
579 test_uri.c
580test_uri_LDADD = \
581 libgnunetutil.la
582
576perf_crypto_hash_SOURCES = \ 583perf_crypto_hash_SOURCES = \
577 perf_crypto_hash.c 584 perf_crypto_hash.c
578perf_crypto_hash_LDADD = \ 585perf_crypto_hash_LDADD = \
diff --git a/src/util/common_allocation.c b/src/util/common_allocation.c
index 4aad49777..a404a1627 100644
--- a/src/util/common_allocation.c
+++ b/src/util/common_allocation.c
@@ -538,9 +538,9 @@ GNUNET_copy_message (const struct GNUNET_MessageHeader *msg)
538 * @param a pointer to @a n bytes which should be tested for the 538 * @param a pointer to @a n bytes which should be tested for the
539 * entire memory being zero'ed out. 539 * entire memory being zero'ed out.
540 * @param n number of bytes in @a to be tested 540 * @param n number of bytes in @a to be tested
541 * @return 0 if a is zero, non-zero otherwise 541 * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
542 */ 542 */
543int 543enum GNUNET_GenericReturnValue
544GNUNET_is_zero_ (const void *a, 544GNUNET_is_zero_ (const void *a,
545 size_t n) 545 size_t n)
546{ 546{
@@ -548,8 +548,8 @@ GNUNET_is_zero_ (const void *a,
548 548
549 for (size_t i = 0; i < n; i++) 549 for (size_t i = 0; i < n; i++)
550 if (b[i]) 550 if (b[i])
551 return 1; 551 return GNUNET_NO;
552 return 0; 552 return GNUNET_YES;
553} 553}
554 554
555 555
diff --git a/src/util/crypto_pow.c b/src/util/crypto_pow.c
index cfa0676d0..051a0c209 100644
--- a/src/util/crypto_pow.c
+++ b/src/util/crypto_pow.c
@@ -38,12 +38,11 @@
38 * @param result where to write the resulting hash 38 * @param result where to write the resulting hash
39 */ 39 */
40void 40void
41GNUNET_CRYPTO_pow_hash (const char *salt, 41GNUNET_CRYPTO_pow_hash (const struct GNUNET_CRYPTO_PowSalt *salt,
42 const void *buf, 42 const void *buf,
43 size_t buf_len, 43 size_t buf_len,
44 struct GNUNET_HashCode *result) 44 struct GNUNET_HashCode *result)
45{ 45{
46 GNUNET_assert (strlen (salt) == crypto_pwhash_argon2id_SALTBYTES);
47 /* Threads hardcoded at 1 in libsodium */ 46 /* Threads hardcoded at 1 in libsodium */
48 GNUNET_break (0 == 47 GNUNET_break (0 ==
49 crypto_pwhash_argon2id ((unsigned char *) result, 48 crypto_pwhash_argon2id ((unsigned char *) result,
diff --git a/src/util/gnunet-scrypt.c b/src/util/gnunet-scrypt.c
index aa64144a8..136c6debb 100644
--- a/src/util/gnunet-scrypt.c
+++ b/src/util/gnunet-scrypt.c
@@ -26,6 +26,13 @@
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include <gcrypt.h> 27#include <gcrypt.h>
28 28
29
30/**
31 * Salt for PoW calcualations.
32 */
33static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
34
35
29/** 36/**
30 * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits. 37 * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits.
31 */ 38 */
@@ -117,7 +124,7 @@ find_proof (void *cls)
117 while ((counter != UINT64_MAX) && (i < ROUND_SIZE)) 124 while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
118 { 125 {
119 GNUNET_memcpy (buf, &counter, sizeof(uint64_t)); 126 GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
120 GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof", 127 GNUNET_CRYPTO_pow_hash (&salt,
121 buf, 128 buf,
122 sizeof(buf), 129 sizeof(buf),
123 &result); 130 &result);
diff --git a/src/util/service.c b/src/util/service.c
index e6bbe855f..ddd31181d 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -473,7 +473,7 @@ check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
473 return GNUNET_NO; 473 return GNUNET_NO;
474 i = 0; 474 i = 0;
475NEXT: 475NEXT:
476 while (0 != GNUNET_is_zero (&list[i].network)) 476 while (GNUNET_NO == GNUNET_is_zero (&list[i].network))
477 { 477 {
478 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++) 478 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
479 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) != 479 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c
index 6d4a131bb..ff5021d03 100644
--- a/src/util/test_os_start_process.c
+++ b/src/util/test_os_start_process.c
@@ -124,11 +124,8 @@ run_task (void *cls)
124 124
125 GNUNET_asprintf (&fn, "cat"); 125 GNUNET_asprintf (&fn, "cat");
126 126
127 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, 127 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
128 GNUNET_NO); 128 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
129 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
130 GNUNET_YES);
131
132 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) 129 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
133 { 130 {
134 GNUNET_break (0); 131 GNUNET_break (0);
@@ -202,10 +199,8 @@ check_kill ()
202{ 199{
203 char *fn; 200 char *fn;
204 201
205 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, 202 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
206 GNUNET_NO); 203 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
207 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
208 GNUNET_YES);
209 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) 204 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
210 { 205 {
211 return 1; 206 return 1;
@@ -247,10 +242,8 @@ check_instant_kill ()
247{ 242{
248 char *fn; 243 char *fn;
249 244
250 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, 245 hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
251 GNUNET_NO); 246 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
252 hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
253 GNUNET_YES);
254 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) 247 if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
255 { 248 {
256 return 1; 249 return 1;
diff --git a/src/util/test_peer.c b/src/util/test_peer.c
index 320746c76..bb0bc48dc 100644
--- a/src/util/test_peer.c
+++ b/src/util/test_peer.c
@@ -106,8 +106,7 @@ check ()
106 * is expected to be set to zero 106 * is expected to be set to zero
107 */GNUNET_log_skip (1, GNUNET_YES); 107 */GNUNET_log_skip (1, GNUNET_YES);
108 GNUNET_PEER_resolve (0, &res); 108 GNUNET_PEER_resolve (0, &res);
109 GNUNET_assert (0 == 109 GNUNET_assert (GNUNET_YES == GNUNET_is_zero (&res));
110 GNUNET_is_zero (&res));
111 110
112 /* Removing peer entries 1 and 3 from table using the list decrement function */ 111 /* Removing peer entries 1 and 3 from table using the list decrement function */
113 /* If count = 0, nothing should be done whatsoever */ 112 /* If count = 0, nothing should be done whatsoever */
diff --git a/src/util/test_uri.c b/src/util/test_uri.c
new file mode 100644
index 000000000..7c8156648
--- /dev/null
+++ b/src/util/test_uri.c
@@ -0,0 +1,837 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include "gnunet_uri_lib.h"
5
6#define KNRM "\x1B[0m"
7#define KBLU "\x1B[34m"
8#define KGRN "\x1B[32m"
9#define KERR "\x1B[5;31;50m"
10
11/* macro to print out the header for a new group of tests */
12#define mu_group(name) printf ("%s • %s%s\n", KBLU, name, KNRM)
13
14/* macro for asserting a statement */
15#define mu_assert(message, test) do { \
16 if (!(test)) { \
17 printf ("\t%s× %s%s\n", KERR, message, KNRM); \
18 return message; \
19 } \
20 printf ("\t%s• %s%s\n", KGRN, message, KNRM); \
21 } while (0)
22
23/* macro for asserting a statement without printing it unless it is a failure */
24#define mu_silent_assert(message, test) do { \
25 if (!(test)) { \
26 printf ("\t\t%s× %s%s\n", KERR, message, KNRM); \
27 return message; \
28 } \
29 } while (0)
30
31/* run a test function and return result */
32#define mu_run_test(test) do { \
33 char *message = test (); tests_run++; \
34 if (message) { return message; } \
35 } while (0)
36
37
38int tests_run;
39
40static int
41strcmp_wrap (const char *str,
42 const char *str2)
43{
44 if (NULL == str && NULL == str2) {
45 return 0;
46 }
47 if (NULL == str) {
48 return 1;
49 }
50 if (NULL == str2) {
51 return -1;
52 }
53
54 return strcmp (str, str2);
55}
56
57#define assert_struct(as_url, \
58 as_scheme, \
59 as_user, \
60 as_pass, \
61 as_host, \
62 as_port, \
63 as_path, \
64 as_query, \
65 as_fragment) \
66 mu_silent_assert ("should set the scheme attribute correctly", \
67 0 == strcmp_wrap (as_url.scheme, as_scheme)); \
68 mu_silent_assert ("should set the username attribute correctly", \
69 0 == strcmp_wrap (as_url.username, as_user)); \
70 mu_silent_assert ("should set the password attribute correctly", \
71 0 == strcmp_wrap (as_url.password, as_pass)); \
72 mu_silent_assert ("should set the host attribute correctly", \
73 0 == strcmp_wrap (as_url.host, as_host)); \
74 mu_silent_assert ("should set the port attribute correctly", \
75 as_port == as_url.port); \
76 mu_silent_assert ("should set the path attribute correctly", \
77 0 == strcmp_wrap (as_url.path, as_path)); \
78 mu_silent_assert ("should set the query attribute correctly", \
79 0 == strcmp_wrap (as_url.query, as_query)); \
80 mu_silent_assert ("should set the fragment attribute correctly", \
81 0 == strcmp_wrap (as_url.fragment, as_fragment));
82
83static char *
84test_parse_http_url_ok (void)
85{
86 int rc;
87 struct GNUNET_Uri url;
88 char *url_string;
89
90 /* Minimal URL */
91 url_string = strdup ("http://example.com");
92 rc = GNUNET_uri_parse (&url,
93 url_string);
94 mu_assert ("minimal HTTP URL", -1 != rc);
95 assert_struct (url,
96 "http",
97 NULL,
98 NULL,
99 "example.com",
100 0,
101 NULL,
102 NULL,
103 NULL);
104 free (url_string);
105
106 /* With path (/) */
107 url_string = strdup ("http://example.com/");
108 rc = GNUNET_uri_parse (&url,
109 url_string);
110 mu_assert ("with path ('/')", -1 != rc);
111 assert_struct (url,
112 "http",
113 NULL,
114 NULL,
115 "example.com",
116 0,
117 "",
118 NULL,
119 NULL);
120 free (url_string);
121
122 /* With path */
123 url_string = strdup ("http://example.com/path");
124 rc = GNUNET_uri_parse (&url,
125 url_string);
126 mu_assert ("with path ('/path')", -1 != rc);
127 assert_struct (url,
128 "http",
129 NULL,
130 NULL,
131 "example.com",
132 0,
133 "path",
134 NULL,
135 NULL);
136 free (url_string);
137
138 /* With port */
139 url_string = strdup ("http://example.com:80");
140 rc = GNUNET_uri_parse (&url,
141 url_string);
142 mu_assert ("with port only",
143 -1 != rc);
144 assert_struct (url,
145 "http",
146 NULL,
147 NULL,
148 "example.com",
149 80,
150 NULL,
151 NULL,
152 NULL);
153 free (url_string);
154
155 /* With query */
156 url_string = strdup ("http://example.com?query=only");
157 rc = GNUNET_uri_parse (&url,
158 url_string);
159 mu_assert ("with query only",
160 -1 != rc);
161 assert_struct (url,
162 "http",
163 NULL,
164 NULL,
165 "example.com",
166 0,
167 NULL,
168 "query=only",
169 NULL);
170 free (url_string);
171
172 /* With fragment */
173 url_string = strdup ("http://example.com#frag=f1");
174 rc = GNUNET_uri_parse (&url,
175 url_string);
176 mu_assert ("with fragment only",
177 -1 != rc);
178 assert_struct (url,
179 "http",
180 NULL,
181 NULL,
182 "example.com",
183 0,
184 NULL,
185 NULL,
186 "frag=f1");
187 free (url_string);
188
189 /* With credentials */
190 url_string = strdup ("http://u:p@example.com");
191 rc = GNUNET_uri_parse (&url,
192 url_string);
193 mu_assert ("with credentials only",
194 -1 != rc);
195 assert_struct (url,
196 "http",
197 "u",
198 "p",
199 "example.com",
200 0,
201 NULL,
202 NULL,
203 NULL);
204 free (url_string);
205
206 /* With port and path */
207 url_string = strdup ("http://example.com:8080/port/and/path");
208 rc = GNUNET_uri_parse (&url,
209 url_string);
210 mu_assert ("with port and path",
211 -1 != rc);
212 assert_struct (url,
213 "http",
214 NULL,
215 NULL,
216 "example.com",
217 8080,
218 "port/and/path",
219 NULL,
220 NULL);
221 free (url_string);
222
223 /* With port and query */
224 url_string = strdup ("http://example.com:8080?query=portANDquery");
225 rc = GNUNET_uri_parse (&url,
226 url_string);
227 mu_assert ("with port and query",
228 -1 != rc);
229 assert_struct (url,
230 "http",
231 NULL,
232 NULL,
233 "example.com",
234 8080,
235 NULL,
236 "query=portANDquery",
237 NULL);
238 free (url_string);
239
240 /* With port and fragment */
241 url_string = strdup ("http://example.com:8080#f1");
242 rc = GNUNET_uri_parse (&url,
243 url_string);
244 mu_assert ("with port and fragment",
245 -1 != rc);
246 assert_struct (url,
247 "http",
248 NULL,
249 NULL,
250 "example.com",
251 8080,
252 NULL,
253 NULL,
254 "f1");
255 free (url_string);
256
257 /* With port and credentials */
258 url_string = strdup ("http://u:p@example.com:8080");
259 rc = GNUNET_uri_parse (&url,
260 url_string);
261 mu_assert ("with port and credentials",
262 -1 != rc);
263 assert_struct (url,
264 "http",
265 "u",
266 "p",
267 "example.com",
268 8080,
269 NULL,
270 NULL,
271 NULL);
272 free (url_string);
273
274 /* With path and query */
275 url_string = strdup ("http://example.com/path/and/query?q=yes");
276 rc = GNUNET_uri_parse (&url,
277 url_string);
278 mu_assert ("with path and query",
279 -1 != rc);
280 assert_struct (url,
281 "http",
282 NULL,
283 NULL,
284 "example.com",
285 0,
286 "path/and/query",
287 "q=yes",
288 NULL);
289 free (url_string);
290
291 /* With path and fragment */
292 url_string = strdup ("http://example.com/path/and#fragment");
293 rc = GNUNET_uri_parse (&url,
294 url_string);
295 mu_assert ("with path and fragment",
296 -1 != rc);
297 assert_struct (url,
298 "http",
299 NULL,
300 NULL,
301 "example.com",
302 0,
303 "path/and",
304 NULL,
305 "fragment");
306 free (url_string);
307
308 /* With query and fragment */
309 url_string = strdup ("http://example.com?q=yes#f1");
310 rc = GNUNET_uri_parse (&url,
311 url_string);
312 mu_assert ("with query and fragment",
313 -1 != rc);
314 assert_struct (url,
315 "http",
316 NULL,
317 NULL,
318 "example.com",
319 0,
320 NULL,
321 "q=yes",
322 "f1");
323 free (url_string);
324
325 /* With query and credentials */
326 url_string = strdup ("http://u:p@example.com?q=yes");
327 rc = GNUNET_uri_parse (&url,
328 url_string);
329 mu_assert ("with query and credentials",
330 -1 != rc);
331 assert_struct (url,
332 "http",
333 "u",
334 "p",
335 "example.com",
336 0,
337 NULL,
338 "q=yes",
339 NULL);
340 free (url_string);
341
342 /* With empty credentials */
343 url_string = strdup ("http://:@example.com");
344 rc = GNUNET_uri_parse (&url,
345 url_string);
346 mu_assert ("with empty credentials",
347 -1 != rc);
348 assert_struct (url,
349 "http",
350 "",
351 "",
352 "example.com",
353 0,
354 NULL,
355 NULL,
356 NULL);
357 free (url_string);
358
359 /* With empty credentials and port */
360 url_string = strdup ("http://:@example.com:89");
361 rc = GNUNET_uri_parse (&url,
362 url_string);
363 mu_assert ("with empty credentials and port",
364 -1 != rc);
365 assert_struct (url,
366 "http",
367 "",
368 "",
369 "example.com",
370 89,
371 NULL,
372 NULL,
373 NULL);
374 free (url_string);
375
376 /* Full URL */
377 url_string = strdup ("https://jack:password@localhost:8989/path/to/test?query=yes&q=jack#fragment1");
378 rc = GNUNET_uri_parse (&url,
379 url_string);
380 mu_assert ("with port, path and query",
381 -1 != rc);
382 assert_struct (url,
383 "https",
384 "jack",
385 "password",
386 "localhost",
387 8989,
388 "path/to/test",
389 "query=yes&q=jack",
390 "fragment1");
391 free (url_string);
392
393 return NULL;
394}
395
396static char *
397test_parse_http_rel_url_ok (void)
398{
399 int rc;
400 struct GNUNET_Uri url;
401 char *url_string;
402
403 /* Minimal relative URL */
404 url_string = strdup ("/");
405 rc = GNUNET_uri_parse (&url,
406 url_string);
407 mu_assert ("minimal relative URL",
408 -1 != rc);
409 assert_struct (url,
410 NULL,
411 NULL,
412 NULL,
413 NULL,
414 0,
415 "",
416 NULL,
417 NULL);
418 free (url_string);
419
420 /* Path only */
421 url_string = strdup ("/hejsan");
422 rc = GNUNET_uri_parse (&url,
423 url_string);
424 mu_assert ("path only",
425 -1 != rc);
426 assert_struct (url,
427 NULL,
428 NULL,
429 NULL,
430 NULL,
431 0,
432 "hejsan",
433 NULL,
434 NULL);
435 free (url_string);
436
437 /* Path and query */
438 url_string = strdup ("/hejsan?q=yes");
439 rc = GNUNET_uri_parse (&url,
440 url_string);
441 mu_assert ("path only",
442 -1 != rc);
443 assert_struct (url,
444 NULL,
445 NULL,
446 NULL,
447 NULL,
448 0,
449 "hejsan",
450 "q=yes",
451 NULL);
452 free (url_string);
453
454 /* Path and fragment */
455 url_string = strdup ("/hejsan#fragment");
456 rc = GNUNET_uri_parse (&url,
457 url_string);
458 mu_assert ("path and fragment",
459 -1 != rc);
460 assert_struct (url,
461 NULL,
462 NULL,
463 NULL,
464 NULL,
465 0,
466 "hejsan",
467 NULL,
468 "fragment");
469 free (url_string);
470
471 /* Path, query and fragment */
472 url_string = strdup ("/?q=yes&q2=no#fragment");
473 rc = GNUNET_uri_parse (&url,
474 url_string);
475 mu_assert ("path, query and fragment",
476 -1 != rc);
477 assert_struct (url,
478 NULL,
479 NULL,
480 NULL,
481 NULL,
482 0,
483 "",
484 "q=yes&q2=no",
485 "fragment");
486 free (url_string);
487
488 return NULL;
489}
490
491static char *
492test_parse_url_fail (void)
493{
494 int rc;
495 struct GNUNET_Uri url;
496 char *url_string;
497
498 /* Empty */
499 url_string = strdup ("");
500 rc = GNUNET_uri_parse (&url,
501 url_string);
502 mu_assert ("empty string should return -1",
503 -1 == rc);
504 free (url_string);
505
506 /* Scheme only */
507 url_string = strdup ("rtsp://");
508 rc = GNUNET_uri_parse (&url,
509 url_string);
510 mu_assert ("scheme only should return -1",
511 -1 == rc);
512 free (url_string);
513
514 /* Hostname only */
515 url_string = strdup ("hostname");
516 rc = GNUNET_uri_parse (&url,
517 url_string);
518 mu_assert ("hostname only should return -1",
519 -1 == rc);
520 free (url_string);
521
522 /* Query only */
523 url_string = strdup ("?query=only");
524 rc = GNUNET_uri_parse (&url,
525 url_string);
526 mu_assert ("query only should return -1",
527 -1 == rc);
528 free (url_string);
529
530 /* Missing scheme */
531 url_string = strdup ("://");
532 rc = GNUNET_uri_parse (&url,
533 url_string);
534 mu_assert ("missing scheme should return -1",
535 -1 == rc);
536 free (url_string);
537
538 /* Missing hostname */
539 url_string = strdup ("rtsp://:8910/path");
540 rc = GNUNET_uri_parse (&url,
541 url_string);
542 mu_assert ("missing hostname should return -1",
543 -1 == rc);
544 free (url_string);
545
546 /* Missing credentials */
547 url_string = strdup ("rtsp://@hostname:8910/path");
548 rc = GNUNET_uri_parse (&url,
549 url_string);
550 mu_assert ("missing credentials should return -1",
551 -1 == rc);
552 free (url_string);
553
554 return NULL;
555}
556
557static char *
558test_split_path_ok (void)
559{
560 int rc;
561 char *path;
562 char *parts[10];
563
564 /* Simple path */
565 path = strdup ("/this/is/a/path");
566 rc = GNUNET_uri_split_path (path,
567 parts,
568 10);
569 mu_assert ("should be able to parse a regular path",
570 4 == rc);
571 mu_silent_assert ("first part should be 'this'",
572 0 == strcmp ("this", parts[0]));
573 mu_silent_assert ("second part should be 'is'",
574 0 == strcmp ("is", parts[1]));
575 mu_silent_assert ("third part should be 'a'",
576 0 == strcmp ("a", parts[2]));
577 mu_silent_assert ("fourth part should be 'path'",
578 0 == strcmp ("path", parts[3]));
579 free (path);
580
581 /* Relative path */
582 path = strdup ("this/is/a/path");
583 rc = GNUNET_uri_split_path (path,
584 parts,
585 10);
586 mu_assert ("should be able to parse a relative path",
587 4 == rc);
588 mu_silent_assert ("first part should be 'this'",
589 0 == strcmp ("this", parts[0]));
590 mu_silent_assert ("second part should be 'is'",
591 0 == strcmp ("is", parts[1]));
592 mu_silent_assert ("third part should be 'a'",
593 0 == strcmp ("a", parts[2]));
594 mu_silent_assert ("fourth part should be 'path'",
595 0 == strcmp ("path", parts[3]));
596 free (path);
597
598 /* Path with empty parts */
599 path = strdup ("//this//is/a/path/");
600 rc = GNUNET_uri_split_path (path,
601 parts,
602 10);
603 mu_assert ("should treat multiple slashes as one",
604 4 == rc);
605 mu_silent_assert ("first part should be 'this'",
606 0 == strcmp("this", parts[0]));
607 mu_silent_assert ("second part should be 'is'",
608 0 == strcmp("is", parts[1]));
609 mu_silent_assert ("third part should be 'a'",
610 0 == strcmp("a", parts[2]));
611 mu_silent_assert ("fourth part should be 'path'",
612 0 == strcmp("path", parts[3]));
613 free (path);
614
615 /* Just one level */
616 path = strdup("/one_level");
617 rc = GNUNET_uri_split_path(path, parts, 10);
618 mu_assert("should be able to parse a path with one level", 1 == rc);
619 mu_silent_assert("first part should be 'this'", 0 == strcmp("one_level", parts[0]));
620 free(path);
621
622 return NULL;
623}
624
625static char *
626test_parse_query_ok (void)
627{
628 int rc;
629 char *q;
630 struct GNUNET_UriParam params[10];
631
632 /* One param query */
633 q = strdup ("q=yes");
634 rc = GNUNET_uri_parse_query (q,
635 '&',
636 params,
637 10);
638 mu_assert ("single parameter with value",
639 1 == rc);
640 mu_silent_assert ("first param key should be 'q'",
641 0 == strcmp ("q", params[0].key));
642 mu_silent_assert ("first param val should be 'yes'",
643 0 == strcmp ("yes", params[0].val));
644 free (q);
645
646 /* One param query without value */
647 q = strdup ("q");
648 rc = GNUNET_uri_parse_query (q,
649 '&',
650 params,
651 10);
652 mu_assert ("single parameter without value",
653 1 == rc);
654 mu_silent_assert ("first param key should be 'q'",
655 0 == strcmp ("q", params[0].key));
656 mu_silent_assert ("first param val should be NULL",
657 NULL == params[0].val);
658 free (q);
659
660 /* Two param query */
661 q = strdup ("query=yes&a1=hello");
662 rc = GNUNET_uri_parse_query (q,
663 '&',
664 params,
665 10);
666 mu_assert ("multiple params with value",
667 2 == rc);
668 mu_silent_assert ("first param key should be 'query'",
669 0 == strcmp ("query", params[0].key));
670 mu_silent_assert ("first param val should be 'yes'",
671 0 == strcmp ("yes", params[0].val));
672 mu_silent_assert ("second param key should be 'a1'",
673 0 == strcmp ("a1", params[1].key));
674 mu_silent_assert ("second param val should be 'hello'",
675 0 == strcmp ("hello", params[1].val));
676 free (q);
677
678 /* Two param query, one without value */
679 q = strdup ("query=yes&forceHttps");
680 rc = GNUNET_uri_parse_query (q,
681 '&',
682 params,
683 10);
684 mu_assert ("multiple params one without value",
685 2 == rc);
686 mu_silent_assert ("first param key should be 'query'",
687 0 == strcmp ("query", params[0].key));
688 mu_silent_assert ("first param val should be 'yes'",
689 0 == strcmp ("yes", params[0].val));
690 mu_silent_assert ("second param key should be 'forceHttps'",
691 0 == strcmp ("forceHttps", params[1].key));
692 mu_silent_assert ("second param val should be NULL",
693 NULL == params[1].val);
694 free (q);
695
696 /* Three param query, all without value */
697 q = strdup ("query&forceHttps&log");
698 rc = GNUNET_uri_parse_query (q,
699 '&',
700 params,
701 10);
702 mu_assert ("multiple params all without value",
703 3 == rc);
704 mu_silent_assert ("first param key should be 'query'",
705 0 == strcmp ("query", params[0].key));
706 mu_silent_assert ("first param val should be NULL",
707 NULL == params[0].val);
708 mu_silent_assert ("second param key should be 'forceHttps'",
709 0 == strcmp ("forceHttps", params[1].key));
710 mu_silent_assert ("second param val should be NULL",
711 NULL == params[1].val);
712 mu_silent_assert ("third param key should be 'log'",
713 0 == strcmp ("log", params[2].key));
714 mu_silent_assert ("third param val should be NULL",
715 NULL == params[2].val);
716 free (q);
717
718 /* Param with empty value */
719 q = strdup ("param=&query=no");
720 rc = GNUNET_uri_parse_query (q,
721 '&',
722 params,
723 10);
724 mu_assert ("param with empty value",
725 2 == rc);
726 mu_silent_assert ("first param key should be 'param'",
727 0 == strcmp ("param", params[0].key));
728 mu_silent_assert ("first param val should be ''",
729 0 == strcmp ("", params[0].val));
730 mu_silent_assert ("second param key should be 'query'",
731 0 == strcmp ("query", params[1].key));
732 mu_silent_assert ("second param val should be 'no'",
733 0 == strcmp ("no", params[1].val));
734 free (q);
735
736 /* Double delimiter */
737 q = strdup ("param=jack&&query=no");
738 rc = GNUNET_uri_parse_query (q,
739 '&',
740 params,
741 10);
742 mu_assert ("double delimiter",
743 3 == rc);
744 mu_silent_assert ("first param key should be 'param'",
745 0 == strcmp ("param", params[0].key));
746 mu_silent_assert ("first param val should be 'jack'",
747 0 == strcmp ("jack", params[0].val));
748 mu_silent_assert ("second param key should be ''",
749 0 == strcmp ("", params[1].key));
750 mu_silent_assert ("second param val should be NULL",
751 NULL == params[1].val);
752 mu_silent_assert ("third param key should be 'query'",
753 0 == strcmp ("query", params[2].key));
754 mu_silent_assert ("third param val should be 'no'",
755 0 == strcmp ("no", params[2].val));
756 free (q);
757
758 /* Delimiter in beginning */
759 q = strdup ("&param=jack&query=no");
760 rc = GNUNET_uri_parse_query (q,
761 '&',
762 params,
763 10);
764 mu_assert ("delimiter in beginning",
765 3 == rc);
766 mu_silent_assert ("first param key should be ''",
767 0 == strcmp ("", params[0].key));
768 mu_silent_assert ("first param val should be NULL",
769 NULL == params[0].val);
770 mu_silent_assert ("second param key should be 'param'",
771 0 == strcmp ("param", params[1].key));
772 mu_silent_assert ("second param val should be 'jack'",
773 0 == strcmp ("jack", params[1].val));
774 mu_silent_assert ("third param key should be 'query'",
775 0 == strcmp ("query", params[2].key));
776 mu_silent_assert ("third param val should be 'no'",
777 0 == strcmp ("no", params[2].val));
778 free (q);
779
780 /* Delimiter at the end */
781 q = strdup ("param=jack&query=no&");
782 rc = GNUNET_uri_parse_query (q,
783 '&',
784 params,
785 10);
786 mu_assert ("delimiter at the end",
787 3 == rc);
788 mu_silent_assert ("first param key should be 'param'",
789 0 == strcmp ("param", params[0].key));
790 mu_silent_assert ("first param val should be 'jack'",
791 0 == strcmp ("jack", params[0].val));
792 mu_silent_assert ("second param key should be 'query'",
793 0 == strcmp ("query", params[1].key));
794 mu_silent_assert ("second param val should be 'no'",
795 0 == strcmp ("no", params[1].val));
796 mu_silent_assert ("third param key should be ''",
797 0 == strcmp ("", params[2].key));
798 mu_silent_assert ("third param val should be NULL",
799 NULL == params[2].val);
800 free (q);
801
802 return NULL;
803}
804
805static char *
806all_tests (void)
807{
808 mu_group ("GNUNET_uri_parse () with an HTTP URL");
809 mu_run_test (test_parse_http_url_ok);
810
811 mu_group ("GNUNET_uri_parse () with an relative URL");
812 mu_run_test (test_parse_http_rel_url_ok);
813
814 mu_group ("GNUNET_uri_parse () with faulty values");
815 mu_run_test (test_parse_url_fail);
816
817 mu_group ("GNUNET_uri_split_path ()");
818 mu_run_test (test_split_path_ok);
819
820 mu_group ("GNUNET_uri_parse_query ()");
821 mu_run_test (test_parse_query_ok);
822
823 return NULL;
824}
825
826int
827main (void)
828{
829 char *result;
830
831 result = all_tests ();
832 if (result != NULL) {
833 exit (EXIT_FAILURE);
834 }
835
836 exit (EXIT_SUCCESS);
837}
diff --git a/src/util/uri.c b/src/util/uri.c
new file mode 100644
index 000000000..87101d7e1
--- /dev/null
+++ b/src/util/uri.c
@@ -0,0 +1,344 @@
1/**
2 * Copyright (C) 2016,2017 Jack Engqvist Johansson
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include "gnunet_uri_lib.h"
26
27
28/**
29 * Parse a non null terminated string into an integer.
30 *
31 * str: the string containing the number.
32 * len: Number of characters to parse.
33 */
34static inline int
35natoi (const char *str,
36 size_t len)
37{
38 int i, r = 0;
39 for (i = 0; i < len; i++) {
40 r *= 10;
41 r += str[i] - '0';
42 }
43
44 return r;
45}
46
47
48/**
49 * Check if a URL is relative (no scheme and hostname).
50 *
51 * url: the string containing the URL to check.
52 *
53 * Returns 1 if relative, otherwise 0.
54 */
55static inline int
56is_relative (const char *url)
57{
58 return (*url == '/') ? 1 : 0;
59}
60
61
62/**
63 * Parse the scheme of a URL by inserting a null terminator after the scheme.
64 *
65 * str: the string containing the URL to parse. Will be modified.
66 *
67 * Returns a pointer to the hostname on success, otherwise NULL.
68 */
69static inline char *
70parse_scheme (char *str)
71{
72 char *s;
73
74 /* If not found or first in string, return error */
75 s = strchr (str, ':');
76 if (s == NULL || s == str) {
77 return NULL;
78 }
79
80 /* If not followed by two slashes, return error */
81 if (s[1] == '\0' || s[1] != '/' || s[2] == '\0' || s[2] != '/') {
82 return NULL;
83 }
84
85 *s = '\0'; // Replace ':' with NULL
86
87 return s + 3;
88}
89
90
91/**
92 * Find a character in a string, replace it with '\0' and return the next
93 * character in the string.
94 *
95 * str: the string to search in.
96 * find: the character to search for.
97 *
98 * Returns a pointer to the character after the one to search for. If not
99 * found, NULL is returned.
100 */
101static inline char *
102find_and_terminate (char *str,
103 char find)
104{
105 str = strchr(str, find);
106 if (NULL == str) {
107 return NULL;
108 }
109
110 *str = '\0';
111 return str + 1;
112}
113
114
115/* Yes, the following functions could be implemented as preprocessor macros
116 instead of inline functions, but I think that this approach will be more
117 clean in this case. */
118static inline char *
119find_fragment (char *str)
120{
121 return find_and_terminate (str, '#');
122}
123
124
125static inline char *
126find_query (char *str)
127{
128 return find_and_terminate (str, '?');
129}
130
131
132static inline char *
133find_path (char *str)
134{
135 return find_and_terminate (str, '/');
136}
137
138
139/**
140 * Parse a URL to a struct.
141 *
142 * The URL string should be in one of the following formats:
143 *
144 * Absolute URL:
145 * scheme ":" [ "//" ] [ username ":" password "@" ] host [ ":" port ] [ "/" ] [ path ] [ "?" query ] [ "#" fragment ]
146 *
147 * Relative URL:
148 * path [ "?" query ] [ "#" fragment ]
149 *
150 * The following parts will be parsed to the corresponding struct member.
151 *
152 * *url: a pointer to the struct where to store the parsed values.
153 * *url_str: a pointer to the url to be parsed (null terminated). The string
154 * will be modified.
155 *
156 * Returns 0 on success, otherwise -1.
157 */
158int
159GNUNET_uri_parse (struct GNUNET_Uri *url,
160 char *u)
161{
162 if (NULL == url || NULL == u) {
163 return -1;
164 }
165
166 memset(url, 0, sizeof (struct GNUNET_Uri));
167
168 /* (Fragment) */
169 url->fragment = find_fragment (u);
170
171 /* (Query) */
172 url->query = find_query (u);
173
174 /* Relative URL? Parse scheme and hostname */
175 if (!is_relative (u)) {
176 /* Scheme */
177 url->scheme = u;
178 u = parse_scheme (u);
179 if (u == NULL) {
180 return -1;
181 }
182
183 /* Host */
184 if ('\0' == *u) {
185 return -1;
186 }
187 url->host = u;
188
189 /* (Path) */
190 url->path = find_path (u);
191
192 /* (Credentials) */
193 u = strchr (url->host, '@');
194 if (NULL != u) {
195 /* Missing credentials? */
196 if (u == url->host) {
197 return -1;
198 }
199
200 url->username = url->host;
201 url->host = u + 1;
202 *u = '\0';
203
204 u = strchr (url->username, ':');
205 if (NULL == u) {
206 return -1;
207 }
208
209 url->password = u + 1;
210 *u = '\0';
211 }
212
213 /* Missing hostname? */
214 if ('\0' == *url->host) {
215 return -1;
216 }
217
218 /* (Port) */
219 u = strchr (url->host, ':');
220 if (NULL != u && (NULL == url->path || u < url->path)) {
221 *(u++) = '\0';
222 if ('\0' == *u) {
223 return -1;
224 }
225
226 if (url->path) {
227 url->port = natoi (u, url->path - u - 1);
228 } else {
229 url->port = atoi (u);
230 }
231 }
232
233 /* Missing hostname? */
234 if ('\0' == *url->host) {
235 return -1;
236 }
237 } else {
238 /* (Path) */
239 url->path = find_path (u);
240 }
241
242 return 0;
243}
244
245
246/**
247 * Split a path into several strings.
248 *
249 * No data is copied, the slashed are used as null terminators and then
250 * pointers to each path part will be stored in **parts. Double slashes will be
251 * treated as one.
252 *
253 * *path: the path to split. The string will be modified.
254 * **parts: a pointer to an array of (char *) where to store the result.
255 * max_parts: max number of parts to parse.
256 *
257 * Returns the number of parsed items. -1 on error.
258 */
259int
260GNUNET_uri_split_path (char *path,
261 char **parts,
262 int max_parts)
263{
264 int i = 0;
265
266 if (NULL == path || '\0' == *path) {
267 return -1;
268 }
269
270 do {
271 /* Forward to after slashes */
272 while (*path == '/') path++;
273
274 if ('\0' == *path) {
275 break;
276 }
277
278 parts[i++] = path;
279
280 path = strchr (path, '/');
281 if (NULL == path) {
282 break;
283 }
284
285 *(path++) = '\0';
286 } while (i < max_parts);
287
288 return i;
289}
290
291
292/**
293 * Parse a query string into a key/value struct.
294 *
295 * The query string should be a null terminated string of parameters separated by
296 * a delimiter. Each parameter are checked for the equal sign character. If it
297 * appears in the parameter, it will be used as a null terminator and the part
298 * that comes after it will be the value of the parameter.
299 *
300 * No data are copied, the equal sign and delimiters are used as null
301 * terminators and then pointers to each parameter key and value will be stored
302 * in the yuarel_param struct.
303 *
304 * *query: the query string to parse. The string will be modified.
305 * delimiter: the character that separates the key/value pairs from eachother.
306 * *params: an array of (struct yuarel_param) where to store the result.
307 * max_values: max number of parameters to parse.
308 *
309 * Returns the number of parsed items. -1 on error.
310 */
311int
312GNUNET_uri_parse_query (char *query,
313 char delimiter,
314 struct GNUNET_UriParam *params,
315 int max_params)
316{
317 int i = 0;
318
319 if (NULL == query || '\0' == *query) {
320 return -1;
321 }
322
323 params[i++].key = query;
324 while (i < max_params && NULL != (query = strchr (query, delimiter))) {
325 *query = '\0';
326 params[i].key = ++query;
327 params[i].val = NULL;
328
329 /* Go back and split previous param */
330 if (i > 0) {
331 if ((params[i - 1].val = strchr (params[i - 1].key, '=')) != NULL) {
332 *(params[i - 1].val)++ = '\0';
333 }
334 }
335 i++;
336 }
337
338 /* Go back and split last param */
339 if ((params[i - 1].val = strchr (params[i - 1].key, '=')) != NULL) {
340 *(params[i - 1].val)++ = '\0';
341 }
342
343 return i;
344}