diff options
author | t3sserakt <t3ss@posteo.de> | 2020-08-28 17:57:44 +0200 |
---|---|---|
committer | t3sserakt <t3ss@posteo.de> | 2020-08-28 17:57:53 +0200 |
commit | 2b552a5f5e85fab1c14af73735c0de61b46cc3dc (patch) | |
tree | 1ed739ddb116d77a7f2dfcc69c013f0eb9f731e7 | |
parent | 03f6a0233f72c2c4c3925f0d6f6f7a81987c6530 (diff) | |
parent | bbf9540c93da3c6b950920ee7eaae479c95403c5 (diff) | |
download | gnunet-2b552a5f5e85fab1c14af73735c0de61b46cc3dc.tar.gz gnunet-2b552a5f5e85fab1c14af73735c0de61b46cc3dc.zip |
Merge branch 'master' of ssh://gnunet.org/gnunet
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 | ||
5 | make | ||
@@ -1,3 +1,66 @@ | |||
1 | Wed, 12 Aug 2020 09:36:33 +0200 (99f820453) | ||
2 | fix: GNUNET_is_zero(ptr) should return enum GNUNET_GenericReturnValue. Fixes #6475. - Martin Schanzenbach | ||
3 | |||
4 | Tue, 11 Aug 2020 11:35:06 +0200 (286759692) | ||
5 | fix: mysql version detection - Martin Schanzenbach | ||
6 | |||
7 | Thu, 6 Aug 2020 08:45:40 +0200 (1d4f5263a) | ||
8 | reclaim: Refactoring and more standards compliance with respect to scopes - Martin Schanzenbach | ||
9 | |||
10 | Wed, 5 Aug 2020 11:35:05 +0200 (6e764f4ab) | ||
11 | reclaim: Make SPAs work with public clients. No longer encrypt code. - Martin Schanzenbach | ||
12 | |||
13 | Tue, 4 Aug 2020 21:08:22 +0200 (ade9b5e52) | ||
14 | reclaim: fix #6463 - Martin Schanzenbach | ||
15 | |||
16 | Tue, 4 Aug 2020 19:40:23 +0200 (815ded19f) | ||
17 | rest: fix #6462 - Martin Schanzenbach | ||
18 | |||
19 | Tue, 4 Aug 2020 10:09:45 +0200 (080519e98) | ||
20 | reclaim: do not store access token instead piggyback ticket - Martin Schanzenbach | ||
21 | |||
22 | Mon, 3 Aug 2020 19:37:23 +0200 (8c86c4472) | ||
23 | reclaim: support client credentials in POST body for token request - Martin Schanzenbach | ||
24 | |||
25 | Sat, 1 Aug 2020 16:22:38 +0200 (e44686f08) | ||
26 | fix: reclaim urlenc / revert accidental change - Martin Schanzenbach | ||
27 | |||
28 | Sat, 1 Aug 2020 16:07:08 +0200 (754d8c1b4) | ||
29 | util: add percent/url encoding - Martin Schanzenbach | ||
30 | |||
31 | Thu, 30 Jul 2020 16:12:22 +0530 (8d312646c) | ||
32 | fix SIGSEGV in GNUNET_buffer_write_data_encoded - Florian Dold | ||
33 | |||
34 | Thu, 30 Jul 2020 15:15:59 +0530 (d335baac8) | ||
35 | implement GNUNET_buffer_write_data_encoded - Florian Dold | ||
36 | |||
37 | Wed, 22 Jul 2020 21:47:42 +0200 (8703a0516) | ||
38 | ensure psql fails hard if there is an error in the SQL (fixes #6437) - Christian Grothoff | ||
39 | |||
40 | Sat, 18 Jul 2020 00:44:39 +0200 (7f4ddbcab) | ||
41 | merge flags into enum for GNUNET_DISK_pipe() API, fixing #6188 - Christian Grothoff | ||
42 | |||
43 | Fri, 17 Jul 2020 22:35:36 +0200 (28ab2c446) | ||
44 | avoid boolean flag in GNUNET_OS_start_process() API (fixes #6188) - Christian Grothoff | ||
45 | |||
46 | Fri, 17 Jul 2020 14:26:45 +0200 (0c9911d73) | ||
47 | TNG: Implemented 5530: add replay protection to TCP communicator. Added monotime value checks - t3sserakt | ||
48 | |||
49 | Thu, 16 Jul 2020 20:36:12 +0200 (bbe0a0501) | ||
50 | avoid boolean argument in GNUNET_CURL_job_add(), see #6188 - Christian Grothoff | ||
51 | |||
52 | Thu, 16 Jul 2020 17:40:14 +0200 (ee1fbffa1) | ||
53 | support context-wide client authentication - Christian Grothoff | ||
54 | |||
55 | Thu, 16 Jul 2020 17:24:30 +0200 (23820348b) | ||
56 | docs: fixed example for pinning a friends public key - rexxnor | ||
57 | |||
58 | Wed, 15 Jul 2020 17:21:39 +0200 (9bb2c1e31) | ||
59 | Load GNSRECORD plugins within GNUnet's context - Christian Grothoff | ||
60 | |||
61 | Fri, 3 Jul 2020 22:37:42 +0200 (0f2ac01f3) | ||
62 | Add function to return GNUnet's default configuration - Christian Grothoff | ||
63 | |||
1 | Thu, 9 Jul 2020 09:09:50 +0200 (5a0df5e18) | 64 | Thu, 9 Jul 2020 09:09:50 +0200 (5a0df5e18) |
2 | fix: raise ATS quotas to 10 MiB #6426 - Martin Schanzenbach | 65 | fix: raise ATS quotas to 10 MiB #6426 - Martin Schanzenbach |
3 | 66 | ||
@@ -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 | ||
106 | init_buildcommon_include() | 106 | init_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 | ||
111 | main() | 111 | main() |
diff --git a/configure.ac b/configure.ac index 39e7ffa7e..bd92bd0e9 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -21,7 +21,7 @@ | |||
21 | # | 21 | # |
22 | AC_PREREQ(2.61) | 22 | AC_PREREQ(2.61) |
23 | # Checks for programs. | 23 | # Checks for programs. |
24 | AC_INIT([gnunet], [0.13.1], [bug-gnunet@gnu.org]) | 24 | AC_INIT([gnunet], [0.13.2], [bug-gnunet@gnu.org]) |
25 | AC_CONFIG_AUX_DIR([build-aux]) | 25 | AC_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 | ||
1428 | AM_CONDITIONAL(HAVE_MYSQL, test x$mysql = xtrue) | 1444 | AM_CONDITIONAL(HAVE_MYSQL, test x$mysql = xtrue) |
@@ -1923,6 +1939,10 @@ src/scalarproduct/Makefile | |||
1923 | src/scalarproduct/scalarproduct.conf | 1939 | src/scalarproduct/scalarproduct.conf |
1924 | src/set/Makefile | 1940 | src/set/Makefile |
1925 | src/set/set.conf | 1941 | src/set/set.conf |
1942 | src/seti/Makefile | ||
1943 | src/seti/seti.conf | ||
1944 | src/setu/Makefile | ||
1945 | src/setu/setu.conf | ||
1926 | src/sq/Makefile | 1946 | src/sq/Makefile |
1927 | src/statistics/Makefile | 1947 | src/statistics/Makefile |
1928 | src/statistics/statistics.conf | 1948 | src/statistics/statistics.conf |
diff --git a/contrib/Makefile.inc b/contrib/Makefile.inc index 35c2d42a8..a563ef4a1 100644 --- a/contrib/Makefile.inc +++ b/contrib/Makefile.inc | |||
@@ -3,6 +3,12 @@ | |||
3 | # itself. | 3 | # itself. |
4 | 4 | ||
5 | BUILDCOMMON_SHLIB_FILES = \ | 5 | BUILDCOMMON_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 | ||
8 | BUILDCOMMON_CONF_FILES = \ | 14 | BUILDCOMMON_CONF_FILES = \ |
diff --git a/doc/handbook/chapters/developer.texi b/doc/handbook/chapters/developer.texi index 6d8ddd3c2..369e5327c 100644 --- a/doc/handbook/chapters/developer.texi +++ b/doc/handbook/chapters/developer.texi | |||
@@ -71,6 +71,8 @@ new chapters, sections or insightful comments. | |||
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 | 6540 | The SET subsystem is in process of being replaced by the SETU and | |
6541 | SETI subsystems, which provide basically the same functionality, | ||
6542 | just using two different subsystems. SETI and SETU should be used | ||
6543 | for new code. | ||
6539 | 6544 | ||
6540 | The SET service implements efficient set operations between two peers | 6545 | The SET service implements efficient set operations between two peers |
6541 | over a mesh tunnel. | 6546 | over a CADET tunnel. |
6542 | Currently, set union and set intersection are the only supported | 6547 | Currently, set union and set intersection are the only supported |
6543 | operations. Elements of a set consist of an @emph{element type} and | 6548 | operations. Elements of a set consist of an @emph{element type} and |
6544 | arbitrary binary @emph{data}. | 6549 | arbitrary binary @emph{data}. |
@@ -6907,6 +6912,513 @@ All Bloom filter operations use a salt to mingle keys before hashing them | |||
6907 | into buckets, such that future iterations have a fresh chance of | 6912 | into buckets, such that future iterations have a fresh chance of |
6908 | succeeding if they failed due to collisions before. | 6913 | succeeding 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 | |||
6926 | The SET service implements efficient set intersection between two peers | ||
6927 | over a CADET tunnel. | ||
6928 | Elements of a set consist of an @emph{element type} and | ||
6929 | arbitrary binary @emph{data}. | ||
6930 | The 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 | |||
6945 | Sets created by a local client can be modified (by adding additional elements) | ||
6946 | and reused for multiple operations. If elements are to be removed, a fresh | ||
6947 | set must be created by the client. | ||
6948 | |||
6949 | @node Set Intersection Modifications | ||
6950 | @subsection Set Intersection Modifications | ||
6951 | |||
6952 | Even when set operations are active, one can add elements | ||
6953 | to a set. | ||
6954 | However, these changes will only be visible to operations that have been | ||
6955 | created after the changes have taken place. That is, every set operation | ||
6956 | only sees a snapshot of the set from the time the operation was started. | ||
6957 | This mechanism is @emph{not} implemented by copying the whole set, but by | ||
6958 | attaching @emph{generation information} to each element and operation. | ||
6959 | |||
6960 | @node Set Intersection Operations | ||
6961 | @subsection Set Intersection Operations | ||
6962 | |||
6963 | Set operations can be started in two ways: Either by accepting an | ||
6964 | operation request from a remote peer, or by requesting a set operation | ||
6965 | from a remote peer. | ||
6966 | Set operations are uniquely identified by the involved @emph{peers}, an | ||
6967 | @emph{application id} and the @emph{operation type}. | ||
6968 | |||
6969 | The client is notified of incoming set operations by @emph{set listeners}. | ||
6970 | A set listener listens for incoming operations of a specific operation | ||
6971 | type and application id. | ||
6972 | Once notified of an incoming set request, the client can accept the set | ||
6973 | request (providing a local set for the operation) or reject it. | ||
6974 | |||
6975 | @node Intersection Result Elements | ||
6976 | @subsection Intersection Result Elements | ||
6977 | |||
6978 | The SET service has two @emph{result modes} that determine how an | ||
6979 | operation'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 | ||
6983 | intersection are returned to the client. | ||
6984 | @item @strong{Removed Elements.} Only elements that are in the local | ||
6985 | peer'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 | |||
7003 | New sets are created with @code{GNUNET_SETI_create}. Only the local peer's | ||
7004 | configuration (as each set has its own client connection) must be provided. | ||
7005 | The set exists until either the client calls @code{GNUNET_SET_destroy} or | ||
7006 | the client's connection to the service is disrupted. | ||
7007 | In the latter case, the client is notified by the return value of | ||
7008 | functions dealing with sets. This return value must always be checked. | ||
7009 | |||
7010 | Elements are added with @code{GNUNET_SET_add_element}. | ||
7011 | |||
7012 | @node Intersection Listeners | ||
7013 | @subsubsection Intersection Listeners | ||
7014 | |||
7015 | Listeners are created with @code{GNUNET_SET_listen}. Each time time a | ||
7016 | remote peer suggests a set operation with an application id and operation | ||
7017 | type matching a listener, the listener's callback is invoked. | ||
7018 | The client then must synchronously call either @code{GNUNET_SET_accept} | ||
7019 | or @code{GNUNET_SET_reject}. Note that the operation will not be started | ||
7020 | until the client calls @code{GNUNET_SET_commit} | ||
7021 | (see Section "Supplying a Set"). | ||
7022 | |||
7023 | @node Intersection Operations | ||
7024 | @subsubsection Intersection Operations | ||
7025 | |||
7026 | Operations to be initiated by the local peer are created with | ||
7027 | @code{GNUNET_SET_prepare}. Note that the operation will not be started | ||
7028 | until 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 | |||
7034 | To 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 | ||
7037 | set to operate on, thus they can not do any work yet. | ||
7038 | |||
7039 | The client must call @code{GNUNET_SET_commit} to specify a set to use for | ||
7040 | an operation. @code{GNUNET_SET_commit} may only be called once per set | ||
7041 | operation. | ||
7042 | |||
7043 | @node The Intersection Result Callback | ||
7044 | @subsubsection The Intersection Result Callback | ||
7045 | |||
7046 | Clients must specify both a result mode and a result callback with | ||
7047 | @code{GNUNET_SET_accept} and @code{GNUNET_SET_prepare}. The result | ||
7048 | callback with a status indicating either that an element was received, or | ||
7049 | the operation failed or succeeded. | ||
7050 | The interpretation of the received element depends on the result mode. | ||
7051 | The callback needs to know which result mode it is used in, as the | ||
7052 | arguments do not indicate if an element is part of the full result set, | ||
7053 | or 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 | |||
7069 | For each set of a client, there exists a client connection to the service. | ||
7070 | Sets are created by sending the @code{GNUNET_SERVICE_SETI_CREATE} message | ||
7071 | over a new client connection. Multiple operations for one set are | ||
7072 | multiplexed over one client connection, using a request id supplied by | ||
7073 | the client. | ||
7074 | |||
7075 | @node Listeners for Intersection | ||
7076 | @subsubsection Listeners for Intersection | ||
7077 | |||
7078 | Each listener also requires a seperate client connection. By sending the | ||
7079 | @code{GNUNET_SERVICE_SETI_LISTEN} message, the client notifies the service | ||
7080 | of the application id and operation type it is interested in. A client | ||
7081 | rejects an incoming request by sending @code{GNUNET_SERVICE_SETI_REJECT} | ||
7082 | on the listener's client connection. | ||
7083 | In contrast, when accepting an incoming request, a | ||
7084 | @code{GNUNET_SERVICE_SETI_ACCEPT} message must be sent over the@ set that | ||
7085 | is supplied for the set operation. | ||
7086 | |||
7087 | @node Initiating Intersection Operations | ||
7088 | @subsubsection Initiating Intersection Operations | ||
7089 | |||
7090 | Operations with remote peers are initiated by sending a | ||
7091 | @code{GNUNET_SERVICE_SETI_EVALUATE} message to the service. The@ client | ||
7092 | connection that this message is sent by determines the set to use. | ||
7093 | |||
7094 | @node Modifying Intersection Sets | ||
7095 | @subsubsection Modifying Intersection Sets | ||
7096 | |||
7097 | Sets 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 | |||
7108 | The service notifies the client of result elements and success/failure of | ||
7109 | a 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 | |||
7114 | The intersection protocol operates over CADET and starts with a | ||
7115 | GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST being sent by the peer | ||
7116 | initiating the operation to the peer listening for inbound requests. | ||
7117 | It includes the number of elements of the initiating peer, which is used | ||
7118 | to decide which side will send a Bloom filter first. | ||
7119 | |||
7120 | The listening peer checks if the operation type and application | ||
7121 | identifier are acceptable for its current state. | ||
7122 | If not, it responds with a GNUNET_MESSAGE_TYPE_SETI_RESULT and a status of | ||
7123 | GNUNET_SETI_STATUS_FAILURE (and terminates the CADET channel). | ||
7124 | |||
7125 | If the application accepts the request, the listener sends back a | ||
7126 | @code{GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO} if it has | ||
7127 | more elements in the set than the client. | ||
7128 | Otherwise, it immediately starts with the Bloom filter exchange. | ||
7129 | If the initiator receives a | ||
7130 | @code{GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO} response, | ||
7131 | it beings the Bloom filter exchange, unless the set size is indicated to | ||
7132 | be zero, in which case the intersection is considered finished after | ||
7133 | just 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 | |||
7144 | In this phase, each peer transmits a Bloom filter over the remaining | ||
7145 | keys of the local set to the other peer using a | ||
7146 | @code{GNUNET_MESSAGE_TYPE_SETI_P2P_BF} message. This | ||
7147 | message additionally includes the number of elements left in the sender's | ||
7148 | set, as well as the XOR over all of the keys in that set. | ||
7149 | |||
7150 | The number of bits 'k' set per element in the Bloom filter is calculated | ||
7151 | based on the relative size of the two sets. | ||
7152 | Furthermore, the size of the Bloom filter is calculated based on 'k' and | ||
7153 | the number of elements in the set to maximize the amount of data filtered | ||
7154 | per byte transmitted on the wire (while avoiding an excessively high | ||
7155 | number of iterations). | ||
7156 | |||
7157 | The receiver of the message removes all elements from its local set that | ||
7158 | do not pass the Bloom filter test. | ||
7159 | It then checks if the set size of the sender and the XOR over the keys | ||
7160 | match what is left of its own set. If they do, it sends a | ||
7161 | @code{GNUNET_MESSAGE_TYPE_SETI_P2P_DONE} back to indicate | ||
7162 | that the latest set is the final result. | ||
7163 | Otherwise, the receiver starts another Bloom filter exchange, except | ||
7164 | this time as the sender. | ||
7165 | |||
7166 | @node Intersection Salt | ||
7167 | @subsubsection Intersection Salt | ||
7168 | |||
7169 | Bloom filter operations are probabilistic: With some non-zero probability | ||
7170 | the test may incorrectly say an element is in the set, even though it is | ||
7171 | not. | ||
7172 | |||
7173 | To mitigate this problem, the intersection protocol iterates exchanging | ||
7174 | Bloom filters using a different random 32-bit salt in each iteration (the | ||
7175 | salt is also included in the message). | ||
7176 | With different salts, set operations may fail for different elements. | ||
7177 | Merging the results from the executions, the probability of failure drops | ||
7178 | to zero. | ||
7179 | |||
7180 | The iterations terminate once both peers have established that they have | ||
7181 | sets of the same size, and where the XOR over all keys computes the same | ||
7182 | 512-bit value (leaving a failure probability of 2-511). | ||
7183 | |||
7184 | |||
7185 | @cindex SETU Subsystem | ||
7186 | @node SETU Subsystem | ||
7187 | @section SETU Subsystem | ||
7188 | |||
7189 | The SETU service implements efficient set union operations between two peers | ||
7190 | over a CADET tunnel. Elements of a set consist of an @emph{element type} and | ||
7191 | arbitrary binary @emph{data}. The size of an element's data is limited to | ||
7192 | around 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 | |||
7207 | Sets created by a local client can be modified (by adding additional elements) | ||
7208 | and reused for multiple operations. If elements are to be removed, a fresh | ||
7209 | set must be created by the client. | ||
7210 | |||
7211 | @node Set Union Modifications | ||
7212 | @subsection Set Union Modifications | ||
7213 | |||
7214 | Even when set operations are active, one can add elements | ||
7215 | to a set. | ||
7216 | However, these changes will only be visible to operations that have been | ||
7217 | created after the changes have taken place. That is, every set operation | ||
7218 | only sees a snapshot of the set from the time the operation was started. | ||
7219 | This mechanism is @emph{not} implemented by copying the whole set, but by | ||
7220 | attaching @emph{generation information} to each element and operation. | ||
7221 | |||
7222 | @node Set Union Operations | ||
7223 | @subsection Set Union Operations | ||
7224 | |||
7225 | Set operations can be started in two ways: Either by accepting an | ||
7226 | operation request from a remote peer, or by requesting a set operation | ||
7227 | from a remote peer. | ||
7228 | Set operations are uniquely identified by the involved @emph{peers}, an | ||
7229 | @emph{application id} and the @emph{operation type}. | ||
7230 | |||
7231 | The client is notified of incoming set operations by @emph{set listeners}. | ||
7232 | A set listener listens for incoming operations of a specific operation | ||
7233 | type and application id. | ||
7234 | Once notified of an incoming set request, the client can accept the set | ||
7235 | request (providing a local set for the operation) or reject it. | ||
7236 | |||
7237 | @node Union Result Elements | ||
7238 | @subsection Union Result Elements | ||
7239 | |||
7240 | The SET service has three @emph{result modes} that determine how an | ||
7241 | operation's result set is delivered to the client: | ||
7242 | |||
7243 | @itemize @bullet | ||
7244 | @item @strong{Locally added Elements.} Elements that are in the union | ||
7245 | but not already in the local peer's set are returned. | ||
7246 | @item @strong{Remote added Elements.} Additionally, notify the client | ||
7247 | if the remote peer lacked some elements and thus also return to the | ||
7248 | local client those elements that we are sending to the remote peer to | ||
7249 | be added to its union. Obtaining these elements requires setting | ||
7250 | the @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 | |||
7268 | New sets are created with @code{GNUNET_SETU_create}. Only the local peer's | ||
7269 | configuration (as each set has its own client connection) must be provided. | ||
7270 | The set exists until either the client calls @code{GNUNET_SETU_destroy} or | ||
7271 | the client's connection to the service is disrupted. | ||
7272 | In the latter case, the client is notified by the return value of | ||
7273 | functions dealing with sets. This return value must always be checked. | ||
7274 | |||
7275 | Elements are added with @code{GNUNET_SETU_add_element}. | ||
7276 | |||
7277 | @node Union Listeners | ||
7278 | @subsubsection Union Listeners | ||
7279 | |||
7280 | Listeners are created with @code{GNUNET_SETU_listen}. Each time time a | ||
7281 | remote peer suggests a set operation with an application id and operation | ||
7282 | type matching a listener, the listener's callback is invoked. | ||
7283 | The client then must synchronously call either @code{GNUNET_SETU_accept} | ||
7284 | or @code{GNUNET_SETU_reject}. Note that the operation will not be started | ||
7285 | until the client calls @code{GNUNET_SETU_commit} | ||
7286 | (see Section "Supplying a Set"). | ||
7287 | |||
7288 | @node Union Operations | ||
7289 | @subsubsection Union Operations | ||
7290 | |||
7291 | Operations to be initiated by the local peer are created with | ||
7292 | @code{GNUNET_SETU_prepare}. Note that the operation will not be started | ||
7293 | until 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 | |||
7299 | To 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 | ||
7302 | set to operate on, thus they can not do any work yet. | ||
7303 | |||
7304 | The client must call @code{GNUNET_SETU_commit} to specify a set to use for | ||
7305 | an operation. @code{GNUNET_SETU_commit} may only be called once per set | ||
7306 | operation. | ||
7307 | |||
7308 | @node The Union Result Callback | ||
7309 | @subsubsection The Union Result Callback | ||
7310 | |||
7311 | Clients must specify both a result mode and a result callback with | ||
7312 | @code{GNUNET_SETU_accept} and @code{GNUNET_SETU_prepare}. The result | ||
7313 | callback with a status indicating either that an element was received, | ||
7314 | transmitted to the other peer (if this information was requested), or | ||
7315 | if 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 | |||
7331 | For each set of a client, there exists a client connection to the service. | ||
7332 | Sets are created by sending the @code{GNUNET_SERVICE_SETU_CREATE} message | ||
7333 | over a new client connection. Multiple operations for one set are | ||
7334 | multiplexed over one client connection, using a request id supplied by | ||
7335 | the client. | ||
7336 | |||
7337 | @node Listeners for Union | ||
7338 | @subsubsection Listeners for Union | ||
7339 | |||
7340 | Each listener also requires a seperate client connection. By sending the | ||
7341 | @code{GNUNET_SERVICE_SETU_LISTEN} message, the client notifies the service | ||
7342 | of the application id and operation type it is interested in. A client | ||
7343 | rejects an incoming request by sending @code{GNUNET_SERVICE_SETU_REJECT} | ||
7344 | on the listener's client connection. | ||
7345 | In contrast, when accepting an incoming request, a | ||
7346 | @code{GNUNET_SERVICE_SETU_ACCEPT} message must be sent over the@ set that | ||
7347 | is supplied for the set operation. | ||
7348 | |||
7349 | @node Initiating Union Operations | ||
7350 | @subsubsection Initiating Union Operations | ||
7351 | |||
7352 | |||
7353 | |||
7354 | Operations with remote peers are initiated by sending a | ||
7355 | @code{GNUNET_SERVICE_SETU_EVALUATE} message to the service. The@ client | ||
7356 | connection that this message is sent by determines the set to use. | ||
7357 | |||
7358 | @node Modifying Union Sets | ||
7359 | @subsubsection Modifying Union Sets | ||
7360 | |||
7361 | Sets 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 | |||
7372 | The service notifies the client of result elements and success/failure of | ||
7373 | a 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 | |||
7380 | The SET union protocol is based on Eppstein's efficient set reconciliation | ||
7381 | without prior context. You should read this paper first if you want to | ||
7382 | understand the protocol. | ||
7383 | |||
7384 | The union protocol operates over CADET and starts with a | ||
7385 | GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST being sent by the peer | ||
7386 | initiating the operation to the peer listening for inbound requests. | ||
7387 | It includes the number of elements of the initiating peer, which is | ||
7388 | currently not used. | ||
7389 | |||
7390 | The listening peer checks if the operation type and application | ||
7391 | identifier are acceptable for its current state. If not, it responds with | ||
7392 | a @code{GNUNET_MESSAGE_TYPE_SETU_RESULT} and a status of | ||
7393 | @code{GNUNET_SETU_STATUS_FAILURE} (and terminates the CADET channel). | ||
7394 | |||
7395 | If the application accepts the request, it sends back a strata estimator | ||
7396 | using a message of type GNUNET_MESSAGE_TYPE_SETU_P2P_SE. The | ||
7397 | initiator evaluates the strata estimator and initiates the exchange of | ||
7398 | invertible Bloom filters, sending a GNUNET_MESSAGE_TYPE_SETU_P2P_IBF. | ||
7399 | |||
7400 | During the IBF exchange, if the receiver cannot invert the Bloom filter or | ||
7401 | detects a cycle, it sends a larger IBF in response (up to a defined | ||
7402 | maximum limit; if that limit is reached, the operation fails). | ||
7403 | Elements decoded while processing the IBF are transmitted to the other | ||
7404 | peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS, or requested from the | ||
7405 | other peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS messages, | ||
7406 | depending on the sign observed during decoding of the IBF. | ||
7407 | Peers respond to a GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS message | ||
7408 | with the respective element in a GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS | ||
7409 | message. If the IBF fully decodes, the peer responds with a | ||
7410 | GNUNET_MESSAGE_TYPE_SETU_P2P_DONE message instead of another | ||
7411 | GNUNET_MESSAGE_TYPE_SETU_P2P_IBF. | ||
7412 | |||
7413 | All Bloom filter operations use a salt to mingle keys before hashing them | ||
7414 | into buckets, such that future iterations have a fresh chance of | ||
7415 | succeeding 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 | ||
1991 | The reclaimID Identity Provider (IdP) is a decentralized IdP service. | 1991 | The re:claimID Identity Provider (IdP) is a decentralized IdP service. |
1992 | It allows its users to manage and authorize third parties to access | 1992 | It allows its users to manage and authorize third parties to access |
1993 | their identity attributes such as email or shipping addresses. | 1993 | their identity attributes such as email or shipping addresses. |
1994 | 1994 | ||
1995 | It basically mimics the concepts of centralized IdPs, such as those | 1995 | It basically mimics the concepts of centralized IdPs, such as those |
1996 | offered by Google or Facebook. | 1996 | offered by Google or Facebook. |
1997 | Like other IdPs, reclaimID features an (optional) OpenID-Connect | 1997 | Like other IdPs, reclaimID features an (optional) OpenID Connect |
1998 | 1.0-compliant protocol layer that can be used for websites to | 1998 | 1.0-compliant protocol layer that can be used for websites to |
1999 | integrate reclaimID as an Identity Provider with little effort. | 1999 | integrate 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 | |||
2038 | If you want to allow a third party such as a website or friend to access to your attributes (or a subset thereof) execute: | 2038 | If 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 | ||
2044 | Where "PKEY" is the public key of the third party and "attribute1,attribute2,..." is a comma-separated list of attribute names, such as "email,name,...", that you want to share. | ||
2045 | |||
2046 | The command will return a "ticket" string. | 2044 | The command will return a "ticket" string. |
2047 | You must give this "ticket" to the requesting third party. | 2045 | You 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 | |||
2049 | The third party may retrieve the key in string format for use in the above | ||
2050 | call using "gnunet-identity": | ||
2051 | |||
2052 | @example | ||
2053 | $ RP_KEY=$(gnunet-identity -d grep "relyingparty" | awk '@{print $3@}') | ||
2054 | @end example | ||
2048 | 2055 | ||
2049 | The third party can then retrieve your shared identity attributes using: | 2056 | The 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 | ||
2055 | Where "friend" is the name for "user" that the requesting party is using. | 2062 | Where "relyingparty" is the name for the identity behind $RP_KEY that the |
2063 | requesting party is using. | ||
2056 | This will retrieve and list the shared identity attributes. | 2064 | This will retrieve and list the shared identity attributes. |
2057 | The above command will also work if the user is currently offline since the attributes are retrieved from GNS. | 2065 | The above command will also work if the user is currently offline since the attributes are retrieved from GNS. |
2058 | Further, the "ticket" can be re-used later to retrieve up-to-date attributes in case "friend" has changed the value(s). For instance, because his email address changed. | 2066 | Further, $TICKET can be re-used later to retrieve up-to-date attributes in case "friend" has changed the value(s). For instance, because his email address changed. |
2059 | 2067 | ||
2060 | To list all given authorizations (tickets) you can execute: | 2068 | To 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 | ||
2069 | If you want to revoke the access of a third party to your attributes you can execute: | 2076 | If 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 | ||
2075 | This will prevent the third party from accessing the attribute in the future. | 2082 | This will prevent the third party from accessing the attribute in the future. |
@@ -2080,30 +2087,26 @@ This behaviour is _exactly the same_ as with other IdPs. | |||
2080 | @node OpenID Connect | 2087 | @node OpenID Connect |
2081 | @subsection OpenID Connect | 2088 | @subsection OpenID Connect |
2082 | 2089 | ||
2083 | There is an OpenID Connect API for use with reclaimID. | 2090 | There is an @uref{OpenID Connect, https://openid.net/specs/openid-connect-core-1_0.html} API for use with re:claimID. |
2084 | However, its use is quite complicated to setup. | 2091 | However, its use is quite complicated to setup. |
2085 | As a proof-of-concept, you can look at https://gitlab.com/reclaimid. | ||
2086 | |||
2087 | In the PoC and by convention for reclaimID, the OpenID Connect Endpoints are | ||
2088 | found at: | ||
2089 | 2092 | ||
2090 | @example | 2093 | @example |
2091 | http://api.reclaim/openid/authorize | 2094 | https://api.reclaim/openid/authorize |
2092 | http://api.reclaim/openid/token | 2095 | http://localhost:7776/openid/token |
2093 | http://api.reclaim/openid/userinfo | 2096 | http://localhost:7776/openid/userinfo |
2094 | http://api.reclaim/openid/login | 2097 | http://localhost:7776/openid/login |
2095 | @end example | 2098 | @end example |
2096 | 2099 | ||
2097 | The token endpoint is protected using HTTP basic authentication. | 2100 | The token endpoint is protected using HTTP basic authentication. |
2098 | You can authenticate using any username and the password configured under: | 2101 | You 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 | ||
2104 | The authorize endpoint is protected using a Cookie which can be obtained through | 2107 | The authorize endpoint is protected using a Cookie which can be obtained through |
2105 | a request against the login endpoint. | 2108 | a request against the login endpoint. |
2106 | This flow is meant to be used in the context of the OpenID Connect authorization | 2109 | This functionality is meant to be used in the context of the OpenID Connect authorization |
2107 | flow to collect user consent interactively. | 2110 | flow to collect user consent interactively. |
2108 | Without a Cookie, the authorize endpoint redirects to a URI configured under: | 2111 | Without 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 | ||
2114 | Our PoC includes a user interface (https://gitlab.com/reclaimid) which | ||
2115 | integrates this process is an OpenID Connect compatible fashion. | ||
2116 | |||
2117 | The token endpoint is protected using OAuth2 and expects the grant | 2117 | The token endpoint is protected using OAuth2 and expects the grant |
2118 | which is retrieved from the authorization endpoint according to the standard. | 2118 | which is retrieved from the authorization endpoint according to the standard. |
2119 | 2119 | ||
2120 | The userinfo endpoint is protected using OAuth2 and expects a bearer access | 2120 | The userinfo endpoint is protected using OAuth2 and expects a bearer access |
2121 | token which is retrieved from a token request. | 2121 | token which is retrieved from a token request. |
2122 | 2122 | ||
2123 | In order to create and register a client you need to execute the following | 2123 | In order to make use of OpenID Connect flows as a user, you need to install |
2124 | steps: | 2124 | the 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 | |||
2131 | In order to create and register an OpenID Connect client as a relying party, | ||
2132 | you 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 | ||
2132 | The client_id will be the public key of the client. | 2140 | The "client_id" for use in OpenID Connect is the public key of the client as |
2133 | As a redirect URI, you may use any globally unique DNS or GNS URI. | 2141 | displayed using: |
2134 | The 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 | |||
2146 | The RECLAIM_OIDC_REDIRECT record contains your website redirect URI. | ||
2147 | You may use any globally unique DNS or GNS URI. | ||
2148 | The RECLAIM_OIDC_CLIENT record represents the client description which whill | ||
2149 | be displayed to users in an authorization request. | ||
2135 | 2150 | ||
2136 | Any website or relying party must use the endpoint | 2151 | Any website or relying party must use the authorization endpoint |
2137 | https://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. | |||
2146 | This will direct the user's browser onto his local reclaimID instance. | 2161 | This will direct the user's browser onto his local reclaimID instance. |
2147 | After giving consent, you will be provided with the OpenID Connect authorization | 2162 | After giving consent, you will be provided with the OpenID Connect authorization |
2148 | code according to the specifications at your provided redirect URI. | 2163 | code according to the specifications at your provided redirect URI. |
2149 | The example code for the PoC website can be found at https://gitlab.com/reclaimid/demo. | 2164 | |
2165 | The ID Tokens issues by the token endpoints are signed using HS512 with the | ||
2166 | shared secret configured under: | ||
2167 | |||
2168 | @example | ||
2169 | $ gnunet-config -s reclaim-rest-plugin -o JWT_SECRET | ||
2170 | @end example | ||
2171 | |||
2172 | The authorization code flow optionally supports @uref{https://tools.ietf.org/html/rfc7636, Proof Key for Code Exchange}. | ||
2173 | If PKCE is used, the client does not need to authenticate against the token | ||
2174 | endpoint. | ||
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 | |||
272 | src/reclaim/json_reclaim.c | 272 | src/reclaim/json_reclaim.c |
273 | src/reclaim/oidc_helper.c | 273 | src/reclaim/oidc_helper.c |
274 | src/reclaim/plugin_gnsrecord_reclaim.c | 274 | src/reclaim/plugin_gnsrecord_reclaim.c |
275 | src/reclaim/plugin_reclaim_attestation_jwt.c | 275 | src/reclaim/plugin_reclaim_credential_jwt.c |
276 | src/reclaim/plugin_reclaim_attribute_basic.c | 276 | src/reclaim/plugin_reclaim_attribute_basic.c |
277 | src/reclaim/plugin_rest_openid_connect.c | 277 | src/reclaim/plugin_rest_openid_connect.c |
278 | src/reclaim/plugin_rest_reclaim.c | 278 | src/reclaim/plugin_rest_reclaim.c |
279 | src/reclaim/reclaim_api.c | 279 | src/reclaim/reclaim_api.c |
280 | src/reclaim/reclaim_attestation.c | 280 | src/reclaim/reclaim_credential.c |
281 | src/reclaim/reclaim_attribute.c | 281 | src/reclaim/reclaim_attribute.c |
282 | src/regex/gnunet-daemon-regexprofiler.c | 282 | src/regex/gnunet-daemon-regexprofiler.c |
283 | src/regex/gnunet-regex-profiler.c | 283 | src/regex/gnunet-regex-profiler.c |
@@ -333,6 +333,19 @@ src/set/ibf.c | |||
333 | src/set/ibf_sim.c | 333 | src/set/ibf_sim.c |
334 | src/set/plugin_block_set_test.c | 334 | src/set/plugin_block_set_test.c |
335 | src/set/set_api.c | 335 | src/set/set_api.c |
336 | src/seti/gnunet-service-set_intersection.c | ||
337 | src/seti/gnunet-service-seti.c | ||
338 | src/seti/gnunet-seti-profiler.c | ||
339 | src/seti/plugin_block_seti_test.c | ||
340 | src/seti/setu_api.c | ||
341 | src/setu/gnunet-service-setu.c | ||
342 | src/setu/gnunet-service-setu_strata_estimator.c | ||
343 | src/setu/gnunet-setu-ibf-profiler.c | ||
344 | src/setu/gnunet-setu-profiler.c | ||
345 | src/setu/ibf.c | ||
346 | src/setu/ibf_sim.c | ||
347 | src/setu/plugin_block_setu_test.c | ||
348 | src/setu/setu_api.c | ||
336 | src/sq/sq.c | 349 | src/sq/sq.c |
337 | src/sq/sq_exec.c | 350 | src/sq/sq_exec.c |
338 | src/sq/sq_prepare.c | 351 | src/sq/sq_prepare.c |
diff --git a/src/Makefile.am b/src/Makefile.am index 446b1aa2a..234a63389 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -89,6 +89,8 @@ SUBDIRS = \ | |||
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 | */ | ||
480 | void | ||
481 | GNUNET_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 | |||
81 | struct RequestHandle | 81 | struct 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 | */ | ||
152 | static struct RequestHandle *requests_head; | ||
153 | |||
154 | /** | ||
155 | * DLL | ||
156 | */ | ||
157 | static 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 * | |||
437 | libgnunet_plugin_rest_gns_done (void *cls) | 459 | libgnunet_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 | |||
3 | test_gnsrecord_serialization | 3 | test_gnsrecord_serialization |
4 | zonefiles | 4 | zonefiles |
5 | perf_gnsrecord_crypto | 5 | perf_gnsrecord_crypto |
6 | gnunet-gnsrecord-tvg | ||
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 6859396d6..d86d29e36 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c | |||
@@ -191,6 +191,16 @@ struct EgoEntry | |||
191 | struct RequestHandle | 191 | struct 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 | */ | ||
267 | static struct RequestHandle *requests_head; | ||
268 | |||
269 | /** | ||
270 | * DLL | ||
271 | */ | ||
272 | static 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 | */ |
1178 | int | 1178 | enum GNUNET_GenericReturnValue |
1179 | GNUNET_is_zero_ (const void *a, | 1179 | GNUNET_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 | */ | ||
674 | struct 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 | */ |
678 | void | 688 | void |
679 | GNUNET_CRYPTO_pow_hash (const char *salt, | 689 | GNUNET_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 | */ | ||
352 | void | ||
353 | GNUNET_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 | ||
42 | enum 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 | /** | 54 | enum 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 | ||
76 | GNUNET_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 | ||
86 | GNUNET_NETWORK_STRUCT_END | ||
87 | |||
77 | static const struct GNUNET_RECLAIM_Identifier GNUNET_RECLAIM_ID_ZERO; | 88 | static 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 | */ |
143 | struct GNUNET_RECLAIM_Attestation | 155 | struct 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 | */ | ||
195 | struct 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 | */ | ||
261 | struct 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 | |||
275 | struct 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 | */ |
219 | struct GNUNET_RECLAIM_AttestationList | 298 | struct 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 | ||
233 | struct GNUNET_RECLAIM_AttestationListEntry | 312 | struct 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 | */ |
263 | struct GNUNET_RECLAIM_Attribute * | 343 | struct GNUNET_RECLAIM_Attribute * |
264 | GNUNET_RECLAIM_attribute_new (const char *attr_name, | 344 | GNUNET_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 | |||
304 | GNUNET_RECLAIM_attribute_list_add ( | 384 | GNUNET_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 | */ |
367 | struct GNUNET_RECLAIM_Attribute * | 448 | ssize_t |
368 | GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size); | 449 | GNUNET_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 | */ |
436 | size_t | 518 | size_t |
437 | GNUNET_RECLAIM_attestation_list_serialize_get_size ( | 519 | GNUNET_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 | */ |
446 | void | 528 | void |
447 | GNUNET_RECLAIM_attestation_list_destroy ( | 529 | GNUNET_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 | */ |
459 | void | 541 | void |
460 | GNUNET_RECLAIM_attestation_list_add ( | 542 | GNUNET_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 | */ |
475 | size_t | 557 | size_t |
476 | GNUNET_RECLAIM_attestation_list_serialize ( | 558 | GNUNET_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 | */ |
488 | struct GNUNET_RECLAIM_AttestationList * | 570 | struct GNUNET_RECLAIM_CredentialList * |
489 | GNUNET_RECLAIM_attestation_list_deserialize (const char *data, | 571 | GNUNET_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 | */ |
497 | size_t | 579 | size_t |
498 | GNUNET_RECLAIM_attestation_serialize_get_size ( | 580 | GNUNET_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 | */ |
509 | size_t | 591 | size_t |
510 | GNUNET_RECLAIM_attestation_serialize ( | 592 | GNUNET_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 | */ |
523 | struct GNUNET_RECLAIM_Attestation * | 605 | struct GNUNET_RECLAIM_Credential * |
524 | GNUNET_RECLAIM_attestation_deserialize (const char *data, size_t data_size); | 606 | GNUNET_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 | */ |
536 | struct GNUNET_RECLAIM_Attestation * | 618 | struct GNUNET_RECLAIM_Credential * |
537 | GNUNET_RECLAIM_attestation_new (const char *name, | 619 | GNUNET_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 | */ |
550 | char * | 632 | char * |
551 | GNUNET_RECLAIM_attestation_value_to_string (uint32_t type, | 633 | GNUNET_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 | */ |
565 | int | 647 | int |
566 | GNUNET_RECLAIM_attestation_string_to_value (uint32_t type, | 648 | GNUNET_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 | */ |
577 | const char * | 659 | const char * |
578 | GNUNET_RECLAIM_attestation_number_to_typename (uint32_t type); | 660 | GNUNET_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 | */ |
586 | uint32_t | 668 | uint32_t |
587 | GNUNET_RECLAIM_attestation_typename_to_number (const char *typename); | 669 | GNUNET_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 | */ |
595 | struct GNUNET_RECLAIM_AttributeList* | 677 | struct GNUNET_RECLAIM_AttributeList* |
596 | GNUNET_RECLAIM_attestation_get_attributes (const struct | 678 | GNUNET_RECLAIM_credential_get_attributes (const struct |
597 | GNUNET_RECLAIM_Attestation *attest); | 679 | GNUNET_RECLAIM_Credential *cred); |
680 | |||
681 | char* | ||
682 | GNUNET_RECLAIM_credential_get_issuer (const struct | ||
683 | GNUNET_RECLAIM_Credential *cred); | ||
684 | |||
685 | int | ||
686 | GNUNET_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 | */ | ||
696 | size_t | ||
697 | GNUNET_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 | */ | ||
706 | void | ||
707 | GNUNET_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 | */ | ||
718 | size_t | ||
719 | GNUNET_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 | */ | ||
731 | struct GNUNET_RECLAIM_PresentationList * | ||
732 | GNUNET_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 | */ | ||
740 | size_t | ||
741 | GNUNET_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 | */ | ||
752 | size_t | ||
753 | GNUNET_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 | */ | ||
766 | struct GNUNET_RECLAIM_Presentation * | ||
767 | GNUNET_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 | */ | ||
778 | char * | ||
779 | GNUNET_RECLAIM_presentation_value_to_string (uint32_t type, | ||
780 | const void *data, | ||
781 | size_t data_size); | ||
782 | |||
783 | struct GNUNET_RECLAIM_Presentation * | ||
784 | GNUNET_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 | */ | ||
798 | int | ||
799 | GNUNET_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 | */ | ||
811 | const char * | ||
812 | GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type); | ||
813 | |||
814 | struct GNUNET_RECLAIM_AttributeList* | ||
815 | GNUNET_RECLAIM_presentation_get_attributes (const struct | ||
816 | GNUNET_RECLAIM_Presentation *cred); | ||
598 | 817 | ||
599 | char* | 818 | char* |
600 | GNUNET_RECLAIM_attestation_get_issuer (const struct | 819 | GNUNET_RECLAIM_presentation_get_issuer (const struct |
601 | GNUNET_RECLAIM_Attestation *attest); | 820 | GNUNET_RECLAIM_Presentation *cred); |
602 | 821 | ||
603 | int | 822 | int |
604 | GNUNET_RECLAIM_attestation_get_expiration (const struct | 823 | GNUNET_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 | */ | ||
841 | int | ||
842 | GNUNET_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 | */ |
116 | typedef char *(*GNUNET_RECLAIM_AttestationValueToStringFunction) ( | 116 | typedef 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 | */ |
135 | typedef int (*GNUNET_RECLAIM_AttestationStringToValueFunction) ( | 135 | typedef 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 | */ |
151 | typedef uint32_t (*GNUNET_RECLAIM_AttestationTypenameToNumberFunction) ( | 151 | typedef 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 | */ |
164 | typedef const char *(*GNUNET_RECLAIM_AttestationNumberToTypenameFunction) ( | 164 | typedef 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 | */ |
175 | typedef struct | 175 | typedef struct |
176 | GNUNET_RECLAIM_AttributeList *(* | 176 | GNUNET_RECLAIM_AttributeList *(* |
177 | GNUNET_RECLAIM_AttestationGetAttributesFunction) ( | 177 | GNUNET_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 | */ |
188 | typedef char *(*GNUNET_RECLAIM_AttestationGetIssuerFunction) ( | 188 | typedef 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 | */ |
200 | typedef int (*GNUNET_RECLAIM_AttestationGetExpirationFunction) ( | 200 | typedef 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 | */ | ||
215 | typedef 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 | */ | ||
234 | typedef 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 | */ | ||
250 | typedef 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 | */ | ||
263 | typedef 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 | */ | ||
274 | typedef struct | ||
275 | GNUNET_RECLAIM_AttributeList *(* | ||
276 | GNUNET_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 | */ | ||
287 | typedef 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 | */ | ||
299 | typedef int (*GNUNET_RECLAIM_PresentationGetExpirationFunction) ( | ||
300 | void *cls, | ||
301 | const struct GNUNET_RECLAIM_Presentation *cred, | ||
302 | struct GNUNET_TIME_Absolute *expiration); | ||
303 | |||
304 | typedef 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 | */ |
243 | struct GNUNET_RECLAIM_AttestationPluginFunctions | 347 | struct 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 | */ |
94 | typedef void (*GNUNET_RECLAIM_TicketCallback) ( | 94 | typedef 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 | */ | ||
106 | typedef 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 | */ |
118 | typedef void (*GNUNET_RECLAIM_AttributeResult) ( | 131 | typedef 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 | */ |
130 | typedef void (*GNUNET_RECLAIM_AttributeTicketResult) ( | 143 | typedef 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 | */ |
144 | typedef void (*GNUNET_RECLAIM_AttestationResult) ( | 157 | typedef 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 | */ |
192 | struct GNUNET_RECLAIM_Operation * | 205 | struct GNUNET_RECLAIM_Operation * |
193 | GNUNET_RECLAIM_attestation_store ( | 206 | GNUNET_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 | */ |
231 | struct GNUNET_RECLAIM_Operation * | 244 | struct GNUNET_RECLAIM_Operation * |
232 | GNUNET_RECLAIM_attestation_delete ( | 245 | GNUNET_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 | */ |
319 | struct GNUNET_RECLAIM_AttestationIterator * | 332 | struct GNUNET_RECLAIM_CredentialIterator * |
320 | GNUNET_RECLAIM_get_attestations_start ( | 333 | GNUNET_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 | */ |
337 | void | 350 | void |
338 | GNUNET_RECLAIM_get_attestations_next (struct | 351 | GNUNET_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 | */ |
349 | void | 362 | void |
350 | GNUNET_RECLAIM_get_attestations_stop (struct | 363 | GNUNET_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 | ||
37 | extern "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 | */ | ||
57 | struct GNUNET_SETI_Handle; | ||
58 | |||
59 | /** | ||
60 | * Opaque handle to a set operation request from another peer. | ||
61 | */ | ||
62 | struct GNUNET_SETI_Request; | ||
63 | |||
64 | /** | ||
65 | * Opaque handle to a listen operation. | ||
66 | */ | ||
67 | struct GNUNET_SETI_ListenHandle; | ||
68 | |||
69 | /** | ||
70 | * Opaque handle to a set operation. | ||
71 | */ | ||
72 | struct GNUNET_SETI_OperationHandle; | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Status for the result callback | ||
77 | */ | ||
78 | enum 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 | */ | ||
109 | struct 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 | */ | ||
133 | enum 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 | */ | ||
152 | struct 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 | */ | ||
178 | typedef 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 | */ | ||
200 | typedef 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 | */ | ||
214 | struct GNUNET_SETI_Handle * | ||
215 | GNUNET_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 | */ | ||
228 | int | ||
229 | GNUNET_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 | */ | ||
241 | void | ||
242 | GNUNET_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 | */ | ||
258 | struct GNUNET_SETI_OperationHandle * | ||
259 | GNUNET_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 | */ | ||
280 | struct GNUNET_SETI_ListenHandle * | ||
281 | GNUNET_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 | */ | ||
295 | void | ||
296 | GNUNET_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 | */ | ||
312 | struct GNUNET_SETI_OperationHandle * | ||
313 | GNUNET_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 | */ | ||
332 | int | ||
333 | GNUNET_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 | */ | ||
344 | void | ||
345 | GNUNET_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 | */ | ||
355 | void | ||
356 | GNUNET_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 | ||
37 | extern "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 | */ | ||
57 | struct GNUNET_SETU_Handle; | ||
58 | |||
59 | /** | ||
60 | * Opaque handle to a set operation request from another peer. | ||
61 | */ | ||
62 | struct GNUNET_SETU_Request; | ||
63 | |||
64 | /** | ||
65 | * Opaque handle to a listen operation. | ||
66 | */ | ||
67 | struct GNUNET_SETU_ListenHandle; | ||
68 | |||
69 | /** | ||
70 | * Opaque handle to a set operation. | ||
71 | */ | ||
72 | struct GNUNET_SETU_OperationHandle; | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Status for the result callback | ||
77 | */ | ||
78 | enum 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 | */ | ||
110 | struct 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 | */ | ||
134 | enum 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 | */ | ||
173 | struct 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 | */ | ||
199 | typedef 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 | */ | ||
221 | typedef 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 | */ | ||
235 | struct GNUNET_SETU_Handle * | ||
236 | GNUNET_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 | */ | ||
249 | int | ||
250 | GNUNET_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 | */ | ||
262 | void | ||
263 | GNUNET_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 | */ | ||
279 | struct GNUNET_SETU_OperationHandle * | ||
280 | GNUNET_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 | */ | ||
301 | struct GNUNET_SETU_ListenHandle * | ||
302 | GNUNET_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 | */ | ||
316 | void | ||
317 | GNUNET_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 | */ | ||
333 | struct GNUNET_SETU_OperationHandle * | ||
334 | GNUNET_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 | */ | ||
353 | int | ||
354 | GNUNET_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 | */ | ||
365 | void | ||
366 | GNUNET_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 | */ | ||
376 | void | ||
377 | GNUNET_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 | */ | ||
34 | struct 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. */ | ||
47 | struct 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 | */ | ||
72 | int | ||
73 | GNUNET_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 | */ | ||
90 | int | ||
91 | GNUNET_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 | */ | ||
115 | int | ||
116 | GNUNET_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 | |||
161 | struct RequestHandle | 161 | struct 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 | */ | ||
273 | static struct RequestHandle *requests_head; | ||
274 | |||
275 | /** | ||
276 | * DLL | ||
277 | */ | ||
278 | static 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 | */ | ||
119 | static 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; | |||
180 | struct RequestHandle | 180 | struct 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 | */ | ||
267 | static struct RequestHandle *requests_head; | ||
268 | |||
269 | /** | ||
270 | * DLL | ||
271 | */ | ||
272 | static 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 | ||
16 | ATTESTATION_PLUGIN = \ | 16 | CREDENTIAL_PLUGIN = \ |
17 | libgnunet_plugin_reclaim_attestation_jwt.la | 17 | libgnunet_plugin_reclaim_credential_jwt.la |
18 | 18 | ||
19 | EXTRA_DIST = \ | 19 | EXTRA_DIST = \ |
20 | reclaim.conf \ | 20 | reclaim.conf \ |
@@ -34,7 +34,7 @@ lib_LTLIBRARIES = \ | |||
34 | plugin_LTLIBRARIES = \ | 34 | plugin_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 | ||
40 | bin_PROGRAMS = \ | 40 | bin_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 |
120 | libgnunetreclaim_la_LIBADD = \ | 120 | libgnunetreclaim_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 = \ | |||
133 | libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \ | 133 | libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \ |
134 | $(GN_PLUGIN_LDFLAGS) | 134 | $(GN_PLUGIN_LDFLAGS) |
135 | 135 | ||
136 | libgnunet_plugin_reclaim_attestation_jwt_la_SOURCES = \ | 136 | libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \ |
137 | plugin_reclaim_attestation_jwt.c | 137 | plugin_reclaim_credential_jwt.c |
138 | libgnunet_plugin_reclaim_attestation_jwt_la_LIBADD = \ | 138 | libgnunet_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) |
143 | libgnunet_plugin_reclaim_attestation_jwt_la_LDFLAGS = \ | 143 | libgnunet_plugin_reclaim_credential_jwt_la_LDFLAGS = \ |
144 | $(GN_PLUGIN_LDFLAGS) | 144 | $(GN_PLUGIN_LDFLAGS) |
145 | 145 | ||
146 | gnunet_reclaim_SOURCES = \ | 146 | gnunet_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 | ||
155 | test_reclaim_attribute_SOURCES = \ | ||
156 | test_reclaim_attribute.c | ||
157 | test_reclaim_attribute_LDADD = \ | ||
158 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
159 | libgnunetreclaim.la \ | ||
160 | $(GN_LIBINTL) | ||
161 | |||
155 | check_SCRIPTS = \ | 162 | check_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 | |
167 | check_PROGRAMS = \ | ||
168 | test_reclaim_attribute | ||
160 | 169 | ||
161 | if ENABLE_TEST_RUN | 170 | if 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; | |||
43 | static int list; | 43 | static int list; |
44 | 44 | ||
45 | /** | 45 | /** |
46 | * List attestations flag | 46 | * List credentials flag |
47 | */ | 47 | */ |
48 | static int list_attestations; | 48 | static int list_credentials; |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * Attestation ID string | 51 | * Credential ID string |
52 | */ | 52 | */ |
53 | static char *attestation_id; | 53 | static char *credential_id; |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Attestation ID | 56 | * Credential ID |
57 | */ | 57 | */ |
58 | static struct GNUNET_RECLAIM_Identifier attestation; | 58 | static struct GNUNET_RECLAIM_Identifier credential; |
59 | 59 | ||
60 | /** | 60 | /** |
61 | * Attestation name | 61 | * Credential name |
62 | */ | 62 | */ |
63 | static char *attestation_name; | 63 | static char *credential_name; |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * Attestation exists | 66 | * Credential type |
67 | */ | 67 | */ |
68 | static int attestation_exists; | 68 | static char *credential_type; |
69 | |||
70 | /** | ||
71 | * Credential exists | ||
72 | */ | ||
73 | static int credential_exists; | ||
69 | 74 | ||
70 | /** | 75 | /** |
71 | * Relying party | 76 | * Relying party |
@@ -133,9 +138,9 @@ static struct GNUNET_RECLAIM_Operation *reclaim_op; | |||
133 | static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator; | 138 | static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator; |
134 | 139 | ||
135 | /** | 140 | /** |
136 | * Attestation iterator | 141 | * Credential iterator |
137 | */ | 142 | */ |
138 | static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator; | 143 | static 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 | */ |
144 | static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator; | 149 | static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator; |
145 | 150 | ||
146 | /** | ||
147 | * Master ABE key | ||
148 | */ | ||
149 | static 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 | ||
228 | static void | 229 | static void |
229 | ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | 230 | ticket_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 | |||
260 | process_attrs (void *cls, | 263 | process_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 | |||
362 | iter_error (void *cls) | 363 | iter_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 | ||
610 | static void | 612 | static void |
611 | attest_iter_finished (void *cls) | 613 | cred_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 | ||
650 | static void | 654 | static void |
651 | attest_iter_cb (void *cls, | 655 | cred_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 | |||
646 | send_ticket_result (const struct IdpClient *client, | 646 | send_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 | */ |
675 | static void | 690 | static void |
676 | issue_ticket_result_cb (void *cls, | 691 | issue_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 | |||
842 | consume_result_cb (void *cls, | 864 | consume_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 | */ |
1078 | static void | 1101 | static void |
1079 | attest_store_cont (void *cls, int32_t success, const char *emsg) | 1102 | cred_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 | */ |
1114 | static void | 1137 | static void |
1115 | attest_error (void *cls) | 1138 | cred_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 | */ |
1135 | static void | 1158 | static void |
1136 | attest_add_cb (void *cls, | 1159 | cred_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 | */ |
1174 | static void | 1198 | static void |
1175 | attest_store_task (void *cls) | 1199 | cred_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 | */ |
1205 | static int | 1228 | static int |
1206 | check_attestation_store_message (void *cls, | 1229 | check_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 | */ |
1227 | static void | 1250 | static void |
1228 | handle_attestation_store_message (void *cls, | 1251 | handle_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 | */ |
1580 | static void | 1604 | static void |
1581 | attest_delete_cont (void *cls, int32_t success, const char *emsg) | 1605 | cred_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 | */ |
1606 | static int | 1630 | static int |
1607 | check_attestation_delete_message (void *cls, | 1631 | check_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 | */ |
1628 | static void | 1652 | static void |
1629 | handle_attestation_delete_message (void *cls, | 1653 | handle_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 | */ |
1857 | static void | 1881 | static void |
1858 | attest_iter_finished (void *cls) | 1882 | cred_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 | */ |
1881 | static void | 1905 | static void |
1882 | attest_iter_error (void *cls) | 1906 | cred_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 | */ |
1900 | static void | 1924 | static void |
1901 | attest_iter_cb (void *cls, | 1925 | cred_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 | */ |
1941 | static void | 1965 | static void |
1942 | handle_attestation_iteration_start (void *cls, | 1966 | handle_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 | */ |
1976 | static void | 2000 | static void |
1977 | handle_attestation_iteration_stop (void *cls, | 2001 | handle_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 | */ |
2011 | static void | 2035 | static void |
2012 | handle_attestation_iteration_next (void *cls, | 2036 | handle_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 | |||
1284 | issue_ticket (struct TicketIssueHandle *ih) | 1293 | issue_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) ( | |||
120 | typedef void (*RECLAIM_TICKETS_TicketResult) ( | 121 | typedef 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 | */ |
144 | struct GNUNET_JSON_Specification | 144 | struct GNUNET_JSON_Specification |
145 | GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_Attribute **attr) | 145 | GNUNET_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 | */ |
289 | static int | 289 | static int |
290 | parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) | 290 | parse_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 | */ |
358 | static void | 358 | static void |
359 | clean_attest (void *cls, struct GNUNET_JSON_Specification *spec) | 359 | clean_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 | */ |
378 | struct GNUNET_JSON_Specification | 378 | struct GNUNET_JSON_Specification |
379 | GNUNET_RECLAIM_JSON_spec_claim_attest (struct | 379 | GNUNET_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 | */ |
38 | struct GNUNET_JSON_Specification | 38 | struct GNUNET_JSON_Specification |
39 | GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_Attribute **attr); | 39 | GNUNET_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 | |||
48 | GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket); | 48 | GNUNET_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 | */ |
56 | struct GNUNET_JSON_Specification | 56 | struct GNUNET_JSON_Specification |
57 | GNUNET_RECLAIM_JSON_spec_claim_attest (struct | 57 | GNUNET_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 | ||
70 | GNUNET_NETWORK_STRUCT_END | 70 | GNUNET_NETWORK_STRUCT_END |
@@ -156,25 +156,25 @@ fix_base64 (char *str) | |||
156 | 156 | ||
157 | static json_t* | 157 | static json_t* |
158 | generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, | 158 | generate_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 | */ |
292 | char * | 297 | char * |
293 | OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, | 298 | OIDC_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, | |||
317 | char * | 323 | char * |
318 | OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | 324 | OIDC_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, | |||
433 | char * | 440 | char * |
434 | OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | 441 | OIDC_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 *) ¶ms[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 *) ¶ms[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 *) ¶ms[1]) + code_challenge_len + nonce_len; | 699 | attrs_ser = ((char *) ¶ms[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 @@ | |||
51 | char* | 52 | char* |
52 | OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | 53 | OIDC_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, | |||
71 | char* | 73 | char* |
72 | OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | 74 | OIDC_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 | */ |
138 | enum GNUNET_GenericReturnValue | 141 | enum GNUNET_GenericReturnValue |
139 | OIDC_check_scopes_for_claim_request (const char*scopes, | 142 | OIDC_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 | */ |
151 | char * | 154 | char * |
152 | OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, | 155 | OIDC_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 | */ |
98 | static struct | 97 | static 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 | */ |
153 | struct GNUNET_RECLAIM_AttributeList * | 152 | struct GNUNET_RECLAIM_AttributeList * |
154 | jwt_parse_attributes (void *cls, | 153 | jwt_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 | */ | ||
209 | struct GNUNET_RECLAIM_AttributeList * | ||
210 | jwt_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 | */ | ||
224 | struct GNUNET_RECLAIM_AttributeList * | ||
225 | jwt_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 | */ |
213 | char * | 239 | char * |
214 | jwt_get_issuer (void *cls, | 240 | jwt_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 | */ | ||
275 | char * | ||
276 | jwt_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 | */ | ||
292 | char * | ||
293 | jwt_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 | */ |
251 | int | 309 | int |
252 | jwt_get_expiration (void *cls, | 310 | jwt_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 | */ | ||
345 | int | ||
346 | jwt_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 | */ | ||
361 | int | ||
362 | jwt_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 | |||
370 | int | ||
371 | jwt_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 | */ |
288 | void * | 392 | void * |
289 | libgnunet_plugin_reclaim_attestation_jwt_init (void *cls) | 393 | libgnunet_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 | */ |
311 | void * | 423 | void * |
312 | libgnunet_plugin_reclaim_attestation_jwt_done (void *cls) | 424 | libgnunet_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 | ||
394 | struct RequestHandle | 394 | struct 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 | */ | ||
547 | static struct RequestHandle *requests_head; | ||
548 | |||
549 | /** | ||
550 | * DLL | ||
551 | */ | ||
552 | static 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 | ||
581 | static void | ||
582 | cleanup_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 | */ |
922 | static void | 942 | static void |
923 | oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | 943 | oidc_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 | ||
1039 | static void | 1061 | static void |
1040 | oidc_attest_collect_finished_cb (void *cls) | 1062 | oidc_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 | */ |
1061 | static void | 1088 | static void |
1062 | oidc_attest_collect (void *cls, | 1089 | oidc_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 | |||
2122 | consume_ticket (void *cls, | 2147 | consume_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 | ||
2623 | static int | ||
2624 | cleanup_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 | ||
155 | struct RequestHandle | 155 | struct 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 | */ | ||
261 | static struct RequestHandle *requests_head; | ||
262 | |||
263 | /** | ||
264 | * DLL | ||
265 | */ | ||
266 | static 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) | |||
319 | static void | 342 | static void |
320 | collect_error_cb (void *cls) | 343 | collect_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 | ||
438 | static void | 462 | static void |
439 | add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, | 463 | add_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 | */ |
522 | static void | 546 | static void |
523 | attest_collect (void *cls, | 547 | cred_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 | */ |
604 | static void | 628 | static void |
605 | list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, | 629 | list_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 | */ |
661 | static void | 685 | static void |
662 | delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle, | 686 | delete_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 | */ |
861 | struct GNUNET_RECLAIM_Attribute * | 885 | struct GNUNET_RECLAIM_Attribute * |
862 | parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest, | 886 | parse_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 | |||
1156 | consume_cont (void *cls, | 1180 | consume_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 | */ |
164 | struct AttestationResultMessage | 164 | struct 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 | */ |
239 | struct AttestationIterationStartMessage | 239 | struct 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 | */ |
261 | struct AttestationIterationNextMessage | 261 | struct 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 | */ |
278 | struct AttestationIterationStopMessage | 278 | struct 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 | */ |
244 | struct GNUNET_RECLAIM_AttestationIterator | 249 | struct 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 | */ |
466 | static void | 471 | static void |
467 | free_ait (struct GNUNET_RECLAIM_AttestationIterator *ait) | 472 | free_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 | */ |
776 | static int | 781 | static int |
777 | check_attestation_result (void *cls, const struct AttestationResultMessage *msg) | 782 | check_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 | */ |
800 | static void | 805 | static void |
801 | handle_attestation_result (void *cls, const struct | 806 | handle_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 | */ | ||
882 | static int | ||
883 | check_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 | */ |
1188 | struct GNUNET_RECLAIM_Operation * | 1226 | struct GNUNET_RECLAIM_Operation * |
1189 | GNUNET_RECLAIM_attestation_store ( | 1227 | GNUNET_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 | */ |
1235 | struct GNUNET_RECLAIM_Operation * | 1273 | struct GNUNET_RECLAIM_Operation * |
1236 | GNUNET_RECLAIM_attestation_delete ( | 1274 | GNUNET_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 | */ |
1401 | struct GNUNET_RECLAIM_AttestationIterator * | 1439 | struct GNUNET_RECLAIM_CredentialIterator * |
1402 | GNUNET_RECLAIM_get_attestations_start ( | 1440 | GNUNET_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 | */ |
1448 | void | 1486 | void |
1449 | GNUNET_RECLAIM_get_attestations_next (struct | 1487 | GNUNET_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 | */ |
1470 | void | 1508 | void |
1471 | GNUNET_RECLAIM_get_attestations_stop (struct | 1509 | GNUNET_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 | */ | ||
35 | struct 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 | */ | ||
52 | static struct Plugin **attest_plugins; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Number of plugins | ||
57 | */ | ||
58 | static unsigned int num_plugins; | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Init canary | ||
63 | */ | ||
64 | static 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 | */ | ||
74 | static void | ||
75 | add_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 | */ | ||
93 | static void | ||
94 | init () | ||
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 | */ | ||
112 | uint32_t | ||
113 | GNUNET_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 | */ | ||
137 | const char * | ||
138 | GNUNET_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 | */ | ||
166 | int | ||
167 | GNUNET_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 | */ | ||
198 | char * | ||
199 | GNUNET_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 | */ | ||
230 | struct GNUNET_RECLAIM_Attestation * | ||
231 | GNUNET_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 | */ | ||
264 | size_t | ||
265 | GNUNET_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 | */ | ||
288 | size_t | ||
289 | GNUNET_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 | */ | ||
317 | struct GNUNET_RECLAIM_AttestationList * | ||
318 | GNUNET_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 | */ | ||
359 | struct GNUNET_RECLAIM_AttestationList * | ||
360 | GNUNET_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 | */ | ||
391 | void | ||
392 | GNUNET_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 | */ | ||
416 | size_t | ||
417 | GNUNET_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 | */ | ||
432 | size_t | ||
433 | GNUNET_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 | */ | ||
471 | struct GNUNET_RECLAIM_Attestation * | ||
472 | GNUNET_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 | |||
512 | struct GNUNET_RECLAIM_AttributeList* | ||
513 | GNUNET_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 | |||
532 | char* | ||
533 | GNUNET_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 | |||
552 | int | ||
553 | GNUNET_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, | |||
231 | struct GNUNET_RECLAIM_Attribute * | 231 | struct GNUNET_RECLAIM_Attribute * |
232 | GNUNET_RECLAIM_attribute_new (const char *attr_name, | 232 | GNUNET_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 | |||
272 | GNUNET_RECLAIM_attribute_list_add ( | 272 | GNUNET_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 | */ |
506 | struct GNUNET_RECLAIM_Attribute * | 506 | ssize_t |
507 | GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size) | 507 | GNUNET_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 | ||
31 | GNUNET_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 | /** | 71 | GNUNET_NETWORK_STRUCT_BEGIN |
70 | * Serialized attestation claim | ||
71 | */ | ||
72 | struct 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 | */ | ||
35 | struct 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 | */ | ||
52 | static struct Plugin **credential_plugins; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Number of plugins | ||
57 | */ | ||
58 | static unsigned int num_plugins; | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Init canary | ||
63 | */ | ||
64 | static 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 | */ | ||
74 | static void | ||
75 | add_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 | */ | ||
93 | static void | ||
94 | init () | ||
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 | */ | ||
112 | uint32_t | ||
113 | GNUNET_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 | */ | ||
137 | const char * | ||
138 | GNUNET_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 | */ | ||
166 | int | ||
167 | GNUNET_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 | */ | ||
198 | char * | ||
199 | GNUNET_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 | */ | ||
230 | struct GNUNET_RECLAIM_Credential * | ||
231 | GNUNET_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 | */ | ||
264 | size_t | ||
265 | GNUNET_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 | */ | ||
288 | size_t | ||
289 | GNUNET_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 | */ | ||
317 | struct GNUNET_RECLAIM_CredentialList * | ||
318 | GNUNET_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 | */ | ||
359 | struct GNUNET_RECLAIM_CredentialList * | ||
360 | GNUNET_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 | */ | ||
391 | void | ||
392 | GNUNET_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 | */ | ||
416 | size_t | ||
417 | GNUNET_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 | */ | ||
432 | size_t | ||
433 | GNUNET_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 | */ | ||
471 | struct GNUNET_RECLAIM_Credential * | ||
472 | GNUNET_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 | |||
512 | struct GNUNET_RECLAIM_AttributeList* | ||
513 | GNUNET_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 | |||
532 | char* | ||
533 | GNUNET_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 | |||
552 | int | ||
553 | GNUNET_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 | */ | ||
579 | uint32_t | ||
580 | GNUNET_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 | */ | ||
604 | const char * | ||
605 | GNUNET_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 | */ | ||
633 | int | ||
634 | GNUNET_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 | */ | ||
665 | char * | ||
666 | GNUNET_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 | |||
688 | struct GNUNET_RECLAIM_Presentation * | ||
689 | GNUNET_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 | */ | ||
713 | size_t | ||
714 | GNUNET_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 | */ | ||
737 | size_t | ||
738 | GNUNET_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 | */ | ||
766 | struct GNUNET_RECLAIM_PresentationList * | ||
767 | GNUNET_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 | */ | ||
809 | struct GNUNET_RECLAIM_PresentationList * | ||
810 | GNUNET_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 | */ | ||
840 | void | ||
841 | GNUNET_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 | */ | ||
865 | size_t | ||
866 | GNUNET_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 | */ | ||
880 | size_t | ||
881 | GNUNET_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 | */ | ||
907 | struct GNUNET_RECLAIM_Presentation * | ||
908 | GNUNET_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 | |||
939 | struct GNUNET_RECLAIM_AttributeList* | ||
940 | GNUNET_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 | |||
960 | char* | ||
961 | GNUNET_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 | |||
981 | int | ||
982 | GNUNET_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 | */ | ||
1013 | int | ||
1014 | GNUNET_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 | */ |
34 | struct Attestation | 34 | struct 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 | */ | ||
68 | struct 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 | |||
6 | int | ||
7 | main (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; | |||
45 | struct RequestHandle | 45 | struct 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 | */ | ||
86 | static struct RequestHandle *requests_head; | ||
87 | |||
88 | /** | ||
89 | * DLL | ||
90 | */ | ||
91 | static 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 * | |||
415 | libgnunet_plugin_rest_config_done (void *cls) | 439 | libgnunet_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; | |||
46 | struct RequestHandle | 46 | struct 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 | */ | ||
82 | static struct RequestHandle *requests_head; | ||
83 | |||
84 | /** | ||
85 | * DLL | ||
86 | */ | ||
87 | static 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 | |||
2 | gnunet-revocation | 2 | gnunet-revocation |
3 | test_revocation | 3 | test_revocation |
4 | test_local_revocation.py | 4 | test_local_revocation.py |
5 | gnunet-revocation-tvg | ||
diff --git a/src/revocation/Makefile.am b/src/revocation/Makefile.am index a90f8cd79..9d98502a6 100644 --- a/src/revocation/Makefile.am +++ b/src/revocation/Makefile.am | |||
@@ -78,7 +78,7 @@ gnunet_service_revocation_SOURCES = \ | |||
78 | gnunet_service_revocation_LDADD = \ | 78 | gnunet_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 | */ |
83 | static struct GNUNET_SET_Handle *revocation_set; | 83 | static 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 | */ |
124 | static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle; | 124 | static 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 | */ |
433 | static void | 433 | static void |
434 | add_revocation (void *cls, | 434 | add_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 | |||
740 | handle_revocation_union_request (void *cls, | 733 | handle_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 | ||
106 | static 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 = \ | |||
39 | gnunet_service_scalarproduct_alice_LDADD = \ | 39 | gnunet_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 = \ | |||
50 | gnunet_service_scalarproduct_bob_LDADD = \ | 50 | gnunet_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 = \ | |||
61 | gnunet_service_scalarproduct_ecc_alice_LDADD = \ | 61 | gnunet_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 = \ | |||
72 | gnunet_service_scalarproduct_ecc_bob_LDADD = \ | 72 | gnunet_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 | */ |
656 | static void | 656 | static void |
657 | cb_intersection_element_removed (void *cls, | 657 | cb_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 | |||
740 | cb_intersection_request_alice (void *cls, | 733 | cb_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 | */ |
585 | static void | 585 | static void |
586 | cb_intersection_element_removed (void *cls, | 586 | cb_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 | */ |
901 | static void | 901 | static void |
902 | cb_intersection_element_removed (void *cls, | 902 | cb_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 | |||
985 | cb_intersection_request_alice (void *cls, | 979 | cb_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 | */ |
895 | static void | 895 | static void |
896 | cb_intersection_element_removed (void *cls, | 896 | cb_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 @@ | |||
1 | gnunet-seti-profiler | ||
2 | gnunet-service-seti | ||
3 | test_seti_api | ||
diff --git a/src/seti/Makefile.am b/src/seti/Makefile.am new file mode 100644 index 000000000..b4980b670 --- /dev/null +++ b/src/seti/Makefile.am | |||
@@ -0,0 +1,90 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
5 | |||
6 | libexecdir= $(pkglibdir)/libexec/ | ||
7 | |||
8 | plugindir = $(libdir)/gnunet | ||
9 | |||
10 | pkgcfg_DATA = \ | ||
11 | seti.conf | ||
12 | |||
13 | if USE_COVERAGE | ||
14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | ||
15 | endif | ||
16 | |||
17 | if HAVE_TESTING | ||
18 | bin_PROGRAMS = \ | ||
19 | gnunet-seti-profiler | ||
20 | endif | ||
21 | |||
22 | libexec_PROGRAMS = \ | ||
23 | gnunet-service-seti | ||
24 | |||
25 | lib_LTLIBRARIES = \ | ||
26 | libgnunetseti.la | ||
27 | |||
28 | gnunet_seti_profiler_SOURCES = \ | ||
29 | gnunet-seti-profiler.c | ||
30 | gnunet_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 | |||
38 | gnunet_service_seti_SOURCES = \ | ||
39 | gnunet-service-seti.c \ | ||
40 | gnunet-service-set_protocol.h | ||
41 | gnunet_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 | |||
50 | libgnunetseti_la_SOURCES = \ | ||
51 | seti_api.c seti.h | ||
52 | libgnunetseti_la_LIBADD = \ | ||
53 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
54 | $(LTLIBINTL) | ||
55 | libgnunetseti_la_LDFLAGS = \ | ||
56 | $(GN_LIB_LDFLAGS) | ||
57 | |||
58 | if HAVE_TESTING | ||
59 | check_PROGRAMS = \ | ||
60 | test_seti_api | ||
61 | endif | ||
62 | |||
63 | if ENABLE_TEST_RUN | ||
64 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
65 | TESTS = $(check_PROGRAMS) | ||
66 | endif | ||
67 | |||
68 | test_seti_api_SOURCES = \ | ||
69 | test_seti_api.c | ||
70 | test_seti_api_LDADD = \ | ||
71 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
72 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
73 | libgnunetseti.la | ||
74 | |||
75 | plugin_LTLIBRARIES = \ | ||
76 | libgnunet_plugin_block_seti_test.la | ||
77 | |||
78 | libgnunet_plugin_block_seti_test_la_SOURCES = \ | ||
79 | plugin_block_seti_test.c | ||
80 | libgnunet_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) | ||
85 | libgnunet_plugin_block_seti_test_la_LDFLAGS = \ | ||
86 | $(GN_PLUGIN_LDFLAGS) | ||
87 | |||
88 | |||
89 | EXTRA_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 | */ | ||
43 | enum 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 | */ | ||
86 | struct 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 | */ | ||
94 | struct ElementEntry; | ||
95 | |||
96 | /** | ||
97 | * Operation context used to execute a set operation. | ||
98 | */ | ||
99 | struct 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 | */ | ||
108 | struct 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 | */ | ||
139 | struct Listener; | ||
140 | |||
141 | |||
142 | /** | ||
143 | * State we keep per client. | ||
144 | */ | ||
145 | struct 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 | */ | ||
172 | struct 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 | */ | ||
341 | struct 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 | */ | ||
368 | struct 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 | */ | ||
421 | struct 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 | */ | ||
471 | static struct GNUNET_CADET_Handle *cadet; | ||
472 | |||
473 | /** | ||
474 | * Statistics handle. | ||
475 | */ | ||
476 | static struct GNUNET_STATISTICS_Handle *_GSS_statistics; | ||
477 | |||
478 | /** | ||
479 | * Listeners are held in a doubly linked list. | ||
480 | */ | ||
481 | static struct Listener *listener_head; | ||
482 | |||
483 | /** | ||
484 | * Listeners are held in a doubly linked list. | ||
485 | */ | ||
486 | static struct Listener *listener_tail; | ||
487 | |||
488 | /** | ||
489 | * Number of active clients. | ||
490 | */ | ||
491 | static 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 | */ | ||
497 | static 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 | */ | ||
505 | static 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 | */ | ||
515 | static void | ||
516 | send_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 | */ | ||
561 | static 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 | */ | ||
577 | static int | ||
578 | filtered_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 | */ | ||
648 | static int | ||
649 | iterator_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 | */ | ||
703 | static int | ||
704 | iterator_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 | */ | ||
737 | static 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 | */ | ||
797 | static 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 | */ | ||
806 | static void | ||
807 | incoming_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 | */ | ||
836 | static void | ||
837 | send_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 | */ | ||
865 | static 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 | */ | ||
909 | static void | ||
910 | fail_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 | */ | ||
943 | static void | ||
944 | send_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 | */ | ||
1047 | static void | ||
1048 | finished_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 | */ | ||
1066 | static void | ||
1067 | send_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 | */ | ||
1091 | static void | ||
1092 | send_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 | */ | ||
1167 | static int | ||
1168 | initialize_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 | */ | ||
1199 | static void | ||
1200 | send_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 | */ | ||
1221 | static void | ||
1222 | begin_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 | */ | ||
1239 | static void | ||
1240 | handle_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 | */ | ||
1272 | static void | ||
1273 | process_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 | */ | ||
1354 | static int | ||
1355 | check_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 | */ | ||
1371 | static void | ||
1372 | handle_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 | */ | ||
1471 | static int | ||
1472 | filter_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 | */ | ||
1504 | static void | ||
1505 | handle_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 | */ | ||
1565 | static struct Operation * | ||
1566 | get_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 | */ | ||
1587 | static void * | ||
1588 | client_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 | */ | ||
1610 | static int | ||
1611 | destroy_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 | */ | ||
1629 | static void | ||
1630 | client_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 | */ | ||
1703 | static int | ||
1704 | check_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 | */ | ||
1751 | static void | ||
1752 | handle_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 | */ | ||
1804 | static void | ||
1805 | handle_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 | */ | ||
1840 | static void | ||
1841 | incoming_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 | */ | ||
1868 | static void * | ||
1869 | channel_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 | */ | ||
1911 | static void | ||
1912 | channel_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 | */ | ||
1936 | static void | ||
1937 | channel_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 | */ | ||
1951 | static void | ||
1952 | handle_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 | */ | ||
2012 | static void | ||
2013 | handle_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 | */ | ||
2044 | static int | ||
2045 | check_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 | */ | ||
2060 | static void | ||
2061 | handle_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 | */ | ||
2124 | static void | ||
2125 | advance_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 | */ | ||
2146 | static int | ||
2147 | check_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 | */ | ||
2164 | static void | ||
2165 | handle_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 | */ | ||
2272 | static void | ||
2273 | handle_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 | */ | ||
2327 | static void | ||
2328 | handle_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 | */ | ||
2423 | static void | ||
2424 | shutdown_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 | */ | ||
2451 | static void | ||
2452 | run (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 | */ | ||
2477 | GNUNET_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 | |||
33 | GNUNET_NETWORK_STRUCT_BEGIN | ||
34 | |||
35 | struct 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 | */ | ||
61 | struct 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 | */ | ||
78 | struct 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 | */ | ||
123 | struct 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 | |||
142 | GNUNET_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 | |||
33 | static int ret; | ||
34 | |||
35 | static unsigned int num_a = 5; | ||
36 | static unsigned int num_b = 5; | ||
37 | static unsigned int num_c = 20; | ||
38 | |||
39 | const static struct GNUNET_CONFIGURATION_Handle *config; | ||
40 | |||
41 | struct 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 | |||
51 | static struct GNUNET_CONTAINER_MultiHashMap *common_sent; | ||
52 | |||
53 | static struct GNUNET_HashCode app_id; | ||
54 | |||
55 | static struct GNUNET_PeerIdentity local_peer; | ||
56 | |||
57 | static struct GNUNET_SETI_ListenHandle *set_listener; | ||
58 | |||
59 | static unsigned int use_intersection; | ||
60 | |||
61 | static unsigned int element_size = 32; | ||
62 | |||
63 | /** | ||
64 | * Handle to the statistics service. | ||
65 | */ | ||
66 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
67 | |||
68 | /** | ||
69 | * The profiler will write statistics | ||
70 | * for all peers to the file with this name. | ||
71 | */ | ||
72 | static char *statistics_filename; | ||
73 | |||
74 | /** | ||
75 | * The profiler will write statistics | ||
76 | * for all peers to this file. | ||
77 | */ | ||
78 | static FILE *statistics_file; | ||
79 | |||
80 | |||
81 | static int | ||
82 | map_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 | */ | ||
108 | static int | ||
109 | statistics_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 | |||
124 | static void | ||
125 | statistics_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 | |||
135 | static void | ||
136 | check_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 | |||
164 | static void | ||
165 | set_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 | |||
238 | static void | ||
239 | set_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 | |||
272 | static int | ||
273 | set_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 | |||
288 | static void | ||
289 | handle_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 | |||
322 | static void | ||
323 | run (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 | |||
421 | static void | ||
422 | pre_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 | |||
434 | int | ||
435 | main (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 | */ | ||
48 | static enum GNUNET_BLOCK_EvaluationResult | ||
49 | block_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 | */ | ||
79 | static int | ||
80 | block_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 | */ | ||
93 | void * | ||
94 | libgnunet_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 | */ | ||
113 | void * | ||
114 | libgnunet_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] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | @UNIXONLY@PORT = 2106 | ||
4 | HOSTNAME = localhost | ||
5 | BINARY = gnunet-service-seti | ||
6 | ACCEPT_FROM = 127.0.0.1; | ||
7 | ACCEPT_FROM6 = ::1; | ||
8 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-seti.sock | ||
9 | UNIX_MATCH_UID = YES | ||
10 | UNIX_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 | |||
33 | GNUNET_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 | */ | ||
39 | struct 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 | */ | ||
53 | struct 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 | */ | ||
76 | struct 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 | */ | ||
106 | struct 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 | */ | ||
123 | struct 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 | */ | ||
151 | struct 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 | */ | ||
191 | struct 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 | */ | ||
226 | struct 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 | */ | ||
251 | struct 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 | |||
265 | GNUNET_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 | */ | ||
39 | struct 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 | */ | ||
85 | struct 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 | */ | ||
105 | struct 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 | */ | ||
162 | struct 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 | */ | ||
212 | static int | ||
213 | check_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 | */ | ||
227 | static void | ||
228 | handle_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 | */ | ||
304 | static void | ||
305 | set_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 | */ | ||
334 | void | ||
335 | GNUNET_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 | */ | ||
368 | static void | ||
369 | handle_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 | */ | ||
398 | struct GNUNET_SETI_Handle * | ||
399 | GNUNET_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 | */ | ||
446 | int | ||
447 | GNUNET_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 | */ | ||
487 | void | ||
488 | GNUNET_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 | */ | ||
525 | struct GNUNET_SETI_OperationHandle * | ||
526 | GNUNET_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 | */ | ||
571 | static void | ||
572 | listen_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 | */ | ||
582 | static int | ||
583 | check_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 | */ | ||
607 | static void | ||
608 | handle_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 | */ | ||
650 | static void | ||
651 | handle_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 | */ | ||
673 | static void | ||
674 | listen_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 | */ | ||
714 | struct GNUNET_SETI_ListenHandle * | ||
715 | GNUNET_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 | */ | ||
746 | void | ||
747 | GNUNET_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 | */ | ||
779 | struct GNUNET_SETI_OperationHandle * | ||
780 | GNUNET_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 | */ | ||
835 | int | ||
836 | GNUNET_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 | */ | ||
874 | void | ||
875 | GNUNET_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] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-set/ | ||
5 | |||
6 | [seti] | ||
7 | START_ON_DEMAND = YES | ||
8 | #PREFIX = valgrind --leak-check=full | ||
9 | #PREFIX = gdbserver :1234 | ||
10 | OPTIONS = -L INFO | ||
11 | |||
12 | [transport] | ||
13 | PLUGINS = unix | ||
14 | OPTIONS = -LERROR | ||
15 | |||
16 | [nat] | ||
17 | RETURN_LOCAL_ADDRESSES = YES | ||
18 | DISABLEV6 = YES | ||
19 | USE_LOCALADDR = YES | ||
20 | |||
21 | [peerinfo] | ||
22 | NO_IO = YES | ||
23 | |||
24 | [nat] | ||
25 | # Use addresses from the local network interfaces (inluding loopback, but also others) | ||
26 | USE_LOCALADDR = YES | ||
27 | |||
28 | # Disable IPv6 support | ||
29 | DISABLEV6 = NO | ||
30 | |||
31 | # Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8) | ||
32 | RETURN_LOCAL_ADDRESSES = YES | ||
diff --git a/src/seti/test_seti_api.c b/src/seti/test_seti_api.c new file mode 100644 index 000000000..9074fab41 --- /dev/null +++ b/src/seti/test_seti_api.c | |||
@@ -0,0 +1,345 @@ | |||
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 | |||
33 | static int ret; | ||
34 | |||
35 | static struct GNUNET_PeerIdentity local_id; | ||
36 | |||
37 | static struct GNUNET_HashCode app_id; | ||
38 | |||
39 | static struct GNUNET_SETI_Handle *set1; | ||
40 | |||
41 | static struct GNUNET_SETI_Handle *set2; | ||
42 | |||
43 | static struct GNUNET_SETI_ListenHandle *listen_handle; | ||
44 | |||
45 | static const struct GNUNET_CONFIGURATION_Handle *config; | ||
46 | |||
47 | static struct GNUNET_SCHEDULER_Task *tt; | ||
48 | |||
49 | static struct GNUNET_SETI_OperationHandle *oh1; | ||
50 | |||
51 | static struct GNUNET_SETI_OperationHandle *oh2; | ||
52 | |||
53 | |||
54 | static void | ||
55 | result_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 | |||
89 | static void | ||
90 | result_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 | |||
127 | static void | ||
128 | listen_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 | */ | ||
156 | static void | ||
157 | start (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 | */ | ||
189 | static void | ||
190 | init_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 | */ | ||
221 | static void | ||
222 | init_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 | */ | ||
249 | static void | ||
250 | do_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 | */ | ||
290 | static void | ||
291 | timeout_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 | */ | ||
309 | static void | ||
310 | run (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 | |||
335 | int | ||
336 | main (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 @@ | |||
1 | gnunet-setu-profiler | ||
2 | gnunet-service-setu | ||
3 | gnunet-setu-ibf-profiler | ||
4 | test_setu_api | ||
5 | test_setu_copy | ||
6 | test_setu_result_symmetric | ||
diff --git a/src/setu/Makefile.am b/src/setu/Makefile.am new file mode 100644 index 000000000..b37ceba51 --- /dev/null +++ b/src/setu/Makefile.am | |||
@@ -0,0 +1,102 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
5 | |||
6 | libexecdir= $(pkglibdir)/libexec/ | ||
7 | |||
8 | plugindir = $(libdir)/gnunet | ||
9 | |||
10 | pkgcfg_DATA = \ | ||
11 | setu.conf | ||
12 | |||
13 | if USE_COVERAGE | ||
14 | AM_CFLAGS = -fprofile-arcs -ftest-coverage | ||
15 | endif | ||
16 | |||
17 | if HAVE_TESTING | ||
18 | bin_PROGRAMS = \ | ||
19 | gnunet-setu-profiler | ||
20 | |||
21 | noinst_PROGRAMS = \ | ||
22 | gnunet-setu-ibf-profiler | ||
23 | endif | ||
24 | |||
25 | libexec_PROGRAMS = \ | ||
26 | gnunet-service-setu | ||
27 | |||
28 | lib_LTLIBRARIES = \ | ||
29 | libgnunetsetu.la | ||
30 | |||
31 | gnunet_setu_profiler_SOURCES = \ | ||
32 | gnunet-setu-profiler.c | ||
33 | gnunet_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 | |||
41 | gnunet_setu_ibf_profiler_SOURCES = \ | ||
42 | gnunet-setu-ibf-profiler.c \ | ||
43 | ibf.c | ||
44 | gnunet_setu_ibf_profiler_LDADD = \ | ||
45 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
46 | $(GN_LIBINTL) | ||
47 | |||
48 | gnunet_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 | ||
53 | gnunet_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 | |||
62 | libgnunetsetu_la_SOURCES = \ | ||
63 | setu_api.c setu.h | ||
64 | libgnunetsetu_la_LIBADD = \ | ||
65 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
66 | $(LTLIBINTL) | ||
67 | libgnunetsetu_la_LDFLAGS = \ | ||
68 | $(GN_LIB_LDFLAGS) | ||
69 | |||
70 | if HAVE_TESTING | ||
71 | check_PROGRAMS = \ | ||
72 | test_setu_api | ||
73 | endif | ||
74 | |||
75 | if ENABLE_TEST_RUN | ||
76 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
77 | TESTS = $(check_PROGRAMS) | ||
78 | endif | ||
79 | |||
80 | test_setu_api_SOURCES = \ | ||
81 | test_setu_api.c | ||
82 | test_setu_api_LDADD = \ | ||
83 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
84 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
85 | libgnunetsetu.la | ||
86 | |||
87 | plugin_LTLIBRARIES = \ | ||
88 | libgnunet_plugin_block_setu_test.la | ||
89 | |||
90 | libgnunet_plugin_block_setu_test_la_SOURCES = \ | ||
91 | plugin_block_setu_test.c | ||
92 | libgnunet_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) | ||
97 | libgnunet_plugin_block_setu_test_la_LDFLAGS = \ | ||
98 | $(GN_PLUGIN_LDFLAGS) | ||
99 | |||
100 | |||
101 | EXTRA_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 | */ | ||
85 | enum 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 | */ | ||
150 | struct 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 | */ | ||
181 | struct Listener; | ||
182 | |||
183 | |||
184 | /** | ||
185 | * A set that supports a specific operation with other peers. | ||
186 | */ | ||
187 | struct Set; | ||
188 | |||
189 | |||
190 | /** | ||
191 | * State we keep per client. | ||
192 | */ | ||
193 | struct 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 | */ | ||
220 | struct 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 | */ | ||
404 | struct 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 | */ | ||
431 | struct 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 | */ | ||
483 | struct 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 | */ | ||
511 | struct 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 | */ | ||
531 | struct 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 | */ | ||
581 | static struct GNUNET_CADET_Handle *cadet; | ||
582 | |||
583 | /** | ||
584 | * Statistics handle. | ||
585 | */ | ||
586 | static struct GNUNET_STATISTICS_Handle *_GSS_statistics; | ||
587 | |||
588 | /** | ||
589 | * Listeners are held in a doubly linked list. | ||
590 | */ | ||
591 | static struct Listener *listener_head; | ||
592 | |||
593 | /** | ||
594 | * Listeners are held in a doubly linked list. | ||
595 | */ | ||
596 | static struct Listener *listener_tail; | ||
597 | |||
598 | /** | ||
599 | * Number of active clients. | ||
600 | */ | ||
601 | static 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 | */ | ||
607 | static 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 | */ | ||
614 | static 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 | */ | ||
627 | static int | ||
628 | destroy_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 | */ | ||
651 | static void | ||
652 | send_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 | */ | ||
711 | static 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 | */ | ||
779 | static 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 | */ | ||
788 | static void | ||
789 | incoming_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 | */ | ||
817 | static 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 | */ | ||
847 | static void | ||
848 | fail_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 | */ | ||
872 | static struct IBF_Key | ||
873 | get_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 | */ | ||
890 | struct 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 | */ | ||
914 | static int | ||
915 | op_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 | */ | ||
941 | static struct KeyEntry * | ||
942 | op_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 | */ | ||
981 | static void | ||
982 | op_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 | */ | ||
1005 | static void | ||
1006 | salt_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 | */ | ||
1022 | static void | ||
1023 | unsalt_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 | */ | ||
1042 | static int | ||
1043 | prepare_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 | */ | ||
1071 | static 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 | */ | ||
1089 | static int | ||
1090 | init_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 | */ | ||
1116 | static void | ||
1117 | initialize_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 | */ | ||
1138 | static int | ||
1139 | prepare_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 | */ | ||
1169 | static int | ||
1170 | send_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 | */ | ||
1239 | static unsigned int | ||
1240 | get_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 | */ | ||
1263 | static int | ||
1264 | send_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 | */ | ||
1295 | static void | ||
1296 | send_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 | */ | ||
1320 | static int | ||
1321 | check_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 | */ | ||
1352 | static void | ||
1353 | handle_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 | */ | ||
1485 | static int | ||
1486 | send_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 | */ | ||
1521 | static void | ||
1522 | send_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 | */ | ||
1545 | static int | ||
1546 | decode_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 | */ | ||
1711 | static int | ||
1712 | check_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 | */ | ||
1769 | static void | ||
1770 | handle_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 | */ | ||
1847 | static void | ||
1848 | send_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 | */ | ||
1886 | static void | ||
1887 | maybe_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 | */ | ||
1932 | static int | ||
1933 | check_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 | */ | ||
1955 | static void | ||
1956 | handle_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 | */ | ||
2047 | static int | ||
2048 | check_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 | */ | ||
2065 | static void | ||
2066 | handle_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 | */ | ||
2149 | static int | ||
2150 | check_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 | */ | ||
2179 | static void | ||
2180 | handle_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 | */ | ||
2217 | static int | ||
2218 | send_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 | */ | ||
2249 | static void | ||
2250 | handle_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 | */ | ||
2277 | static void | ||
2278 | handle_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 | */ | ||
2337 | static int | ||
2338 | check_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 | */ | ||
2364 | static void | ||
2365 | handle_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 | */ | ||
2431 | static int | ||
2432 | check_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 | */ | ||
2464 | static void | ||
2465 | handle_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 | */ | ||
2525 | static void | ||
2526 | handle_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 | */ | ||
2576 | static void | ||
2577 | handle_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 | */ | ||
2592 | static struct Operation * | ||
2593 | get_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 | */ | ||
2617 | static void * | ||
2618 | client_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 | */ | ||
2640 | static int | ||
2641 | destroy_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 | */ | ||
2659 | static void | ||
2660 | client_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 | */ | ||
2745 | static int | ||
2746 | check_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 | */ | ||
2793 | static void | ||
2794 | handle_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 | */ | ||
2847 | static void | ||
2848 | handle_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 | */ | ||
2899 | static void | ||
2900 | incoming_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 | */ | ||
2927 | static void * | ||
2928 | channel_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 | */ | ||
2970 | static void | ||
2971 | channel_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 | */ | ||
2995 | static void | ||
2996 | channel_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 | */ | ||
3010 | static void | ||
3011 | handle_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 | */ | ||
3107 | static void | ||
3108 | handle_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 | */ | ||
3139 | static int | ||
3140 | check_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 | */ | ||
3155 | static void | ||
3156 | handle_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 | */ | ||
3222 | static void | ||
3223 | advance_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 | */ | ||
3239 | static int | ||
3240 | check_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 | */ | ||
3257 | static void | ||
3258 | handle_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 | */ | ||
3412 | static void | ||
3413 | handle_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 | */ | ||
3467 | static void | ||
3468 | handle_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 | */ | ||
3591 | static void | ||
3592 | shutdown_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 | */ | ||
3619 | static void | ||
3620 | run (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 | */ | ||
3645 | GNUNET_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 | |||
33 | GNUNET_NETWORK_STRUCT_BEGIN | ||
34 | |||
35 | struct 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 | */ | ||
67 | struct 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 | |||
104 | struct 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 | */ | ||
130 | struct 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 | */ | ||
147 | struct 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 | */ | ||
192 | struct 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 | */ | ||
214 | struct 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 | |||
224 | GNUNET_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 | */ | ||
46 | size_t | ||
47 | strata_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 | */ | ||
94 | int | ||
95 | strata_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 | */ | ||
143 | void | ||
144 | strata_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 | */ | ||
164 | void | ||
165 | strata_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 | */ | ||
187 | struct StrataEstimator * | ||
188 | strata_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 | */ | ||
227 | unsigned int | ||
228 | strata_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 | */ | ||
272 | struct StrataEstimator * | ||
273 | strata_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 | */ | ||
294 | void | ||
295 | strata_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 | ||
35 | extern "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 | */ | ||
46 | struct 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 | */ | ||
72 | size_t | ||
73 | strata_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 | */ | ||
87 | int | ||
88 | strata_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 | */ | ||
102 | struct StrataEstimator * | ||
103 | strata_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 | */ | ||
116 | unsigned int | ||
117 | strata_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 | */ | ||
127 | void | ||
128 | strata_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 | */ | ||
138 | void | ||
139 | strata_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 | */ | ||
148 | void | ||
149 | strata_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 | */ | ||
158 | struct StrataEstimator * | ||
159 | strata_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 | |||
32 | static unsigned int asize = 10; | ||
33 | static unsigned int bsize = 10; | ||
34 | static unsigned int csize = 10; | ||
35 | static unsigned int hash_num = 4; | ||
36 | static unsigned int ibf_size = 80; | ||
37 | |||
38 | /* FIXME: add parameter for this */ | ||
39 | static enum GNUNET_CRYPTO_Quality random_quality = GNUNET_CRYPTO_QUALITY_WEAK; | ||
40 | |||
41 | static struct GNUNET_CONTAINER_MultiHashMap *set_a; | ||
42 | static struct GNUNET_CONTAINER_MultiHashMap *set_b; | ||
43 | /* common elements in a and b */ | ||
44 | static struct GNUNET_CONTAINER_MultiHashMap *set_c; | ||
45 | |||
46 | static struct GNUNET_CONTAINER_MultiHashMap *key_to_hashcode; | ||
47 | |||
48 | static struct InvertibleBloomFilter *ibf_a; | ||
49 | static struct InvertibleBloomFilter *ibf_b; | ||
50 | |||
51 | |||
52 | static void | ||
53 | register_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 | |||
68 | static void | ||
69 | iter_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 | |||
83 | static int | ||
84 | insert_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 | |||
93 | static int | ||
94 | remove_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 | |||
104 | static void | ||
105 | run (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 | |||
261 | int | ||
262 | main (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 | |||
33 | static int ret; | ||
34 | |||
35 | static unsigned int num_a = 5; | ||
36 | static unsigned int num_b = 5; | ||
37 | static unsigned int num_c = 20; | ||
38 | |||
39 | static char *op_str = "union"; | ||
40 | |||
41 | const static struct GNUNET_CONFIGURATION_Handle *config; | ||
42 | |||
43 | struct 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 | |||
53 | static struct GNUNET_CONTAINER_MultiHashMap *common_sent; | ||
54 | |||
55 | static struct GNUNET_HashCode app_id; | ||
56 | |||
57 | static struct GNUNET_PeerIdentity local_peer; | ||
58 | |||
59 | static struct GNUNET_SETU_ListenHandle *set_listener; | ||
60 | |||
61 | static int byzantine; | ||
62 | static unsigned int force_delta; | ||
63 | static unsigned int force_full; | ||
64 | static unsigned int element_size = 32; | ||
65 | |||
66 | /** | ||
67 | * Handle to the statistics service. | ||
68 | */ | ||
69 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
70 | |||
71 | /** | ||
72 | * The profiler will write statistics | ||
73 | * for all peers to the file with this name. | ||
74 | */ | ||
75 | static char *statistics_filename; | ||
76 | |||
77 | /** | ||
78 | * The profiler will write statistics | ||
79 | * for all peers to this file. | ||
80 | */ | ||
81 | static FILE *statistics_file; | ||
82 | |||
83 | |||
84 | static int | ||
85 | map_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 | */ | ||
111 | static int | ||
112 | statistics_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 | |||
127 | static void | ||
128 | statistics_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 | |||
138 | static void | ||
139 | check_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 | |||
167 | static void | ||
168 | set_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 | |||
218 | static void | ||
219 | set_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 | |||
262 | static int | ||
263 | set_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 | |||
278 | static void | ||
279 | handle_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 | |||
312 | static void | ||
313 | run (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 | |||
424 | static void | ||
425 | pre_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 | |||
435 | int | ||
436 | main (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 | */ | ||
42 | struct IBF_Key | ||
43 | ibf_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 | */ | ||
56 | void | ||
57 | ibf_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 | */ | ||
78 | struct InvertibleBloomFilter * | ||
79 | ibf_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 | */ | ||
117 | static void | ||
118 | ibf_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; | ||
135 | try_next:; | ||
136 | x = ((uint64_t) bucket << 32) | i; | ||
137 | bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | |||
142 | static void | ||
143 | ibf_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 | */ | ||
166 | void | ||
167 | ibf_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 | */ | ||
183 | void | ||
184 | ibf_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 | */ | ||
197 | static int | ||
198 | ibf_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 | */ | ||
227 | int | ||
228 | ibf_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 | */ | ||
289 | void | ||
290 | ibf_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 | */ | ||
322 | void | ||
323 | ibf_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 | */ | ||
355 | void | ||
356 | ibf_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 | */ | ||
378 | struct InvertibleBloomFilter * | ||
379 | ibf_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 | */ | ||
402 | void | ||
403 | ibf_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 | ||
34 | extern "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 | */ | ||
45 | struct IBF_Key | ||
46 | { | ||
47 | uint64_t key_val; | ||
48 | }; | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Hash of an IBF key. | ||
53 | */ | ||
54 | struct IBF_KeyHash | ||
55 | { | ||
56 | uint32_t key_hash_val; | ||
57 | }; | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Type of the count field of IBF buckets. | ||
62 | */ | ||
63 | struct 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 | */ | ||
82 | struct 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 | */ | ||
125 | void | ||
126 | ibf_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 | */ | ||
140 | void | ||
141 | ibf_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 | */ | ||
153 | struct IBF_Key | ||
154 | ibf_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 | */ | ||
164 | void | ||
165 | ibf_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 | */ | ||
175 | struct InvertibleBloomFilter * | ||
176 | ibf_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 | */ | ||
185 | void | ||
186 | ibf_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 | */ | ||
195 | void | ||
196 | ibf_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 | */ | ||
206 | void | ||
207 | ibf_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 | */ | ||
223 | int | ||
224 | ibf_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 | */ | ||
234 | struct InvertibleBloomFilter * | ||
235 | ibf_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 | */ | ||
244 | void | ||
245 | ibf_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 | |||
52 | int | ||
53 | main (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 | */ | ||
48 | static enum GNUNET_BLOCK_EvaluationResult | ||
49 | block_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 | */ | ||
79 | static int | ||
80 | block_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 | */ | ||
93 | void * | ||
94 | libgnunet_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 | */ | ||
113 | void * | ||
114 | libgnunet_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] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | @UNIXONLY@PORT = 2106 | ||
4 | HOSTNAME = localhost | ||
5 | BINARY = gnunet-service-setu | ||
6 | ACCEPT_FROM = 127.0.0.1; | ||
7 | ACCEPT_FROM6 = ::1; | ||
8 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-setu.sock | ||
9 | UNIX_MATCH_UID = YES | ||
10 | UNIX_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 | |||
33 | GNUNET_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 | */ | ||
40 | struct 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 | */ | ||
55 | struct 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 | */ | ||
78 | struct 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 | */ | ||
131 | struct 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 | */ | ||
148 | struct 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 | */ | ||
176 | struct 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 | */ | ||
239 | struct 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 | */ | ||
275 | struct 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 | */ | ||
299 | struct 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 | |||
313 | GNUNET_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 | */ | ||
38 | struct 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 | */ | ||
73 | struct 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 | */ | ||
93 | struct 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 | */ | ||
144 | struct 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 | */ | ||
194 | static int | ||
195 | check_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 | */ | ||
209 | static void | ||
210 | handle_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 | */ | ||
288 | static void | ||
289 | set_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 | */ | ||
318 | void | ||
319 | GNUNET_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 | */ | ||
352 | static void | ||
353 | handle_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 | */ | ||
382 | struct GNUNET_SETU_Handle * | ||
383 | GNUNET_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 | */ | ||
427 | int | ||
428 | GNUNET_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 | */ | ||
469 | void | ||
470 | GNUNET_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 | */ | ||
507 | struct GNUNET_SETU_OperationHandle * | ||
508 | GNUNET_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 | */ | ||
563 | static void | ||
564 | listen_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 | */ | ||
574 | static int | ||
575 | check_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 | */ | ||
599 | static void | ||
600 | handle_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 | */ | ||
642 | static void | ||
643 | handle_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 | */ | ||
665 | static void | ||
666 | listen_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 | */ | ||
707 | struct GNUNET_SETU_ListenHandle * | ||
708 | GNUNET_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 | */ | ||
739 | void | ||
740 | GNUNET_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 | */ | ||
773 | struct GNUNET_SETU_OperationHandle * | ||
774 | GNUNET_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 | */ | ||
836 | int | ||
837 | GNUNET_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 | */ | ||
875 | void | ||
876 | GNUNET_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 | |||
32 | static struct GNUNET_PeerIdentity local_id; | ||
33 | |||
34 | static struct GNUNET_HashCode app_id; | ||
35 | |||
36 | static struct GNUNET_SETU_Handle *set1; | ||
37 | |||
38 | static struct GNUNET_SETU_Handle *set2; | ||
39 | |||
40 | static struct GNUNET_SETU_ListenHandle *listen_handle; | ||
41 | |||
42 | static struct GNUNET_SETU_OperationHandle *oh1; | ||
43 | |||
44 | static struct GNUNET_SETU_OperationHandle *oh2; | ||
45 | |||
46 | static const struct GNUNET_CONFIGURATION_Handle *config; | ||
47 | |||
48 | static int ret; | ||
49 | |||
50 | static struct GNUNET_SCHEDULER_Task *tt; | ||
51 | |||
52 | |||
53 | static void | ||
54 | result_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 | |||
100 | static void | ||
101 | result_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 | |||
139 | static void | ||
140 | listen_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 | */ | ||
161 | static void | ||
162 | start (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 | */ | ||
188 | static void | ||
189 | init_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 | */ | ||
211 | static void | ||
212 | init_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 | */ | ||
232 | static void | ||
233 | timeout_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 | */ | ||
247 | static void | ||
248 | do_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 | */ | ||
291 | static void | ||
292 | run (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 | |||
343 | int | ||
344 | main (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 | |||
71 | perf_crypto_symmetric | 71 | perf_crypto_symmetric |
72 | perf_crypto_rsa | 72 | perf_crypto_rsa |
73 | perf_crypto_ecc_dlog | 73 | perf_crypto_ecc_dlog |
74 | test_hexcoder | 74 | test_hexcoder |
75 | test_regex | 75 | test_regex |
76 | test_tun | 76 | test_tun |
77 | test_uri | ||
77 | gnunet-timeout | 78 | gnunet-timeout |
78 | python27_location | 79 | python27_location |
79 | perf_malloc | 80 | perf_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 = \ | |||
573 | test_speedup_LDADD = \ | 575 | test_speedup_LDADD = \ |
574 | libgnunetutil.la | 576 | libgnunetutil.la |
575 | 577 | ||
578 | test_uri_SOURCES = \ | ||
579 | test_uri.c | ||
580 | test_uri_LDADD = \ | ||
581 | libgnunetutil.la | ||
582 | |||
576 | perf_crypto_hash_SOURCES = \ | 583 | perf_crypto_hash_SOURCES = \ |
577 | perf_crypto_hash.c | 584 | perf_crypto_hash.c |
578 | perf_crypto_hash_LDADD = \ | 585 | perf_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 | */ |
543 | int | 543 | enum GNUNET_GenericReturnValue |
544 | GNUNET_is_zero_ (const void *a, | 544 | GNUNET_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 | */ |
40 | void | 40 | void |
41 | GNUNET_CRYPTO_pow_hash (const char *salt, | 41 | GNUNET_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 | */ | ||
33 | static 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; |
475 | NEXT: | 475 | NEXT: |
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 | |||
38 | int tests_run; | ||
39 | |||
40 | static int | ||
41 | strcmp_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 | |||
83 | static char * | ||
84 | test_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 | |||
396 | static char * | ||
397 | test_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 | |||
491 | static char * | ||
492 | test_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 | |||
557 | static char * | ||
558 | test_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 | |||
625 | static char * | ||
626 | test_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 ("¶m=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 | |||
805 | static char * | ||
806 | all_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 | |||
826 | int | ||
827 | main (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 | */ | ||
34 | static inline int | ||
35 | natoi (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 | */ | ||
55 | static inline int | ||
56 | is_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 | */ | ||
69 | static inline char * | ||
70 | parse_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 | */ | ||
101 | static inline char * | ||
102 | find_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. */ | ||
118 | static inline char * | ||
119 | find_fragment (char *str) | ||
120 | { | ||
121 | return find_and_terminate (str, '#'); | ||
122 | } | ||
123 | |||
124 | |||
125 | static inline char * | ||
126 | find_query (char *str) | ||
127 | { | ||
128 | return find_and_terminate (str, '?'); | ||
129 | } | ||
130 | |||
131 | |||
132 | static inline char * | ||
133 | find_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 | */ | ||
158 | int | ||
159 | GNUNET_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 | */ | ||
259 | int | ||
260 | GNUNET_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 | */ | ||
311 | int | ||
312 | GNUNET_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 | } | ||