aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules6
-rw-r--r--ChangeLog226
-rw-r--r--Makefile.am11
-rwxr-xr-xbootstrap36
-rw-r--r--configure.ac13
-rw-r--r--contrib/Makefile.am6
m---------contrib/build-common0
-rw-r--r--contrib/conf/uncrustify.cfg19
-rwxr-xr-xcontrib/conf/uncrustify_precommit2
m---------contrib/gana0
-rw-r--r--doc/handbook/chapters/developer.texi2
-rw-r--r--doc/man/gnunet-identity.126
-rwxr-xr-xdoc/man/produce_html.sh.in9
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/abd/Makefile.am6
-rw-r--r--src/abd/abd_serialization.c4
-rw-r--r--src/abd/delegate_misc.c18
-rw-r--r--src/abd/gnunet-abd.c26
-rw-r--r--src/abd/gnunet-service-abd.c44
-rw-r--r--src/abd/plugin_gnsrecord_abd.c11
-rw-r--r--src/block/block.c190
-rw-r--r--src/block/plugin_block_template.c83
-rw-r--r--src/block/plugin_block_test.c109
-rw-r--r--src/consensus/plugin_block_consensus.c116
-rw-r--r--src/curl/curl.c196
-rw-r--r--src/datacache/datacache.c83
-rw-r--r--src/datacache/plugin_datacache_heap.c28
-rw-r--r--src/datacache/plugin_datacache_postgres.c99
-rw-r--r--src/datacache/plugin_datacache_sqlite.c90
-rw-r--r--src/datacache/plugin_datacache_template.c19
-rw-r--r--src/datastore/gnunet-service-datastore.c3
-rw-r--r--src/dht/dht_api.c3
-rw-r--r--src/dht/gnunet-service-dht.h73
-rw-r--r--src/dht/gnunet-service-dht_clients.c1182
-rw-r--r--src/dht/gnunet-service-dht_datacache.c279
-rw-r--r--src/dht/gnunet-service-dht_datacache.h124
-rw-r--r--src/dht/gnunet-service-dht_hello.c18
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c1925
-rw-r--r--src/dht/gnunet-service-dht_neighbours.h63
-rw-r--r--src/dht/gnunet-service-dht_nse.c30
-rw-r--r--src/dht/gnunet-service-dht_routing.c319
-rw-r--r--src/dht/gnunet-service-dht_routing.h24
-rw-r--r--src/dht/plugin_block_dht.c144
-rw-r--r--src/dns/plugin_block_dns.c140
-rw-r--r--src/fs/gnunet-service-fs.c12
-rw-r--r--src/fs/gnunet-service-fs.h2
-rw-r--r--src/fs/gnunet-service-fs_cp.c26
-rw-r--r--src/fs/gnunet-service-fs_pr.c99
-rw-r--r--src/fs/gnunet-service-fs_pr.h28
-rw-r--r--src/fs/plugin_block_fs.c156
-rw-r--r--src/fs/test_plugin_block_fs.c45
-rw-r--r--src/gns/Makefile.am29
-rw-r--r--src/gns/gns.conf.in3
-rw-r--r--src/gns/gnunet-gns-proxy-setup-ca.in60
-rw-r--r--src/gns/plugin_block_gns.c133
-rwxr-xr-xsrc/gns/test_gnunet_gns.sh.in9
-rw-r--r--src/identity/Makefile.am5
-rw-r--r--src/identity/gnunet-identity.c209
-rw-r--r--src/identity/identity_api.c15
-rw-r--r--src/identity/test_identity.conf3
-rwxr-xr-xsrc/identity/test_identity_messages.sh34
-rw-r--r--src/include/.gitignore2
-rw-r--r--src/include/gnu_name_system_record_types.h148
-rw-r--r--src/include/gnunet_block_lib.h115
-rw-r--r--src/include/gnunet_block_plugin.h97
-rw-r--r--src/include/gnunet_crypto_lib.h70
-rw-r--r--src/include/gnunet_datacache_lib.h14
-rw-r--r--src/include/gnunet_datacache_plugin.h60
-rw-r--r--src/include/gnunet_dht_service.h6
-rw-r--r--src/include/gnunet_getopt_lib.h18
-rw-r--r--src/include/gnunet_identity_service.h2
-rw-r--r--src/include/gnunet_json_lib.h38
-rw-r--r--src/include/gnunet_pq_lib.h53
-rw-r--r--src/include/gnunet_signatures.h266
-rw-r--r--src/include/gnunet_sq_lib.h10
-rw-r--r--src/include/gnunet_strings_lib.h19
-rw-r--r--src/include/gnunet_time_lib.h220
-rw-r--r--src/json/json_generator.c122
-rw-r--r--src/json/json_helper.c167
-rw-r--r--src/json/json_pack.c16
-rw-r--r--src/json/test_json.c69
-rw-r--r--src/messenger/messenger_api.c2
-rw-r--r--src/namestore/gnunet-namestore-fcfsd.c4
-rw-r--r--src/nse/gnunet-service-nse.c39
-rw-r--r--src/pq/pq_connect.c1
-rw-r--r--src/pq/pq_query_helper.c55
-rw-r--r--src/pq/pq_result_helper.c142
-rw-r--r--src/regex/plugin_block_regex.c228
-rw-r--r--src/revocation/gnunet-service-revocation.c33
-rw-r--r--src/revocation/plugin_block_revocation.c242
-rw-r--r--src/revocation/revocation_api.c25
-rw-r--r--src/set/plugin_block_set_test.c88
-rw-r--r--src/seti/plugin_block_seti_test.c86
-rw-r--r--src/setu/plugin_block_setu_test.c86
-rw-r--r--src/transport/gnunet-communicator-tcp.c30
-rw-r--r--src/transport/gnunet-communicator-udp.c20
-rw-r--r--src/util/Makefile.am2
-rw-r--r--src/util/crypto_cs.c8
-rw-r--r--src/util/crypto_ecc_setup.c11
-rw-r--r--src/util/crypto_hash.c127
-rw-r--r--src/util/getopt_helpers.c249
-rw-r--r--src/util/gnunet-scrypt.c21
-rw-r--r--src/util/perf_crypto_cs.c8
-rw-r--r--src/util/perf_crypto_rsa.c1
-rw-r--r--src/util/strings.c22
-rw-r--r--src/util/test_crypto_cs.c10
-rw-r--r--src/util/test_crypto_eddsa.c16
-rw-r--r--src/util/test_crypto_hash.c157
-rw-r--r--src/util/time.c218
109 files changed, 5768 insertions, 4349 deletions
diff --git a/.gitmodules b/.gitmodules
index 9773fb9d7..752738003 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
1[submodule "contrib/build-common"] 1[submodule "contrib/gana"]
2 path = contrib/build-common 2 path = contrib/gana
3 url = https://git.taler.net/build-common.git 3 url = git://git.gnunet.org/gana.git
diff --git a/ChangeLog b/ChangeLog
index c347c141d..bf3f089bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,227 @@
1Wed, 1 Sep 2021 10:28:09 +0200 (d51000320) 1Tue, 21 Dec 2021 15:27:27 +0100 (ff714cca7)
2add fix for GNUnet directory permissions by madmurphy - Christian Grothoff 2changed derive_secrets API - Gian Demarmels
3
4Mon, 20 Dec 2021 10:59:42 +0100 (ed65e2cac)
5BUILD: Kill build-common - Martin Schanzenbach
6
7Mon, 20 Dec 2021 10:23:14 +0100 (511058f7e)
8DOCUMENTATION: Fix link to tutorial - Martin Schanzenbach
9
10Thu, 16 Dec 2021 17:48:38 +0100 (4ec4cc9bd)
11fix GNUNET_PQ_result_spec_timestamp_nbo - Christian Grothoff
12
13Thu, 16 Dec 2021 12:51:02 +0100 (a062e1241)
14tolerate old style values (for now) - Christian Grothoff
15
16Wed, 15 Dec 2021 13:18:24 +0100 (8faf7660d)
17enable v10 backwards compatibility - Christian Grothoff
18
19Tue, 14 Dec 2021 15:59:07 +0100 (99779b455)
20introducing GNUNET_TIME_Timestamp - Christian Grothoff
21
22Mon, 6 Dec 2021 22:44:14 +0100 (67b56e366)
23add crypto_cs testing and benchmark - Lucien Heuzeveldt
24
25Mon, 6 Dec 2021 22:13:35 +0100 (2bcdfc2f9)
26add crypto_cs implementation - Lucien Heuzeveldt
27
28Mon, 6 Dec 2021 14:20:25 +0100 (1816cee64)
29fixed timeout for netjail tests, removed duplicated function declaration from header, using GNUNET_TESTING_get_trait_batch_cmds in loop, fixed tng service shutdown logic, added missing GNUNET_SERVICE_client_continue, changed default log level for udp backchannel test to debug - t3sserakt
30
31Mon, 6 Dec 2021 10:14:03 +0100 (7a7f3d5e0)
32propose barrier API - Christian Grothoff
33
34Mon, 6 Dec 2021 10:05:04 +0100 (41f26e067)
35propose barrier API - Christian Grothoff
36
37Mon, 6 Dec 2021 10:04:34 +0100 (a388fd600)
38propose barrier API - Christian Grothoff
39
40Sun, 5 Dec 2021 11:58:45 +0100 (2266d4614)
41add bool type to libgnunetpq - Christian Grothoff
42
43Fri, 3 Dec 2021 22:27:46 +0100 (f236a1f38)
44ABD: Fix build - Martin Schanzenbach
45
46Fri, 3 Dec 2021 18:22:15 +0100 (0d7bbcd3a)
47DHT: Update wire formats. - Martin Schanzenbach
48
49Fri, 3 Dec 2021 18:14:38 +0100 (a0b8084ca)
50DHT: Remove unused processing option - Martin Schanzenbach
51
52Tue, 30 Nov 2021 16:14:35 +0100 (f80d6d695)
53ignore prepared statement failures if statement is already known to enable connection pooling - Christian Grothoff
54
55Fri, 26 Nov 2021 13:11:47 +0100 (9792ef1c3)
56make LE optional - Christian Grothoff
57
58Fri, 26 Nov 2021 07:03:17 -0500 (c384f7784)
59No longer require libextractor at configure time - Thien-Thi Nguyen
60
61Fri, 26 Nov 2021 09:17:35 +0100 (b1bb98f8b)
62make sudo non-interactive - Christian Grothoff
63
64Thu, 25 Nov 2021 23:50:13 +0100 (04166afcb)
65fix configure.ac issues with autoconf 2.69 - Christian Grothoff
66
67Thu, 25 Nov 2021 23:38:58 +0100 (2a52d39a2)
68help fixing #7105 - Christian Grothoff
69
70Thu, 25 Nov 2021 14:38:48 +0100 (63854ee52)
71add pk invariant check - Christian Grothoff
72
73Thu, 25 Nov 2021 14:03:04 +0100 (b9644ee30)
74fix event loop subscriptions on DB reconnect - Christian Grothoff
75
76Tue, 23 Nov 2021 12:31:18 +0100 (5cb62b557)
77RECLAIM: Fix bug that multiple attributes with the same name are added in CLI - Martin Schanzenbach
78
79Sun, 21 Nov 2021 16:14:29 +0100 (3dbb45893)
80Fix gnunet-namestore's URI import - Alessio Vanni
81
82Sun, 21 Nov 2021 17:25:50 +0100 (71d0c6696)
83update FR translation - Christian Grothoff
84
85Thu, 11 Nov 2021 00:56:30 +0100 (20ffa0aa5)
86Update configure.ac and a few macros used by it - Alessio Vanni
87
88Fri, 5 Nov 2021 22:52:53 +0100 (d744d49e1)
89Allow gnunet-qr to read codes from PNG pictures - Alessio Vanni
90
91Sun, 21 Nov 2021 17:25:50 +0100 (71d0c6696)
92update FR translation - Christian Grothoff
93
94Thu, 14 Oct 2021 21:22:40 +0200 (48ccb35c9)
95Improve gnunet-bcd and update logo used in generated cards - Alessio Vanni
96
97Sat, 20 Nov 2021 23:22:19 +0100 (1dcc14eca)
98update fr.po - Christian Grothoff
99
100Sat, 20 Nov 2021 02:27:34 -0500 (9f0a9deef)
101Convert AC_HELP_STRING to AS_HELP_STRING - Thien-Thi Nguyen
102
103Sat, 20 Nov 2021 01:41:02 -0500 (0390da9dd)
104Convert indirect ‘AC_CHECK_FUNCS’ call to direct one - Thien-Thi Nguyen
105
106Sat, 20 Nov 2021 01:31:24 -0500 (b04f9f7a7)
107Remove unnecessary double-quotes escaping - Thien-Thi Nguyen
108
109Sat, 20 Nov 2021 01:24:05 -0500 (73550ea6e)
110Remove m4-quoting from AC_CHECK_FUNCS arg - Thien-Thi Nguyen
3 111
4Mon, 30 Aug 2021 09:35:40 +0200 (9eb417e72) 112Wed, 17 Nov 2021 08:38:55 +0100 (c5a7ce5d2)
5exec' - Christian Grothoff 113subscribes are not reference counted by postgres, only subscribe/unsubscribe once per connection - Christian Grothoff
114
115Thu, 28 Oct 2021 13:32:17 +0200 (6a642f8f6)
116add logging for DB perf analysis - Christian Grothoff
117
118Mon, 25 Oct 2021 14:49:05 +0200 (1609d627e)
119changes to reflect the changes in testing_api_loop.c - t3sserakt
120
121Mon, 25 Oct 2021 11:23:26 +0200 (196b6bc57)
122debian: fix path again - Florian Dold
123
124Mon, 25 Oct 2021 10:40:33 +0200 (61dd07223)
125debian: fix libexec path - Florian Dold
126
127Tue, 19 Oct 2021 13:59:42 +0200 (789268e1b)
128kdf: zero out salt correctly - Florian Dold
129
130Mon, 11 Oct 2021 17:08:46 +0200 (d190d2383)
131fixed unset port forwarding variable bug in netjail script, fixed end cmd without shutdown bug, smaller fixes - t3sserakt
132
133Tue, 19 Oct 2021 13:55:28 +0200 (2e2abc61d)
134make KDF conform to RFC 5869 - Florian Dold
135
136Thu, 14 Oct 2021 16:39:24 +0200 (d64ac2698)
137removed versioned artefacts with v2 and v3. changes to reflect the changes in testing_api_loop.c - t3sserakt
138
139Tue, 12 Oct 2021 10:04:50 +0200 (8ac2a05b3)
140BUILD: Kill infiniband - Martin Schanzenbach
141
142Tue, 12 Oct 2021 08:34:21 +0200 (786210216)
143BUILD: Attempt fix longer file names in make dist - Martin Schanzenbach
144
145Mon, 11 Oct 2021 23:56:12 +0200 (113cd7e3d)
146BUILD: Remove --disable-mysql-version-check. #7033 - Martin Schanzenbach
147
148Mon, 11 Oct 2021 23:43:04 +0200 (4e7e81f4d)
149BUILD: Remove --disable-testing. Issue #7033 - Martin Schanzenbach
150
151Mon, 11 Oct 2021 23:28:17 +0200 (65554324a)
152BUILD: Remove W32 ifdef - Martin Schanzenbach
153
154Mon, 11 Oct 2021 23:01:22 +0200 (41e8c1e21)
155BUILD: Remove EXPENSIVE_TESTS (unused). Issue #7033 - Martin Schanzenbach
156
157Mon, 11 Oct 2021 17:08:46 +0200 (d190d2383)
158fixed unset port forwarding variable bug in netjail script, fixed end cmd without shutdown bug, smaller fixes - t3sserakt
159
160Mon, 11 Oct 2021 16:30:12 +0200 (62ca5edd0)
161BUILD: Remove SuperMUC code. Issue #7033 - Martin Schanzenbach
162
163Sat, 9 Oct 2021 14:20:18 +0200 (ae41c8bcd)
164BUILD: Add version from git tags - Martin Schanzenbach
165
166Wed, 6 Oct 2021 18:53:37 +0200 (6ef071b8c)
167fix #7029 - Christian Grothoff
168
169Mon, 4 Oct 2021 21:07:21 +0000 (e173017ed)
170Fix some typos in the handbook - Christian Grothoff
171
172Mon, 4 Oct 2021 22:30:21 +0200 (961685fab)
173add missing finish cmd - Christian Grothoff
174
175Thu, 23 Sep 2021 22:52:44 +0200 (1aa0d5f34)
176PQ: implementing #7014: support testing database version is current - Christian Grothoff
177
178Wed, 22 Sep 2021 20:32:39 +0200 (369f0a0e8)
179The differences between the contrib subdirectory in the git repository and the contrib subdirectory generated by make dist have grown really big. Please find attached another patch for updating the content of: - Christian Grothoff
180
181Wed, 22 Sep 2021 11:39:25 +0200 (81d925587)
182NSE: return NaN (see #7021) - Christian Grothoff
183
184Wed, 22 Sep 2021 11:35:46 +0200 (7bf37b7ea)
185NSE: return INF, not NaN (fixes #7021) - Christian Grothoff
186
187Thu, 16 Sep 2021 22:51:28 +0200 (fc9ca33bc)
188fix typos spotted by madmurphy - Christian Grothoff
189
190Fri, 10 Sep 2021 16:38:35 +0200 (46e07ed8e)
191Include "gettext.h" even when "platform.h" is unavailable - Alessio Vanni
192
193Sun, 5 Sep 2021 22:21:40 +0200 (3da9cbd62)
194BUILD: Remove FRAMEWORK_BUILD define - Martin Schanzenbach
195
196Sun, 5 Sep 2021 18:27:53 +0200 (f9f3cbe9f)
197make backend-check a gnunet-only gnunet-config option - Christian Grothoff
198
199Sun, 5 Sep 2021 16:58:55 +0200 (b4e034d9a)
200refactor gnunet-config to make preload hacks obsolete - Christian Grothoff
201
202Fri, 3 Sep 2021 18:21:28 +0200 (00c03c7bb)
203HANDBOOK: Add pointers to CI - Martin Schanzenbach
204
205Tue, 31 Aug 2021 16:09:03 +0200 (25d8a8a26)
206Flip the value of GNUNET_EXTRA_LOGGING given when it's undefined - Alessio Vanni
207
208Tue, 31 Aug 2021 15:54:43 +0200 (382fc8faa)
209gnunet.m4: add flag to disable debug messages - Alessio Vanni
210
211Tue, 27 Jul 2021 16:27:14 +0200 (649d10b27)
212Autoconf macro to detect GNUnet installations - Alessio Vanni
213
214Sat, 24 Jul 2021 16:15:10 +0200 (9bdfda437)
215gnunet-config manpage: Document the new flags - Alessio Vanni
216
217Fri, 23 Jul 2021 18:20:33 +0200 (fd1bcccb9)
218UTIL: Allow gnunet-config to output build config informations - Alessio Vanni
219
220Wed, 1 Sep 2021 10:28:09 +0200 (d51000320)
221UTIL: add fix for GNUnet directory permissions by madmurphy - Christian Grothoff
6 222
7Sat, 28 Aug 2021 21:50:06 +0200 (2994fa434) 223Sat, 28 Aug 2021 21:50:06 +0200 (2994fa434)
8improve error message and inherit stderr as suggested by Florian - Christian Grothoff 224UTIL: improve error message and inherit stderr as suggested by Florian - Christian Grothoff
9 225
10Sat, 28 Aug 2021 18:42:53 +0200 (c6528ac77) 226Sat, 28 Aug 2021 18:42:53 +0200 (c6528ac77)
11debian: systemd installation - Florian Dold 227debian: systemd installation - Florian Dold
diff --git a/Makefile.am b/Makefile.am
index 9191107d2..30cc02bc9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -73,3 +73,14 @@ if HAVE_AWK
73check-texinfo: 73check-texinfo:
74 @cd $(top_srcdir); find . -type f ! -path '*/.*' -name '*.texi' -print0 | xargs -0 ./contrib/scripts/check-texinfo.awk > $(srcdir)/texinfo_lint.log || true 74 @cd $(top_srcdir); find . -type f ! -path '*/.*' -name '*.texi' -print0 | xargs -0 ./contrib/scripts/check-texinfo.awk > $(srcdir)/texinfo_lint.log || true
75endif 75endif
76
77gana: gana-gns gana-gnunet-signatures
78
79gana-gns:
80 @cd $(top_srcdir)/contrib/gana/gnu-name-system-record-types; make; cp gnu_name_system_record_types.h ../../../src/include/
81 @cd $(top_srcdir)/contrib/gana/gnu-name-system-default-tlds; make; cp tlds.conf ../../../src/gns
82
83gana-gnunet-signatures:
84 @cd $(top_srcdir)/contrib/gana/gnunet-signatures; make; cp gnunet_signatures.h ../../../src/include
85
86
diff --git a/bootstrap b/bootstrap
index 984c56cb3..766eed237 100755
--- a/bootstrap
+++ b/bootstrap
@@ -40,8 +40,8 @@ check_uncrustify()
40{ 40{
41 if existence uncrustify; then 41 if existence uncrustify; then
42 echo "Installing uncrustify hook and configuration" 42 echo "Installing uncrustify hook and configuration"
43 ln -fs contrib/build-common/conf/uncrustify.cfg uncrustify.cfg 2> /dev/null 43 ln -fs contrib/conf/uncrustify.cfg uncrustify.cfg 2> /dev/null
44 ln -fs contrib/build-common/conf/uncrustify_precommit .git/hooks/pre-commit 2> /dev/null 44 ln -fs contrib/conf/uncrustify_precommit .git/hooks/pre-commit 2> /dev/null
45 else 45 else
46 echo "Uncrustify not detected, hook not installed." 46 echo "Uncrustify not detected, hook not installed."
47 echo "Please install uncrustify if you plan on doing development" 47 echo "Please install uncrustify if you plan on doing development"
@@ -65,7 +65,7 @@ check_yapf()
65 existence yapf3.9 || \ 65 existence yapf3.9 || \
66 existence yapf4.0; then 66 existence yapf4.0; then
67 echo "Installing yapf symlink" 67 echo "Installing yapf symlink"
68 ln -fs contrib/build-common/conf/.style.yapf .style.yapf 2> /dev/null 68 ln -fs contrib/conf/.style.yapf .style.yapf 2> /dev/null
69 else 69 else
70 echo "yapf not detected, please install yapf if you plan on contributing python code" 70 echo "yapf not detected, please install yapf if you plan on contributing python code"
71 fi 71 fi
@@ -98,21 +98,43 @@ submodules()
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 || exit 1 100 git submodule update --init || exit 1
101 git submodule update --recursive || exit 1 101 git submodule update --remote --recursive || exit 1
102 git submodule sync || exit 1 102 git submodule sync || exit 1
103 fi 103 fi
104} 104}
105 105
106init_buildcommon_include() 106gana_update()
107{ 107{
108 cp contrib/build-common/Makefile.inc contrib/Makefile.inc || exit 1 108 if existence recfmt; then
109 cwd=$PWD
110 cd contrib/gana || exit 1
111 # GNS
112 cd gnu-name-system-record-types && \
113 make && \
114 cp gnu_name_system_record_types.h ../../../src/include/ && \
115 make clean
116 cd ../gnu-name-system-default-tlds && \
117 make && \
118 cp tlds.conf ../../../src/gns && \
119 make clean
120
121 # Signatures
122 cd ../gnunet-signatures && \
123 make && \
124 cp gnunet_signatures.h ../../../src/include && \
125 make clean
126 cd $cwd
127 else
128 echo "ERROR: No recutils found! Unable to generate recent GANA headers and configs."
129 exit 1
130 fi
109} 131}
110 132
111main() 133main()
112{ 134{
113 cleanup 135 cleanup
114 submodules 136 submodules
115 init_buildcommon_include 137 gana_update
116 check_uncrustify 138 check_uncrustify
117 check_yapf 139 check_yapf
118 check_libtool 140 check_libtool
diff --git a/configure.ac b/configure.ac
index 1e5ba403f..feee06f9f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1232,9 +1232,11 @@ AC_SUBST([JAVAPORT])
1232AC_ARG_ENABLE([experimental], 1232AC_ARG_ENABLE([experimental],
1233 [AS_HELP_STRING([--enable-experimental], 1233 [AS_HELP_STRING([--enable-experimental],
1234 [enable experimental code paths (default is no)])], 1234 [enable experimental code paths (default is no)])],
1235 [enable_experimental="${enableval}"] 1235 [AS_IF([test "x$enableval" = "xno"],
1236 [enable_experimental="no"]) 1236 [enable_experimental=0],
1237AM_CONDITIONAL([HAVE_EXPERIMENTAL], [test "x$enable_experimental" = "xyes"]) 1237 [enable_experimental=1])],
1238 [enable_experimental=0])
1239AM_CONDITIONAL([HAVE_EXPERIMENTAL], [test "x$enable_experimental" = "x1"])
1238 1240
1239# check if malicious code should be compiled (for testing) 1241# check if malicious code should be compiled (for testing)
1240AC_ARG_ENABLE([malicious], 1242AC_ARG_ENABLE([malicious],
@@ -1437,6 +1439,7 @@ src/zonemaster/Makefile
1437src/zonemaster/zonemaster.conf 1439src/zonemaster/zonemaster.conf
1438src/rest/Makefile 1440src/rest/Makefile
1439src/abd/Makefile 1441src/abd/Makefile
1442src/abd/abd.conf
1440src/abe/Makefile 1443src/abe/Makefile
1441src/reclaim/Makefile 1444src/reclaim/Makefile
1442src/messenger/Makefile 1445src/messenger/Makefile
@@ -1489,13 +1492,13 @@ AS_IF([test "x$enable_java_ports" = "xyes"],
1489 [java_msg="no"]) 1492 [java_msg="no"])
1490 1493
1491# experimental code is enabled 1494# experimental code is enabled
1492AS_IF([test "x$enable_experimental" = "xyes"], 1495AS_IF([test "x$enable_experimental" = "x1"],
1493 [experimental_msg="yes"], 1496 [experimental_msg="yes"],
1494 [experimental_msg="no"]) 1497 [experimental_msg="no"])
1495 1498
1496# experimental code for transport is enabled 1499# experimental code for transport is enabled
1497transport_msg="tcp udp unix http" 1500transport_msg="tcp udp unix http"
1498AS_IF([test "x$build_target" = "xlinux" && test "x$enable_experimental" = "xyes"], 1501AS_IF([test "x$build_target" = "xlinux" && test "x$enable_experimental" = "x1"],
1499 [transport_msg="tcp udp unix http wlan"]) 1502 [transport_msg="tcp udp unix http wlan"])
1500 1503
1501# libidn version 1504# libidn version
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index e0370d3c9..4e7928c7e 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -32,8 +32,7 @@ dist_pkgdata_DATA = \
32 netjail/netjail_exec.sh \ 32 netjail/netjail_exec.sh \
33 netjail/netjail_start.sh \ 33 netjail/netjail_start.sh \
34 netjail/netjail_stop.sh \ 34 netjail/netjail_stop.sh \
35 netjail/topo.sh \ 35 netjail/topo.sh
36 $(BUILDCOMMON_SHLIB_FILES)
37 36
38INITD_FILES = \ 37INITD_FILES = \
39 services/systemd/gnunet-user.service \ 38 services/systemd/gnunet-user.service \
@@ -221,8 +220,7 @@ EXTRA_DIST = \
221 patches/lrn-indent.diff \ 220 patches/lrn-indent.diff \
222 test_gnunet_prefix.c \ 221 test_gnunet_prefix.c \
223 $(PACKAGES_FILES) \ 222 $(PACKAGES_FILES) \
224 $(INITD_FILES) \ 223 $(INITD_FILES)
225 $(BUILD_COMMON_FILES)
226 224
227check_PROGRAMS = \ 225check_PROGRAMS = \
228 test_gnunet_prefix 226 test_gnunet_prefix
diff --git a/contrib/build-common b/contrib/build-common
deleted file mode 160000
Subproject 1915a74bbb4cd2ae9bc541a382dfebc37064a2f
diff --git a/contrib/conf/uncrustify.cfg b/contrib/conf/uncrustify.cfg
index 8c9df2c43..6ced05d7a 100644
--- a/contrib/conf/uncrustify.cfg
+++ b/contrib/conf/uncrustify.cfg
@@ -4,7 +4,7 @@ output_tab_size = 2
4indent_columns = 2 4indent_columns = 2
5indent_with_tabs = 0 5indent_with_tabs = 0
6indent_case_brace = 2 6indent_case_brace = 2
7indent_label=-16 7indent_label=0
8 8
9code_width=80 9code_width=80
10#cmd_width=80 10#cmd_width=80
@@ -49,12 +49,8 @@ nl_assign_brace=remove
49 49
50# No extra newlines that cause noisy diffs 50# No extra newlines that cause noisy diffs
51nl_start_of_file=remove 51nl_start_of_file=remove
52nl_after_func_proto = 2
53nl_after_func_body = 3
54# If there's no new line, it's not a text file! 52# If there's no new line, it's not a text file!
55nl_end_of_file=add 53nl_end_of_file=add
56nl_max_blank_in_func = 3
57nl_max = 3
58 54
59sp_inside_paren = remove 55sp_inside_paren = remove
60 56
@@ -73,7 +69,6 @@ sp_between_ptr_star = remove
73sp_before_sparen = add 69sp_before_sparen = add
74 70
75sp_inside_fparen = remove 71sp_inside_fparen = remove
76sp_inside_sparen = remove
77 72
78# add space before function call and decl: "foo (x)" 73# add space before function call and decl: "foo (x)"
79sp_func_call_paren = add 74sp_func_call_paren = add
@@ -81,15 +76,3 @@ sp_func_proto_paren = add
81sp_func_proto_paren_empty = add 76sp_func_proto_paren_empty = add
82sp_func_def_paren = add 77sp_func_def_paren = add
83sp_func_def_paren_empty = add 78sp_func_def_paren_empty = add
84
85# We'd want it for "if ( (foo) || (bar) )", but not for "if (m())",
86# so as uncrustify doesn't give exactly what we want => ignore
87sp_paren_paren = ignore
88sp_inside_paren = remove
89sp_bool = force
90
91nl_func_type_name = force
92#nl_branch_else = add
93nl_else_brace = add
94nl_elseif_brace = add
95nl_for_brace = add
diff --git a/contrib/conf/uncrustify_precommit b/contrib/conf/uncrustify_precommit
index 24873330f..fd29998c3 100755
--- a/contrib/conf/uncrustify_precommit
+++ b/contrib/conf/uncrustify_precommit
@@ -30,6 +30,6 @@ if [ $RET = 1 ];
30then 30then
31 echo "Run" 31 echo "Run"
32 echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}" 32 echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}"
33 echo "before committing." 33 echo "before commiting."
34fi 34fi
35exit $RET 35exit $RET
diff --git a/contrib/gana b/contrib/gana
new file mode 160000
Subproject 9b8a787580307cea5a38359c485d521cd8ece82
diff --git a/doc/handbook/chapters/developer.texi b/doc/handbook/chapters/developer.texi
index a8f9d1ec3..e3ff20dcd 100644
--- a/doc/handbook/chapters/developer.texi
+++ b/doc/handbook/chapters/developer.texi
@@ -96,7 +96,7 @@ introduction, each of the GNUnet subsystems (directories in the
96addition to this documentation, GNUnet developers should be aware of the 96addition to this documentation, GNUnet developers should be aware of the
97services available on the GNUnet server to them. 97services available on the GNUnet server to them.
98 98
99New developers can have a look a the @uref{https://docs.gnunet.org/tutorial/gnunet-tutorial.html, GNUnet C tutorial}. 99New developers can have a look a the @uref{https://docs.gnunet.org/tutorial/tutorial.html, GNUnet C tutorial}.
100 100
101@c ** FIXME: Link to files in source, not online. 101@c ** FIXME: Link to files in source, not online.
102@c ** FIXME: Where is the Java tutorial? 102@c ** FIXME: Where is the Java tutorial?
diff --git a/doc/man/gnunet-identity.1 b/doc/man/gnunet-identity.1
index 599d3b269..835dfb225 100644
--- a/doc/man/gnunet-identity.1
+++ b/doc/man/gnunet-identity.1
@@ -26,7 +26,7 @@
26.Os 26.Os
27.Sh NAME 27.Sh NAME
28.Nm gnunet-identity 28.Nm gnunet-identity
29.Nd create, delete or list egos 29.Nd maintain (create, delete or list) or perform actions with egos
30.Sh SYNOPSIS 30.Sh SYNOPSIS
31.Nm 31.Nm
32.Op Fl C Ar NAME | Fl -create= Ns Ar NAME 32.Op Fl C Ar NAME | Fl -create= Ns Ar NAME
@@ -34,11 +34,14 @@
34.Op Fl d | -display 34.Op Fl d | -display
35.Op Fl e Ar NAME | Fl -ego= Ns Ar NAME 35.Op Fl e Ar NAME | Fl -ego= Ns Ar NAME
36.Op Fl h | -help 36.Op Fl h | -help
37.Op Fl k Ar PUBLIC_KEY | Fl -key= Ns Ar PUBLIC_KEY
37.Op Fl m | -monitor 38.Op Fl m | -monitor
38.Op Fl p | -private-keys 39.Op Fl p | -private-keys
39.Op Fl q | -quiet 40.Op Fl q | -quiet
41.Op Fl R Ar MESSAGE | Fl -read= Ns Ar MESSAGE
40.Op Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM 42.Op Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM
41.Op Fl V | -verbose 43.Op Fl V | -verbose
44.Op Fl W Ar MESSAGE | Fl -write= Ns Ar MESSAGE
42.Op Fl X | -eddsa 45.Op Fl X | -eddsa
43.Sh DESCRIPTION 46.Sh DESCRIPTION
44.Nm 47.Nm
@@ -51,6 +54,9 @@ created locally, to create new egos, and to delete
51existing egos (the namespace will continue to exist, but it will 54existing egos (the namespace will continue to exist, but it will
52be impossible to add additional data to it). 55be impossible to add additional data to it).
53.Pp 56.Pp
57In addition, it is possible to encrypt and decrypt messages (arbitrary strings)
58using a given public key (for encryption) or ego (for decryption).
59.Pp
54Creating a new ego requires using the 60Creating a new ego requires using the
55.Fl C 61.Fl C
56option together with an identifier (name) that is to be used for 62option together with an identifier (name) that is to be used for
@@ -72,6 +78,11 @@ Perform "set" operation with the respective ego or restrict "display"
72operation to the respective ego. 78operation to the respective ego.
73.It Fl h | -help 79.It Fl h | -help
74Print the help page. 80Print the help page.
81.It Fl k Ar PUBLIC_KEY | Fl -key= Ns Ar PUBLIC_KEY
82The public key to use for a message recipient. Use together with
83.Fl W .
84The recipient can obtain the desired ego's public key using the "display"
85operation.
75.It Fl m | -monitor 86.It Fl m | -monitor
76Run in monitor mode, listing all ouf our egos until CTRL-C is pressed. 87Run in monitor mode, listing all ouf our egos until CTRL-C is pressed.
77Each ego is listed together with a unique pointer value; if 88Each ego is listed together with a unique pointer value; if
@@ -83,6 +94,12 @@ keys. The second column shows the public key, the third column shows the
83private key. 94private key.
84.It Fl q | -quiet 95.It Fl q | -quiet
85Be quiet, in particular outputs only the public key when listing egos. 96Be quiet, in particular outputs only the public key when listing egos.
97.It Fl R Ar MESSAGE | Fl -read= Ns Ar MESSAGE
98Decrypt (read) a message using the respective ego private key. Use together with
99.Fl e .
100The message consists of an ephemeral key and the ciphertext, separated by a dot.
101Such messages can be created with
102.Fl W .
86.It Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM 103.It Fl s Ar SUBSYSTEM | Fl -set= Ns Ar SUBSYSTEM
87Perform "set" operation for the specified 104Perform "set" operation for the specified
88.Ar SUBSYSTEM 105.Ar SUBSYSTEM
@@ -95,6 +112,13 @@ This will fail if
95does not yet exist. 112does not yet exist.
96.It Fl V | -verbose 113.It Fl V | -verbose
97Be verbose, in particular outputs the public key of freshly created egos. 114Be verbose, in particular outputs the public key of freshly created egos.
115.It Fl W Ar MESSAGE | Fl -write= Ns Ar MESSAGE
116Encrypt (write) the given message for the identity given with
117.Fl k .
118The output contains an ephemeral message public key and the message separated
119by a dot. The entire line needs to be transferred to the recipient, who can use
120.Fl R
121to decrypt the message.
98.It Fl X | -eddsa 122.It Fl X | -eddsa
99Use EdDSA instead of ECDSA. 123Use EdDSA instead of ECDSA.
100.El 124.El
diff --git a/doc/man/produce_html.sh.in b/doc/man/produce_html.sh.in
index 8680c0106..e9581622f 100755
--- a/doc/man/produce_html.sh.in
+++ b/doc/man/produce_html.sh.in
@@ -1,13 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2 2
3if test -e @PKGDATADIRECTORY@/existence.sh 3if command -v mandoc >/dev/null 2>&1;
4then
5 . @PKGDATADIRECTORY@/existence.sh
6else
7 . $dir/../../contrib/build-common/sh/lib.sh/existence.sh
8fi
9
10if existence mandoc;
11then 4then
12 for f in `find . -name \*\.[1-9]`; 5 for f in `find . -name \*\.[1-9]`;
13 do 6 do
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 60f758590..b456f2ad3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -523,6 +523,7 @@ src/util/container_multishortmap.c
523src/util/container_multiuuidmap.c 523src/util/container_multiuuidmap.c
524src/util/crypto_abe.c 524src/util/crypto_abe.c
525src/util/crypto_crc.c 525src/util/crypto_crc.c
526src/util/crypto_cs.c
526src/util/crypto_ecc.c 527src/util/crypto_ecc.c
527src/util/crypto_ecc_dlog.c 528src/util/crypto_ecc_dlog.c
528src/util/crypto_ecc_gnsrecord.c 529src/util/crypto_ecc_gnsrecord.c
diff --git a/src/abd/Makefile.am b/src/abd/Makefile.am
index 304469e22..ae9248b43 100644
--- a/src/abd/Makefile.am
+++ b/src/abd/Makefile.am
@@ -3,7 +3,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
3 3
4EXTRA_DIST = \ 4EXTRA_DIST = \
5 test_abd_defaults.conf \ 5 test_abd_defaults.conf \
6 test_abd_lookup.conf 6 test_abd_lookup.conf \
7 $(check_SCRIPTS) \
8 $(pkgdata_DATA)
7 9
8 10
9if USE_COVERAGE 11if USE_COVERAGE
@@ -51,6 +53,7 @@ libgnunet_plugin_gnsrecord_abd_la_SOURCES = \
51libgnunet_plugin_gnsrecord_abd_la_LIBADD = \ 53libgnunet_plugin_gnsrecord_abd_la_LIBADD = \
52 libgnunetabd.la \ 54 libgnunetabd.la \
53 $(top_builddir)/src/util/libgnunetutil.la \ 55 $(top_builddir)/src/util/libgnunetutil.la \
56 $(top_builddir)/src/identity/libgnunetidentity.la \
54 $(LTLIBINTL) 57 $(LTLIBINTL)
55libgnunet_plugin_gnsrecord_abd_la_LDFLAGS = \ 58libgnunet_plugin_gnsrecord_abd_la_LDFLAGS = \
56 $(GN_PLUGIN_LDFLAGS) 59 $(GN_PLUGIN_LDFLAGS)
@@ -64,6 +67,7 @@ gnunet_service_abd_LDADD = \
64 $(top_builddir)/src/util/libgnunetutil.la \ 67 $(top_builddir)/src/util/libgnunetutil.la \
65 $(top_builddir)/src/gns/libgnunetgns.la \ 68 $(top_builddir)/src/gns/libgnunetgns.la \
66 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 69 $(top_builddir)/src/namestore/libgnunetnamestore.la \
70 $(top_builddir)/src/identity/libgnunetidentity.la \
67 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 71 $(top_builddir)/src/statistics/libgnunetstatistics.la \
68 $(GN_LIBINTL) 72 $(GN_LIBINTL)
69 73
diff --git a/src/abd/abd_serialization.c b/src/abd/abd_serialization.c
index 4c219d791..2ed24ff2f 100644
--- a/src/abd/abd_serialization.c
+++ b/src/abd/abd_serialization.c
@@ -191,8 +191,8 @@ GNUNET_ABD_delegates_serialize (
191 off = 0; 191 off = 0;
192 for (i = 0; i < c_count; i++) 192 for (i = 0; i < c_count; i++)
193 { 193 {
194 // c_rec.subject_attribute_len = htonl ((uint32_t) cd[i].subject_attribute_len); 194 c_rec.subject_attribute_len = htonl (cd[i].subject_attribute_len);
195 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len); 195 c_rec.issuer_attribute_len = htonl (cd[i].issuer_attribute_len);
196 c_rec.issuer_key = cd[i].issuer_key; 196 c_rec.issuer_key = cd[i].issuer_key;
197 c_rec.subject_key = cd[i].subject_key; 197 c_rec.subject_key = cd[i].subject_key;
198 c_rec.signature = cd[i].signature; 198 c_rec.signature = cd[i].signature;
diff --git a/src/abd/delegate_misc.c b/src/abd/delegate_misc.c
index d67b40088..0c5520d52 100644
--- a/src/abd/delegate_misc.c
+++ b/src/abd/delegate_misc.c
@@ -143,10 +143,20 @@ GNUNET_ABD_delegate_from_string (const char *s)
143 } 143 }
144 tmp_str[attr_len - 1] = '\0'; 144 tmp_str[attr_len - 1] = '\0';
145 145
146 GNUNET_IDENTITY_public_key_from_string (subject_pkey, 146 if (GNUNET_SYSERR ==
147 &dele->subject_key); 147 GNUNET_IDENTITY_public_key_from_string (subject_pkey,
148 GNUNET_IDENTITY_public_key_from_string (issuer_pkey, 148 &dele->subject_key))
149 &dele->issuer_key); 149 {
150 GNUNET_free (dele);
151 return NULL;
152 }
153 if (GNUNET_SYSERR ==
154 GNUNET_IDENTITY_public_key_from_string (issuer_pkey,
155 &dele->issuer_key))
156 {
157 GNUNET_free (dele);
158 return NULL;
159 }
150 GNUNET_assert (sizeof (struct GNUNET_IDENTITY_Signature) == 160 GNUNET_assert (sizeof (struct GNUNET_IDENTITY_Signature) ==
151 GNUNET_STRINGS_base64_decode (signature, 161 GNUNET_STRINGS_base64_decode (signature,
152 strlen (signature), 162 strlen (signature),
diff --git a/src/abd/gnunet-abd.c b/src/abd/gnunet-abd.c
index 17671273c..cf3733abd 100644
--- a/src/abd/gnunet-abd.c
+++ b/src/abd/gnunet-abd.c
@@ -544,6 +544,10 @@ static void
544store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) 544store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
545{ 545{
546 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 546 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
547 struct GNUNET_ABD_Delegate *cred;
548 struct GNUNET_IDENTITY_PublicKey zone_pubkey;
549 char *subject_pubkey_str;
550 char *zone_pubkey_str;
547 551
548 el = NULL; 552 el = NULL;
549 553
@@ -562,17 +566,23 @@ store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
562 if (GNUNET_GNSRECORD_TYPE_DELEGATE == type) 566 if (GNUNET_GNSRECORD_TYPE_DELEGATE == type)
563 { 567 {
564 // Parse import 568 // Parse import
565 struct GNUNET_ABD_Delegate *cred;
566 cred = GNUNET_ABD_delegate_from_string (import); 569 cred = GNUNET_ABD_delegate_from_string (import);
567 570
571 if (NULL == cred)
572 {
573 fprintf (stderr,
574 "%s is not a valid credential\n", import);
575 GNUNET_SCHEDULER_shutdown();
576 return;
577 }
578
568 // Get import subject public key string 579 // Get import subject public key string
569 char *subject_pubkey_str = 580 subject_pubkey_str =
570 GNUNET_IDENTITY_public_key_to_string (&cred->subject_key); 581 GNUNET_IDENTITY_public_key_to_string (&cred->subject_key);
571 582
572 // Get zone public key string 583 // Get zone public key string
573 struct GNUNET_IDENTITY_PublicKey zone_pubkey;
574 GNUNET_IDENTITY_ego_get_public_key (ego, &zone_pubkey); 584 GNUNET_IDENTITY_ego_get_public_key (ego, &zone_pubkey);
575 char *zone_pubkey_str = 585 zone_pubkey_str =
576 GNUNET_IDENTITY_public_key_to_string (&zone_pubkey); 586 GNUNET_IDENTITY_public_key_to_string (&zone_pubkey);
577 587
578 // Check if the subject key in the signed import matches the zone's key it is issued to 588 // Check if the subject key in the signed import matches the zone's key it is issued to
@@ -580,6 +590,7 @@ store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
580 { 590 {
581 fprintf (stderr, 591 fprintf (stderr,
582 "Import signed delegate does not match this ego's public key.\n"); 592 "Import signed delegate does not match this ego's public key.\n");
593 GNUNET_free (cred);
583 GNUNET_SCHEDULER_shutdown (); 594 GNUNET_SCHEDULER_shutdown ();
584 return; 595 return;
585 } 596 }
@@ -691,6 +702,13 @@ sign_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
691 // work on keys 702 // work on keys
692 privkey = GNUNET_IDENTITY_ego_get_private_key (ego); 703 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
693 704
705 if (NULL == subject_pubkey_str)
706 {
707 fprintf (stderr,
708 "Subject pubkey not given\n");
709 GNUNET_SCHEDULER_shutdown ();
710 return;
711 }
694 if (GNUNET_OK != 712 if (GNUNET_OK !=
695 GNUNET_IDENTITY_public_key_from_string (subject_pubkey_str, 713 GNUNET_IDENTITY_public_key_from_string (subject_pubkey_str,
696 &subject_pkey)) 714 &subject_pkey))
diff --git a/src/abd/gnunet-service-abd.c b/src/abd/gnunet-service-abd.c
index 3f9f2f924..407d5bdc3 100644
--- a/src/abd/gnunet-service-abd.c
+++ b/src/abd/gnunet-service-abd.c
@@ -512,6 +512,8 @@ send_intermediate_response (struct VerifyRequestHandle *vrh, struct
512 size, 512 size,
513 (char *) &rmsg[1])); 513 (char *) &rmsg[1]));
514 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env); 514 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
515
516 GNUNET_free (dd);
515} 517}
516 518
517 519
@@ -740,12 +742,13 @@ forward_resolution (void *cls,
740 uint32_t rd_count, 742 uint32_t rd_count,
741 const struct GNUNET_GNSRECORD_Data *rd) 743 const struct GNUNET_GNSRECORD_Data *rd)
742{ 744{
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
744
745 struct VerifyRequestHandle *vrh; 745 struct VerifyRequestHandle *vrh;
746 struct DelegationSetQueueEntry *current_set; 746 struct DelegationSetQueueEntry *current_set;
747 struct DelegationSetQueueEntry *ds_entry; 747 struct DelegationSetQueueEntry *ds_entry;
748 struct DelegationQueueEntry *dq_entry; 748 struct DelegationQueueEntry *dq_entry;
749 struct GNUNET_ABD_Delegate *del;
750
751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
749 752
750 current_set = cls; 753 current_set = cls;
751 // set handle to NULL (as el = NULL) 754 // set handle to NULL (as el = NULL)
@@ -760,9 +763,11 @@ forward_resolution (void *cls,
760 continue; 763 continue;
761 764
762 // Start deserialize into Delegate 765 // Start deserialize into Delegate
763 struct GNUNET_ABD_Delegate *del;
764 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size); 766 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
765 767
768 if (NULL == del)
769 continue;
770
766 // Start: Create DQ Entry 771 // Start: Create DQ Entry
767 dq_entry = GNUNET_new (struct DelegationQueueEntry); 772 dq_entry = GNUNET_new (struct DelegationQueueEntry);
768 // AND delegations are not possible, only 1 solution 773 // AND delegations are not possible, only 1 solution
@@ -834,6 +839,7 @@ forward_resolution (void *cls,
834 GNUNET_IDENTITY_public_key_to_string ( 839 GNUNET_IDENTITY_public_key_to_string (
835 &del->subject_key), 840 &del->subject_key),
836 del->subject_attribute); 841 del->subject_attribute);
842 GNUNET_free (del);
837 continue; 843 continue;
838 } 844 }
839 else 845 else
@@ -910,6 +916,7 @@ forward_resolution (void *cls,
910 } 916 }
911 917
912 send_lookup_response (vrh); 918 send_lookup_response (vrh);
919 GNUNET_free (del);
913 return; 920 return;
914 } 921 }
915 } 922 }
@@ -936,6 +943,7 @@ forward_resolution (void *cls,
936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
937 "Forward: Found match with above!\n"); 944 "Forward: Found match with above!\n");
938 945
946 GNUNET_free (del);
939 // one node on the path still needs solutions: return 947 // one node on the path still needs solutions: return
940 if (GNUNET_NO == 948 if (GNUNET_NO ==
941 handle_bidirectional_match (ds_entry, del_entry, vrh)) 949 handle_bidirectional_match (ds_entry, del_entry, vrh))
@@ -965,6 +973,7 @@ forward_resolution (void *cls,
965 GNUNET_GNS_LO_DEFAULT, 973 GNUNET_GNS_LO_DEFAULT,
966 &forward_resolution, 974 &forward_resolution,
967 ds_entry); 975 ds_entry);
976 GNUNET_free (del);
968 } 977 }
969 978
970 if (0 == vrh->pending_lookups) 979 if (0 == vrh->pending_lookups)
@@ -1586,34 +1595,29 @@ handle_delegate_collection_cb (void *cls,
1586 const struct GNUNET_GNSRECORD_Data *rd) 1595 const struct GNUNET_GNSRECORD_Data *rd)
1587{ 1596{
1588 struct VerifyRequestHandle *vrh = cls; 1597 struct VerifyRequestHandle *vrh = cls;
1589 struct GNUNET_ABD_Delegate *del;
1590 struct DelegateRecordEntry *del_entry; 1598 struct DelegateRecordEntry *del_entry;
1591 int cred_record_count;
1592 cred_record_count = 0;
1593 vrh->dele_qe = NULL; 1599 vrh->dele_qe = NULL;
1594 1600
1595 for (uint32_t i = 0; i < rd_count; i++) 1601 for (uint32_t i = 0; i < rd_count; i++)
1596 { 1602 {
1597 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type) 1603 if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
1598 continue; 1604 continue;
1599 cred_record_count++;
1600 del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
1601 if (NULL == del)
1602 {
1603 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
1604 continue;
1605 }
1606 // only add the entries that are explicitly marked as private 1605 // only add the entries that are explicitly marked as private
1607 // and therefore symbolize the end of a chain 1606 // and therefore symbolize the end of a chain
1608 if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE) 1607 if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
1608 continue;
1609 del_entry = GNUNET_new (struct DelegateRecordEntry);
1610 del_entry->delegate = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
1611 if (NULL == del_entry->delegate)
1609 { 1612 {
1610 del_entry = GNUNET_new (struct DelegateRecordEntry); 1613 GNUNET_free (del_entry);
1611 del_entry->delegate = del; 1614 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
1612 GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head, 1615 continue;
1613 vrh->del_chain_tail,
1614 del_entry);
1615 vrh->del_chain_size++;
1616 } 1616 }
1617 GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
1618 vrh->del_chain_tail,
1619 del_entry);
1620 vrh->del_chain_size++;
1617 } 1621 }
1618 1622
1619 delegate_collection_finished (vrh); 1623 delegate_collection_finished (vrh);
diff --git a/src/abd/plugin_gnsrecord_abd.c b/src/abd/plugin_gnsrecord_abd.c
index 24cf6a3aa..7b2f4af5b 100644
--- a/src/abd/plugin_gnsrecord_abd.c
+++ b/src/abd/plugin_gnsrecord_abd.c
@@ -207,8 +207,13 @@ abd_string_to_value (void *cls,
207 matches = sscanf (token, "%s %s", subject_pkey, attr_str); 207 matches = sscanf (token, "%s %s", subject_pkey, attr_str);
208 208
209 // sets the public key for the set entry 209 // sets the public key for the set entry
210 GNUNET_IDENTITY_public_key_from_string (subject_pkey, 210 if (GNUNET_SYSERR ==
211 &set[i].subject_key); 211 GNUNET_IDENTITY_public_key_from_string (subject_pkey,
212 &set[i].subject_key))
213 {
214 GNUNET_free (tmp_str);
215 return GNUNET_SYSERR;
216 }
212 217
213 // If not just key, also set subject attribute (Not A.a <- B but A.a <- B.b) 218 // If not just key, also set subject attribute (Not A.a <- B but A.a <- B.b)
214 if (2 == matches) 219 if (2 == matches)
@@ -252,7 +257,7 @@ abd_string_to_value (void *cls,
252 cred = GNUNET_ABD_delegate_from_string (s); 257 cred = GNUNET_ABD_delegate_from_string (s);
253 258
254 *data_size = GNUNET_ABD_delegate_serialize (cred, (char **) data); 259 *data_size = GNUNET_ABD_delegate_serialize (cred, (char **) data);
255 260 GNUNET_free (cred);
256 return GNUNET_OK; 261 return GNUNET_OK;
257 } 262 }
258 default: 263 default:
diff --git a/src/block/block.c b/src/block/block.c
index 975c0f747..5824946f7 100644
--- a/src/block/block.c
+++ b/src/block/block.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2010, 2017 GNUnet e.V. 3 Copyright (C) 2010, 2017, 2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -70,13 +70,6 @@ struct GNUNET_BLOCK_Context
70}; 70};
71 71
72 72
73/**
74 * Mingle hash with the mingle_number to produce different bits.
75 *
76 * @param in original hash code
77 * @param mingle_number number for hash permutation
78 * @param hc where to store the result.
79 */
80void 73void
81GNUNET_BLOCK_mingle_hash (const struct GNUNET_HashCode *in, 74GNUNET_BLOCK_mingle_hash (const struct GNUNET_HashCode *in,
82 uint32_t mingle_number, 75 uint32_t mingle_number,
@@ -121,12 +114,6 @@ add_plugin (void *cls,
121} 114}
122 115
123 116
124/**
125 * Create a block context. Loads the block plugins.
126 *
127 * @param cfg configuration to use
128 * @return NULL on error
129 */
130struct GNUNET_BLOCK_Context * 117struct GNUNET_BLOCK_Context *
131GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg) 118GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
132{ 119{
@@ -143,11 +130,6 @@ GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
143} 130}
144 131
145 132
146/**
147 * Destroy the block context.
148 *
149 * @param ctx context to destroy
150 */
151void 133void
152GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx) 134GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
153{ 135{
@@ -167,17 +149,7 @@ GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
167} 149}
168 150
169 151
170/** 152enum GNUNET_GenericReturnValue
171 * Serialize state of a block group.
172 *
173 * @param bg group to serialize
174 * @param[out] nonce set to the nonce of the @a bg
175 * @param[out] raw_data set to the serialized state
176 * @param[out] raw_data_size set to the number of bytes in @a raw_data
177 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
178 * supported, #GNUNET_SYSERR on error
179 */
180int
181GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg, 153GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
182 uint32_t *nonce, 154 uint32_t *nonce,
183 void **raw_data, 155 void **raw_data,
@@ -197,11 +169,6 @@ GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
197} 169}
198 170
199 171
200/**
201 * Destroy resources used by a block group.
202 *
203 * @param bg group to destroy, NULL is allowed
204 */
205void 172void
206GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg) 173GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg)
207{ 174{
@@ -211,23 +178,11 @@ GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg)
211} 178}
212 179
213 180
214/** 181enum GNUNET_GenericReturnValue
215 * Try merging two block groups. Afterwards, @a bg1 should remain
216 * valid and contain the rules from both @a bg1 and @bg2, and
217 * @a bg2 should be destroyed (as part of this call). The latter
218 * should happen even if merging is not supported.
219 *
220 * @param[in,out] bg1 first group to merge, is updated
221 * @param bg2 second group to merge, is destroyed
222 * @return #GNUNET_OK on success,
223 * #GNUNET_NO if merge failed due to different nonce
224 * #GNUNET_SYSERR if merging is not supported
225 */
226int
227GNUNET_BLOCK_group_merge (struct GNUNET_BLOCK_Group *bg1, 182GNUNET_BLOCK_group_merge (struct GNUNET_BLOCK_Group *bg1,
228 struct GNUNET_BLOCK_Group *bg2) 183 struct GNUNET_BLOCK_Group *bg2)
229{ 184{
230 int ret; 185 enum GNUNET_GenericReturnValue ret;
231 186
232 if (NULL == bg2) 187 if (NULL == bg2)
233 return GNUNET_OK; 188 return GNUNET_OK;
@@ -257,35 +212,18 @@ static struct GNUNET_BLOCK_PluginFunctions *
257find_plugin (struct GNUNET_BLOCK_Context *ctx, 212find_plugin (struct GNUNET_BLOCK_Context *ctx,
258 enum GNUNET_BLOCK_Type type) 213 enum GNUNET_BLOCK_Type type)
259{ 214{
260 struct Plugin *plugin;
261 unsigned int j;
262
263 for (unsigned i = 0; i < ctx->num_plugins; i++) 215 for (unsigned i = 0; i < ctx->num_plugins; i++)
264 { 216 {
265 plugin = ctx->plugins[i]; 217 struct Plugin *plugin = ctx->plugins[i];
266 j = 0; 218
267 while (0 != (plugin->api->types[j])) 219 for (unsigned int j = 0; 0 != plugin->api->types[j]; j++)
268 {
269 if (type == plugin->api->types[j]) 220 if (type == plugin->api->types[j])
270 return plugin->api; 221 return plugin->api;
271 j++;
272 }
273 } 222 }
274 return NULL; 223 return NULL;
275} 224}
276 225
277 226
278/**
279 * Create a new block group.
280 *
281 * @param ctx block context in which the block group is created
282 * @param type type of the block for which we are creating the group
283 * @param nonce random value used to seed the group creation
284 * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
285 * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
286 * @return block group handle, NULL if block groups are not supported
287 * by this @a type of block (this is not an error)
288 */
289struct GNUNET_BLOCK_Group * 227struct GNUNET_BLOCK_Group *
290GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx, 228GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
291 enum GNUNET_BLOCK_Type type, 229 enum GNUNET_BLOCK_Type type,
@@ -317,24 +255,6 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
317} 255}
318 256
319 257
320/**
321 * Function called to validate a reply or a request. For
322 * request evaluation, simply pass "NULL" for the reply_block.
323 * Note that it is assumed that the reply has already been
324 * matched to the key (and signatures checked) as it would
325 * be done with the "get_key" function.
326 *
327 * @param ctx block contxt
328 * @param type block type
329 * @param block block group to use
330 * @param eo control flags
331 * @param query original query (hash)
332 * @param xquery extended query data (can be NULL, depending on type)
333 * @param xquery_size number of bytes in @a xquery
334 * @param reply_block response to validate
335 * @param reply_block_size number of bytes in @a reply_block
336 * @return characterization of result
337 */
338enum GNUNET_BLOCK_EvaluationResult 258enum GNUNET_BLOCK_EvaluationResult
339GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx, 259GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
340 enum GNUNET_BLOCK_Type type, 260 enum GNUNET_BLOCK_Type type,
@@ -364,18 +284,7 @@ GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
364} 284}
365 285
366 286
367/** 287enum GNUNET_GenericReturnValue
368 * Function called to obtain the key for a block.
369 *
370 * @param ctx block context
371 * @param type block type
372 * @param block block to get the key for
373 * @param block_size number of bytes in @a block
374 * @param key set to the key (query) for the given block
375 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
376 * (or if extracting a key from a block of this type does not work)
377 */
378int
379GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx, 288GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
380 enum GNUNET_BLOCK_Type type, 289 enum GNUNET_BLOCK_Type type,
381 const void *block, 290 const void *block,
@@ -385,8 +294,8 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
385 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, 294 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
386 type); 295 type);
387 296
388 if (plugin == NULL) 297 if (NULL == plugin)
389 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; 298 return GNUNET_SYSERR;
390 return plugin->get_key (plugin->cls, 299 return plugin->get_key (plugin->cls,
391 type, 300 type,
392 block, 301 block,
@@ -395,18 +304,73 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
395} 304}
396 305
397 306
398/** 307enum GNUNET_GenericReturnValue
399 * Update block group to filter out the given results. Note that the 308GNUNET_BLOCK_check_query (struct GNUNET_BLOCK_Context *ctx,
400 * use of a hash for seen results implies that the caller magically 309 enum GNUNET_BLOCK_Type type,
401 * knows how the specific block engine hashes for filtering 310 const struct GNUNET_HashCode *query,
402 * duplicates, so this API may not always apply. 311 const void *xquery,
403 * 312 size_t xquery_size)
404 * @param bf_mutator mutation value to use 313{
405 * @param seen_results results already seen 314 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
406 * @param seen_results_count number of entries in @a seen_results 315 type);
407 * @return #GNUNET_SYSERR if not supported, #GNUNET_OK on success 316
408 */ 317 if (NULL == plugin)
409int 318 return GNUNET_SYSERR;
319 return plugin->check_query (plugin->cls,
320 type,
321 query,
322 xquery,
323 xquery_size);
324}
325
326
327enum GNUNET_GenericReturnValue
328GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
329 enum GNUNET_BLOCK_Type type,
330 const struct GNUNET_HashCode *query,
331 const void *block,
332 size_t block_size)
333{
334 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
335 type);
336
337 if (NULL == plugin)
338 return GNUNET_SYSERR;
339 return plugin->check_block (plugin->cls,
340 type,
341 query,
342 block,
343 block_size);
344}
345
346
347enum GNUNET_BLOCK_ReplyEvaluationResult
348GNUNET_BLOCK_check_reply (struct GNUNET_BLOCK_Context *ctx,
349 enum GNUNET_BLOCK_Type type,
350 struct GNUNET_BLOCK_Group *group,
351 const struct GNUNET_HashCode *query,
352 const void *xquery,
353 size_t xquery_size,
354 const void *reply_block,
355 size_t reply_block_size)
356{
357 struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
358 type);
359
360 if (NULL == plugin)
361 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
362 return plugin->check_reply (plugin->cls,
363 type,
364 group,
365 query,
366 xquery,
367 xquery_size,
368 reply_block,
369 reply_block_size);
370}
371
372
373enum GNUNET_GenericReturnValue
410GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg, 374GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg,
411 const struct GNUNET_HashCode *seen_results, 375 const struct GNUNET_HashCode *seen_results,
412 unsigned int seen_results_count) 376 unsigned int seen_results_count)
diff --git a/src/block/plugin_block_template.c b/src/block/plugin_block_template.c
index ecd46e364..13d9adfda 100644
--- a/src/block/plugin_block_template.c
+++ b/src/block/plugin_block_template.c
@@ -135,6 +135,80 @@ block_plugin_template_evaluate (void *cls,
135 135
136 136
137/** 137/**
138 * Function called to validate a query.
139 *
140 * @param cls closure
141 * @param ctx block context
142 * @param type block type
143 * @param query original query (hash)
144 * @param xquery extrended query data (can be NULL, depending on type)
145 * @param xquery_size number of bytes in @a xquery
146 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
147 */
148static enum GNUNET_GenericReturnValue
149block_plugin_template_check_query (void *cls,
150 enum GNUNET_BLOCK_Type type,
151 const struct GNUNET_HashCode *query,
152 const void *xquery,
153 size_t xquery_size)
154{
155 return GNUNET_OK;
156}
157
158
159/**
160 * Function called to validate a block for storage.
161 *
162 * @param cls closure
163 * @param type block type
164 * @param query key for the block (hash), must match exactly
165 * @param block block data to validate
166 * @param block_size number of bytes in @a block
167 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
168 */
169static enum GNUNET_GenericReturnValue
170block_plugin_template_check_block (void *cls,
171 enum GNUNET_BLOCK_Type type,
172 const struct GNUNET_HashCode *query,
173 const void *block,
174 size_t block_size)
175{
176 return GNUNET_OK;
177}
178
179
180/**
181 * Function called to validate a reply to a request. Note that it is assumed
182 * that the reply has already been matched to the key (and signatures checked)
183 * as it would be done with the GetKeyFunction and the
184 * BlockEvaluationFunction.
185 *
186 * @param cls closure
187 * @param type block type
188 * @param group which block group to use for evaluation
189 * @param query original query (hash)
190 * @param xquery extrended query data (can be NULL, depending on type)
191 * @param xquery_size number of bytes in @a xquery
192 * @param reply_block response to validate
193 * @param reply_block_size number of bytes in @a reply_block
194 * @return characterization of result
195 */
196static enum GNUNET_BLOCK_ReplyEvaluationResult
197block_plugin_template_check_reply (
198 void *cls,
199 enum GNUNET_BLOCK_Type type,
200 struct GNUNET_BLOCK_Group *group,
201 const struct GNUNET_HashCode *query,
202 const void *xquery,
203 size_t xquery_size,
204 const void *reply_block,
205 size_t reply_block_size)
206{
207 return GNUNET_BLOCK_REPLY_OK_MORE;
208}
209
210
211/**
138 * Function called to obtain the key for a block. 212 * Function called to obtain the key for a block.
139 * 213 *
140 * @param cls closure 214 * @param cls closure
@@ -145,7 +219,7 @@ block_plugin_template_evaluate (void *cls,
145 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 219 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
146 * (or if extracting a key from a block of this type does not work) 220 * (or if extracting a key from a block of this type does not work)
147 */ 221 */
148static int 222static enum GNUNET_GenericReturnValue
149block_plugin_template_get_key (void *cls, 223block_plugin_template_get_key (void *cls,
150 enum GNUNET_BLOCK_Type type, 224 enum GNUNET_BLOCK_Type type,
151 const void *block, 225 const void *block,
@@ -164,8 +238,8 @@ block_plugin_template_get_key (void *cls,
164void * 238void *
165libgnunet_plugin_block_template_init (void *cls) 239libgnunet_plugin_block_template_init (void *cls)
166{ 240{
167 static enum GNUNET_BLOCK_Type types[] = { 241 static const enum GNUNET_BLOCK_Type types[] = {
168 /* FIXME: insert supported block types here */ 242 /* NOTE: insert supported block types here */
169 GNUNET_BLOCK_TYPE_ANY /* end of list */ 243 GNUNET_BLOCK_TYPE_ANY /* end of list */
170 }; 244 };
171 struct GNUNET_BLOCK_PluginFunctions *api; 245 struct GNUNET_BLOCK_PluginFunctions *api;
@@ -173,6 +247,9 @@ libgnunet_plugin_block_template_init (void *cls)
173 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 247 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
174 api->evaluate = &block_plugin_template_evaluate; 248 api->evaluate = &block_plugin_template_evaluate;
175 api->get_key = &block_plugin_template_get_key; 249 api->get_key = &block_plugin_template_get_key;
250 api->check_query = &block_plugin_template_check_query;
251 api->check_block = &block_plugin_template_check_block;
252 api->check_reply = &block_plugin_template_check_reply;
176 api->create_group = &block_plugin_template_create_group; 253 api->create_group = &block_plugin_template_create_group;
177 api->types = types; 254 api->types = types;
178 return api; 255 return api;
diff --git a/src/block/plugin_block_test.c b/src/block/plugin_block_test.c
index 45d54d339..fd643c4dc 100644
--- a/src/block/plugin_block_test.c
+++ b/src/block/plugin_block_test.c
@@ -143,6 +143,108 @@ block_plugin_test_evaluate (void *cls,
143 143
144 144
145/** 145/**
146 * Function called to validate a query.
147 *
148 * @param cls closure
149 * @param ctx block context
150 * @param type block type
151 * @param query original query (hash)
152 * @param xquery extrended query data (can be NULL, depending on type)
153 * @param xquery_size number of bytes in @a xquery
154 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
155 */
156static enum GNUNET_GenericReturnValue
157block_plugin_test_check_query (void *cls,
158 enum GNUNET_BLOCK_Type type,
159 const struct GNUNET_HashCode *query,
160 const void *xquery,
161 size_t xquery_size)
162{
163 if (GNUNET_BLOCK_TYPE_TEST != type)
164 {
165 GNUNET_break (0);
166 return GNUNET_SYSERR;
167 }
168 if (0 != xquery_size)
169 {
170 GNUNET_break_op (0);
171 return GNUNET_SYSERR;
172 }
173 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
174}
175
176
177/**
178 * Function called to validate a block for storage.
179 *
180 * @param cls closure
181 * @param type block type
182 * @param query key for the block (hash), must match exactly
183 * @param block block data to validate
184 * @param block_size number of bytes in @a block
185 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
186 */
187static enum GNUNET_GenericReturnValue
188block_plugin_test_check_block (void *cls,
189 enum GNUNET_BLOCK_Type type,
190 const struct GNUNET_HashCode *query,
191 const void *block,
192 size_t block_size)
193{
194 if (GNUNET_BLOCK_TYPE_TEST != type)
195 {
196 GNUNET_break (0);
197 return GNUNET_SYSERR;
198 }
199 return GNUNET_OK;
200}
201
202
203/**
204 * Function called to validate a reply to a request. Note that it is assumed
205 * that the reply has already been matched to the key (and signatures checked)
206 * as it would be done with the GetKeyFunction and the
207 * BlockEvaluationFunction.
208 *
209 * @param cls closure
210 * @param type block type
211 * @param group which block group to use for evaluation
212 * @param query original query (hash)
213 * @param xquery extrended query data (can be NULL, depending on type)
214 * @param xquery_size number of bytes in @a xquery
215 * @param reply_block response to validate
216 * @param reply_block_size number of bytes in @a reply_block
217 * @return characterization of result
218 */
219static enum GNUNET_BLOCK_ReplyEvaluationResult
220block_plugin_test_check_reply (void *cls,
221 enum GNUNET_BLOCK_Type type,
222 struct GNUNET_BLOCK_Group *group,
223 const struct GNUNET_HashCode *query,
224 const void *xquery,
225 size_t xquery_size,
226 const void *reply_block,
227 size_t reply_block_size)
228{
229 struct GNUNET_HashCode chash;
230
231 if (GNUNET_BLOCK_TYPE_TEST != type)
232 {
233 GNUNET_break (0);
234 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
235 }
236 GNUNET_CRYPTO_hash (reply_block,
237 reply_block_size,
238 &chash);
239 if (GNUNET_YES ==
240 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
241 &chash))
242 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
243 return GNUNET_BLOCK_REPLY_OK_MORE;
244}
245
246
247/**
146 * Function called to obtain the key for a block. 248 * Function called to obtain the key for a block.
147 * 249 *
148 * @param cls closure 250 * @param cls closure
@@ -153,7 +255,7 @@ block_plugin_test_evaluate (void *cls,
153 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 255 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
154 * (or if extracting a key from a block of this type does not work) 256 * (or if extracting a key from a block of this type does not work)
155 */ 257 */
156static int 258static enum GNUNET_GenericReturnValue
157block_plugin_test_get_key (void *cls, 259block_plugin_test_get_key (void *cls,
158 enum GNUNET_BLOCK_Type type, 260 enum GNUNET_BLOCK_Type type,
159 const void *block, 261 const void *block,
@@ -175,7 +277,7 @@ block_plugin_test_get_key (void *cls,
175void * 277void *
176libgnunet_plugin_block_test_init (void *cls) 278libgnunet_plugin_block_test_init (void *cls)
177{ 279{
178 static enum GNUNET_BLOCK_Type types[] = { 280 static const enum GNUNET_BLOCK_Type types[] = {
179 GNUNET_BLOCK_TYPE_TEST, 281 GNUNET_BLOCK_TYPE_TEST,
180 GNUNET_BLOCK_TYPE_ANY /* end of list */ 282 GNUNET_BLOCK_TYPE_ANY /* end of list */
181 }; 283 };
@@ -184,6 +286,9 @@ libgnunet_plugin_block_test_init (void *cls)
184 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 286 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
185 api->evaluate = &block_plugin_test_evaluate; 287 api->evaluate = &block_plugin_test_evaluate;
186 api->get_key = &block_plugin_test_get_key; 288 api->get_key = &block_plugin_test_get_key;
289 api->check_query = &block_plugin_test_check_query;
290 api->check_block = &block_plugin_test_check_block;
291 api->check_reply = &block_plugin_test_check_reply;
187 api->create_group = &block_plugin_test_create_group; 292 api->create_group = &block_plugin_test_create_group;
188 api->types = types; 293 api->types = types;
189 return api; 294 return api;
diff --git a/src/consensus/plugin_block_consensus.c b/src/consensus/plugin_block_consensus.c
index cdac12ed5..67309bc79 100644
--- a/src/consensus/plugin_block_consensus.c
+++ b/src/consensus/plugin_block_consensus.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2017 GNUnet e.V. 3 Copyright (C) 2017, 2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -80,6 +80,109 @@ block_plugin_consensus_evaluate (void *cls,
80 80
81 81
82/** 82/**
83 * Function called to validate a query.
84 *
85 * @param cls closure
86 * @param ctx block context
87 * @param type block type
88 * @param query original query (hash)
89 * @param xquery extrended query data (can be NULL, depending on type)
90 * @param xquery_size number of bytes in @a xquery
91 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
92 */
93static enum GNUNET_GenericReturnValue
94block_plugin_consensus_check_query (void *cls,
95 enum GNUNET_BLOCK_Type type,
96 const struct GNUNET_HashCode *query,
97 const void *xquery,
98 size_t xquery_size)
99{
100 /* consensus does not use queries/DHT */
101 GNUNET_break (0);
102 return GNUNET_SYSERR;
103}
104
105
106/**
107 * Function called to validate a block for storage.
108 *
109 * @param cls closure
110 * @param type block type
111 * @param query key for the block (hash), must match exactly
112 * @param block block data to validate
113 * @param block_size number of bytes in @a block
114 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
115 */
116static enum GNUNET_GenericReturnValue
117block_plugin_consensus_check_block (void *cls,
118 enum GNUNET_BLOCK_Type type,
119 const struct GNUNET_HashCode *query,
120 const void *block,
121 size_t block_size)
122{
123 struct GNUNET_BLOCK_Context *ctx = cls;
124 const struct ConsensusElement *ce = block;
125
126 if (block_size < sizeof(*ce))
127 return GNUNET_NO;
128 if ( (0 != ce->marker) ||
129 (0 == ce->payload_type) )
130 return GNUNET_OK;
131 return GNUNET_BLOCK_check_block (ctx,
132 ntohl (ce->payload_type),
133 query,
134 &ce[1],
135 block_size - sizeof(*ce));
136}
137
138
139/**
140 * Function called to validate a reply to a request. Note that it is assumed
141 * that the reply has already been matched to the key (and signatures checked)
142 * as it would be done with the GetKeyFunction and the
143 * BlockEvaluationFunction.
144 *
145 * @param cls closure
146 * @param type block type
147 * @param group which block group to use for evaluation
148 * @param query original query (hash)
149 * @param xquery extrended query data (can be NULL, depending on type)
150 * @param xquery_size number of bytes in @a xquery
151 * @param reply_block response to validate
152 * @param reply_block_size number of bytes in @a reply_block
153 * @return characterization of result
154 */
155static enum GNUNET_BLOCK_ReplyEvaluationResult
156block_plugin_consensus_check_reply (
157 void *cls,
158 enum GNUNET_BLOCK_Type type,
159 struct GNUNET_BLOCK_Group *group,
160 const struct GNUNET_HashCode *query,
161 const void *xquery,
162 size_t xquery_size,
163 const void *reply_block,
164 size_t reply_block_size)
165{
166 struct GNUNET_BLOCK_Context *ctx = cls;
167 const struct ConsensusElement *ce = reply_block;
168
169 if (reply_block_size < sizeof(struct ConsensusElement))
170 return GNUNET_NO;
171 if ( (0 != ce->marker) ||
172 (0 == ce->payload_type) )
173 return GNUNET_BLOCK_REPLY_OK_MORE;
174 return GNUNET_BLOCK_check_reply (ctx,
175 ntohl (ce->payload_type),
176 group,
177 query,
178 xquery,
179 xquery_size,
180 &ce[1],
181 reply_block_size - sizeof(*ce));
182}
183
184
185/**
83 * Function called to obtain the key for a block. 186 * Function called to obtain the key for a block.
84 * 187 *
85 * @param cls closure 188 * @param cls closure
@@ -90,7 +193,7 @@ block_plugin_consensus_evaluate (void *cls,
90 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 193 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
91 * (or if extracting a key from a block of this type does not work) 194 * (or if extracting a key from a block of this type does not work)
92 */ 195 */
93static int 196static enum GNUNET_GenericReturnValue
94block_plugin_consensus_get_key (void *cls, 197block_plugin_consensus_get_key (void *cls,
95 enum GNUNET_BLOCK_Type type, 198 enum GNUNET_BLOCK_Type type,
96 const void *block, 199 const void *block,
@@ -107,15 +210,20 @@ block_plugin_consensus_get_key (void *cls,
107void * 210void *
108libgnunet_plugin_block_consensus_init (void *cls) 211libgnunet_plugin_block_consensus_init (void *cls)
109{ 212{
110 static enum GNUNET_BLOCK_Type types[] = { 213 static const enum GNUNET_BLOCK_Type types[] = {
111 GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT, 214 GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT,
112 GNUNET_BLOCK_TYPE_ANY /* end of list */ 215 GNUNET_BLOCK_TYPE_ANY /* end of list */
113 }; 216 };
217 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
114 struct GNUNET_BLOCK_PluginFunctions *api; 218 struct GNUNET_BLOCK_PluginFunctions *api;
115 219
116 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 220 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
221 api->cls = GNUNET_BLOCK_context_create (cfg);
117 api->evaluate = &block_plugin_consensus_evaluate; 222 api->evaluate = &block_plugin_consensus_evaluate;
118 api->get_key = &block_plugin_consensus_get_key; 223 api->get_key = &block_plugin_consensus_get_key;
224 api->check_query = &block_plugin_consensus_check_query;
225 api->check_block = &block_plugin_consensus_check_block;
226 api->check_reply = &block_plugin_consensus_check_reply;
119 api->types = types; 227 api->types = types;
120 return api; 228 return api;
121} 229}
@@ -128,7 +236,9 @@ void *
128libgnunet_plugin_block_consensus_done (void *cls) 236libgnunet_plugin_block_consensus_done (void *cls)
129{ 237{
130 struct GNUNET_BLOCK_PluginFunctions *api = cls; 238 struct GNUNET_BLOCK_PluginFunctions *api = cls;
239 struct GNUNET_BLOCK_Context *bc = api->cls;
131 240
241 GNUNET_BLOCK_context_destroy (bc);
132 GNUNET_free (api); 242 GNUNET_free (api);
133 return NULL; 243 return NULL;
134} 244}
diff --git a/src/curl/curl.c b/src/curl/curl.c
index 684610101..e45612e94 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -201,14 +201,6 @@ struct GNUNET_CURL_Context
201}; 201};
202 202
203 203
204/**
205 * Force use of the provided username and password
206 * for client authentication for all operations performed
207 * with @a ctx.
208 *
209 * @param ctx context to set authentication data for
210 * @param userpass string with "$USERNAME:$PASSWORD"
211 */
212void 204void
213GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx, 205GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
214 const char *userpass) 206 const char *userpass)
@@ -219,21 +211,6 @@ GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
219} 211}
220 212
221 213
222/**
223 * Force use of the provided TLS client certificate
224 * for client authentication for all operations performed
225 * with @a ctx.
226 *
227 * Note that if the provided information is incorrect,
228 * the earliest operation that could fail is
229 * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()!
230 *
231 * @param ctx context to set authentication data for
232 * @param certtype type of the certificate
233 * @param certfile file with the certificate
234 * @param keyfile file with the private key
235 * @param keypass passphrase to decrypt @a keyfile (or NULL)
236 */
237void 214void
238GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx, 215GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
239 const char *certtype, 216 const char *certtype,
@@ -256,14 +233,6 @@ GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
256} 233}
257 234
258 235
259/**
260 * Initialise this library. This function should be called before using any of
261 * the following functions.
262 *
263 * @param cb function to call when rescheduling is required
264 * @param cb_cls closure for @a cb
265 * @return library context
266 */
267struct GNUNET_CURL_Context * 236struct GNUNET_CURL_Context *
268GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb, 237GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
269 void *cb_cls) 238 void *cb_cls)
@@ -299,12 +268,6 @@ GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
299} 268}
300 269
301 270
302/**
303 * Enable sending the async scope ID as a header.
304 *
305 * @param ctx the context to enable this for
306 * @param header_name name of the header to send.
307 */
308void 271void
309GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx, 272GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx,
310 const char *header_name) 273 const char *header_name)
@@ -313,15 +276,6 @@ GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx,
313} 276}
314 277
315 278
316/**
317 * Return #GNUNET_YES if given a valid scope ID and
318 * #GNUNET_NO otherwise. See #setup_job_headers,
319 * logic related to
320 * #GNUNET_CURL_enable_async_scope_header() for the
321 * code that generates such a @a scope_id.
322 *
323 * @returns #GNUNET_YES iff given a valid scope ID
324 */
325int 279int
326GNUNET_CURL_is_valid_scope_id (const char *scope_id) 280GNUNET_CURL_is_valid_scope_id (const char *scope_id)
327{ 281{
@@ -447,7 +401,9 @@ setup_job (CURL *eh,
447 struct GNUNET_CURL_Job *job; 401 struct GNUNET_CURL_Job *job;
448 402
449 if (CURLE_OK != 403 if (CURLE_OK !=
450 curl_easy_setopt (eh, CURLOPT_HTTPHEADER, all_headers)) 404 curl_easy_setopt (eh,
405 CURLOPT_HTTPHEADER,
406 all_headers))
451 { 407 {
452 GNUNET_break (0); 408 GNUNET_break (0);
453 curl_slist_free_all (all_headers); 409 curl_slist_free_all (all_headers);
@@ -491,12 +447,6 @@ setup_job (CURL *eh,
491} 447}
492 448
493 449
494/**
495 * Add @a extra_headers to the HTTP headers for @a job.
496 *
497 * @param[in,out] job the job to modify
498 * @param extra_headers headers to append
499 */
500void 450void
501GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job, 451GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
502 const struct curl_slist *extra_headers) 452 const struct curl_slist *extra_headers)
@@ -515,21 +465,6 @@ GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
515} 465}
516 466
517 467
518/**
519 * Schedule a CURL request to be executed and call the given @a jcc
520 * upon its completion. Note that the context will make use of the
521 * CURLOPT_PRIVATE facility of the CURL @a eh. Used to download
522 * resources that are NOT in JSON. The raw body will be returned.
523 *
524 * @param ctx context to execute the job in
525 * @param eh curl easy handle for the request, will
526 * be executed AND cleaned up
527 * @param job_headers extra headers to add for this request
528 * @param max_reply_size largest acceptable response body
529 * @param jcc callback to invoke upon completion
530 * @param jcc_cls closure for @a jcc
531 * @return NULL on error (in this case, @eh is still released!)
532 */
533struct GNUNET_CURL_Job * 468struct GNUNET_CURL_Job *
534GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx, 469GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
535 CURL *eh, 470 CURL *eh,
@@ -554,25 +489,6 @@ GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
554} 489}
555 490
556 491
557/**
558 * Schedule a CURL request to be executed and call the given @a jcc
559 * upon its completion. Note that the context will make use of the
560 * CURLOPT_PRIVATE facility of the CURL @a eh.
561 *
562 * This function modifies the CURL handle to add the
563 * "Content-Type: application/json" header if @a add_json is set.
564 *
565 * @param ctx context to execute the job in
566 * @param eh curl easy handle for the request, will be executed AND
567 * cleaned up. NOTE: the handle should _never_ have gotten
568 * any headers list, as that would then be overridden by
569 * @a jcc. Therefore, always pass custom headers as the
570 * @a job_headers parameter.
571 * @param job_headers extra headers to add for this request
572 * @param jcc callback to invoke upon completion
573 * @param jcc_cls closure for @a jcc
574 * @return NULL on error (in this case, @eh is still released!)
575 */
576struct GNUNET_CURL_Job * 492struct GNUNET_CURL_Job *
577GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx, 493GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
578 CURL *eh, 494 CURL *eh,
@@ -624,21 +540,6 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
624} 540}
625 541
626 542
627/**
628 * Schedule a CURL request to be executed and call the given @a jcc
629 * upon its completion. Note that the context will make use of the
630 * CURLOPT_PRIVATE facility of the CURL @a eh.
631 *
632 * This function modifies the CURL handle to add the
633 * "Content-Type: application/json" header.
634 *
635 * @param ctx context to execute the job in
636 * @param eh curl easy handle for the request, will
637 * be executed AND cleaned up
638 * @param jcc callback to invoke upon completion
639 * @param jcc_cls closure for @a jcc
640 * @return NULL on error (in this case, @eh is still released!)
641 */
642struct GNUNET_CURL_Job * 543struct GNUNET_CURL_Job *
643GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx, 544GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
644 CURL *eh, 545 CURL *eh,
@@ -661,18 +562,6 @@ GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
661} 562}
662 563
663 564
664/**
665 * Schedule a CURL request to be executed and call the given @a jcc
666 * upon its completion. Note that the context will make use of the
667 * CURLOPT_PRIVATE facility of the CURL @a eh.
668 *
669 * @param ctx context to execute the job in
670 * @param eh curl easy handle for the request, will
671 * be executed AND cleaned up
672 * @param jcc callback to invoke upon completion
673 * @param jcc_cls closure for @a jcc
674 * @return NULL on error (in this case, @eh is still released!)
675 */
676struct GNUNET_CURL_Job * 565struct GNUNET_CURL_Job *
677GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx, 566GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
678 CURL *eh, 567 CURL *eh,
@@ -687,12 +576,6 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
687} 576}
688 577
689 578
690/**
691 * Cancel a job. Must only be called before the job completion
692 * callback is called for the respective job.
693 *
694 * @param job job to cancel
695 */
696void 579void
697GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job) 580GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job)
698{ 581{
@@ -746,24 +629,6 @@ is_json (const char *ct)
746} 629}
747 630
748 631
749/**
750 * Obtain information about the final result about the
751 * HTTP download. If the download was successful, parses
752 * the JSON in the @a db and returns it. Also returns
753 * the HTTP @a response_code. If the download failed,
754 * the return value is NULL. The response code is set
755 * in any case, on download errors to zero.
756 *
757 * Calling this function also cleans up @a db.
758 *
759 * @param db download buffer
760 * @param eh CURL handle (to get the response code)
761 * @param[out] response_code set to the HTTP response code
762 * (or zero if we aborted the download, for example
763 * because the response was too big, or if
764 * the JSON we received was malformed).
765 * @return NULL if downloading a JSON reply failed.
766 */
767void * 632void *
768GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db, 633GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
769 CURL *eh, 634 CURL *eh,
@@ -838,13 +703,6 @@ GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
838} 703}
839 704
840 705
841/**
842 * Add custom request header.
843 *
844 * @param ctx cURL context.
845 * @param header header string; will be given to the context AS IS.
846 * @return #GNUNET_OK if no errors occurred, #GNUNET_SYSERR otherwise.
847 */
848enum GNUNET_GenericReturnValue 706enum GNUNET_GenericReturnValue
849GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx, 707GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
850 const char *header) 708 const char *header)
@@ -858,14 +716,6 @@ GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
858} 716}
859 717
860 718
861/**
862 * Run the main event loop for the HTTP interaction.
863 *
864 * @param ctx the library context
865 * @param rp parses the raw response returned from
866 * the Web server.
867 * @param rc cleans/frees the response
868 */
869void 719void
870GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx, 720GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
871 GNUNET_CURL_RawParser rp, 721 GNUNET_CURL_RawParser rp,
@@ -920,11 +770,6 @@ GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
920} 770}
921 771
922 772
923/**
924 * Run the main event loop for the HTTP interaction.
925 *
926 * @param ctx the library context
927 */
928void 773void
929GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx) 774GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
930{ 775{
@@ -934,34 +779,6 @@ GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
934} 779}
935 780
936 781
937/**
938 * Obtain the information for a select() call to wait until
939 * #GNUNET_CURL_perform() is ready again. Note that calling
940 * any other GNUNET_CURL-API may also imply that the library
941 * is again ready for #GNUNET_CURL_perform().
942 *
943 * Basically, a client should use this API to prepare for select(),
944 * then block on select(), then call #GNUNET_CURL_perform() and then
945 * start again until the work with the context is done.
946 *
947 * This function will NOT zero out the sets and assumes that @a max_fd
948 * and @a timeout are already set to minimal applicable values. It is
949 * safe to give this API FD-sets and @a max_fd and @a timeout that are
950 * already initialized to some other descriptors that need to go into
951 * the select() call.
952 *
953 * @param ctx context to get the event loop information for
954 * @param read_fd_set will be set for any pending read operations
955 * @param write_fd_set will be set for any pending write operations
956 * @param except_fd_set is here because curl_multi_fdset() has this argument
957 * @param max_fd set to the highest FD included in any set;
958 * if the existing sets have no FDs in it, the initial
959 * value should be "-1". (Note that `max_fd + 1` will need
960 * to be passed to select().)
961 * @param timeout set to the timeout in milliseconds (!); -1 means
962 * no timeout (NULL, blocking forever is OK), 0 means to
963 * proceed immediately with #GNUNET_CURL_perform().
964 */
965void 782void
966GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx, 783GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx,
967 fd_set *read_fd_set, 784 fd_set *read_fd_set,
@@ -995,13 +812,6 @@ GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx,
995} 812}
996 813
997 814
998/**
999 * Cleanup library initialisation resources. This function should be called
1000 * after using this library to cleanup the resources occupied during library's
1001 * initialisation.
1002 *
1003 * @param ctx the library context
1004 */
1005void 815void
1006GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx) 816GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx)
1007{ 817{
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 331a9b784..8b665e705 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -101,7 +101,9 @@ struct GNUNET_DATACACHE_Handle
101 * @param size number of bytes that were made available 101 * @param size number of bytes that were made available
102 */ 102 */
103static void 103static void
104env_delete_notify (void *cls, const struct GNUNET_HashCode *key, size_t size) 104env_delete_notify (void *cls,
105 const struct GNUNET_HashCode *key,
106 size_t size)
105{ 107{
106 struct GNUNET_DATACACHE_Handle *h = cls; 108 struct GNUNET_DATACACHE_Handle *h = cls;
107 109
@@ -122,13 +124,6 @@ env_delete_notify (void *cls, const struct GNUNET_HashCode *key, size_t size)
122} 124}
123 125
124 126
125/**
126 * Create a data cache.
127 *
128 * @param cfg configuration to use
129 * @param section section in the configuration that contains our options
130 * @return handle to use to access the service
131 */
132struct GNUNET_DATACACHE_Handle * 127struct GNUNET_DATACACHE_Handle *
133GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, 128GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
134 const char *section) 129 const char *section)
@@ -193,9 +188,9 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
193 ret->lib_name = libname; 188 ret->lib_name = libname;
194 /* Load the plugin within GNUnet's default context */ 189 /* Load the plugin within GNUnet's default context */
195 pd = GNUNET_OS_project_data_get (); 190 pd = GNUNET_OS_project_data_get ();
196 GNUNET_OS_init(GNUNET_OS_project_data_default ()); 191 GNUNET_OS_init (GNUNET_OS_project_data_default ());
197 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 192 ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
198 GNUNET_OS_init(pd); 193 GNUNET_OS_init (pd);
199 if (NULL == ret->api) 194 if (NULL == ret->api)
200 { 195 {
201 /* Try to load the plugin within the application's context 196 /* Try to load the plugin within the application's context
@@ -215,11 +210,6 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
215} 210}
216 211
217 212
218/**
219 * Destroy a data cache (and free associated resources).
220 *
221 * @param h handle to the datastore
222 */
223void 213void
224GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) 214GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
225{ 215{
@@ -244,21 +234,7 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
244} 234}
245 235
246 236
247/** 237enum GNUNET_GenericReturnValue
248 * Store an item in the datastore.
249 *
250 * @param h handle to the datacache
251 * @param key key to store data under
252 * @param xor_distance distance of @a key to our PID
253 * @param data_size number of bytes in @a data
254 * @param data data to store
255 * @param type type of the value
256 * @param discard_time when to discard the value in any case
257 * @param path_info_len number of entries in @a path_info
258 * @param path_info a path through the network
259 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error, #GNUNET_NO if duplicate
260 */
261int
262GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, 238GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
263 const struct GNUNET_HashCode *key, 239 const struct GNUNET_HashCode *key,
264 uint32_t xor_distance, 240 uint32_t xor_distance,
@@ -310,17 +286,6 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
310} 286}
311 287
312 288
313/**
314 * Iterate over the results for a particular key
315 * in the datacache.
316 *
317 * @param h handle to the datacache
318 * @param key what to look up
319 * @param type entries of which type are relevant?
320 * @param iter maybe NULL (to just count)
321 * @param iter_cls closure for @a iter
322 * @return the number of results found
323 */
324unsigned int 289unsigned int
325GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, 290GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
326 const struct GNUNET_HashCode *key, 291 const struct GNUNET_HashCode *key,
@@ -352,42 +317,6 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
352} 317}
353 318
354 319
355/**
356 * Obtain a random element from the datacache.
357 *
358 * @param h handle to the datacache
359 * @param iter maybe NULL (to just count)
360 * @param iter_cls closure for @a iter
361 * @return the number of results found (zero or 1)
362 */
363unsigned int
364GNUNET_DATACACHE_get_random (struct GNUNET_DATACACHE_Handle *h,
365 GNUNET_DATACACHE_Iterator iter,
366 void *iter_cls)
367{
368 GNUNET_STATISTICS_update (h->stats,
369 gettext_noop (
370 "# requests for random value received"),
371 1,
372 GNUNET_NO);
373 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing request for random value\n");
374 return h->api->get_random (h->api->cls, iter, iter_cls);
375}
376
377
378/**
379 * Iterate over the results that are "close" to a particular key in
380 * the datacache. "close" is defined as numerically larger than @a
381 * key (when interpreted as a circular address space), with small
382 * distance.
383 *
384 * @param h handle to the datacache
385 * @param key area of the keyspace to look into
386 * @param num_results number of results that should be returned to @a iter
387 * @param iter maybe NULL (to just count)
388 * @param iter_cls closure for @a iter
389 * @return the number of results found
390 */
391unsigned int 320unsigned int
392GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h, 321GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
393 const struct GNUNET_HashCode *key, 322 const struct GNUNET_HashCode *key,
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index 074437e7d..20d18458d 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -402,33 +402,6 @@ heap_plugin_del (void *cls)
402 402
403 403
404/** 404/**
405 * Return a random value from the datastore.
406 *
407 * @param cls closure (our `struct Plugin`)
408 * @param iter maybe NULL (to just count)
409 * @param iter_cls closure for @a iter
410 * @return the number of results found
411 */
412static unsigned int
413heap_plugin_get_random (void *cls,
414 GNUNET_DATACACHE_Iterator iter,
415 void *iter_cls)
416{
417 struct Plugin *plugin = cls;
418 struct GetContext get_ctx;
419
420 get_ctx.type = GNUNET_BLOCK_TYPE_ANY;
421 get_ctx.iter = iter;
422 get_ctx.iter_cls = iter_cls;
423 get_ctx.cnt = 0;
424 GNUNET_CONTAINER_multihashmap_get_random (plugin->map,
425 &get_cb,
426 &get_ctx);
427 return get_ctx.cnt;
428}
429
430
431/**
432 * Closure for #find_closest(). 405 * Closure for #find_closest().
433 */ 406 */
434struct GetClosestContext 407struct GetClosestContext
@@ -548,7 +521,6 @@ libgnunet_plugin_datacache_heap_init (void *cls)
548 api->get = &heap_plugin_get; 521 api->get = &heap_plugin_get;
549 api->put = &heap_plugin_put; 522 api->put = &heap_plugin_put;
550 api->del = &heap_plugin_del; 523 api->del = &heap_plugin_del;
551 api->get_random = &heap_plugin_get_random;
552 api->get_closest = &heap_plugin_get_closest; 524 api->get_closest = &heap_plugin_get_closest;
553 LOG (GNUNET_ERROR_TYPE_INFO, 525 LOG (GNUNET_ERROR_TYPE_INFO,
554 _ ("Heap datacache running\n")); 526 _ ("Heap datacache running\n"));
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c
index 6613ae928..070619137 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -67,7 +67,8 @@ static int
67init_connection (struct Plugin *plugin) 67init_connection (struct Plugin *plugin)
68{ 68{
69 struct GNUNET_PQ_ExecuteStatement es[] = { 69 struct GNUNET_PQ_ExecuteStatement es[] = {
70 GNUNET_PQ_make_try_execute ("CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn011dc_oid_seq"), 70 GNUNET_PQ_make_try_execute (
71 "CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn011dc_oid_seq"),
71 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn011dc (" 72 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn011dc ("
72 " oid OID NOT NULL DEFAULT nextval('gn011dc_oid_seq')," 73 " oid OID NOT NULL DEFAULT nextval('gn011dc_oid_seq'),"
73 " type INTEGER NOT NULL," 74 " type INTEGER NOT NULL,"
@@ -107,11 +108,6 @@ init_connection (struct Plugin *plugin)
107 "SELECT length(value) AS len,oid,key FROM gn011dc" 108 "SELECT length(value) AS len,oid,key FROM gn011dc"
108 " ORDER BY prox ASC, discard_time ASC LIMIT 1", 109 " ORDER BY prox ASC, discard_time ASC LIMIT 1",
109 0), 110 0),
110 GNUNET_PQ_make_prepare ("get_random",
111 "SELECT discard_time,type,value,path,key FROM gn011dc"
112 " WHERE discard_time >= $1"
113 " ORDER BY key ASC LIMIT 1 OFFSET $2",
114 2),
115 GNUNET_PQ_make_prepare ("get_closest", 111 GNUNET_PQ_make_prepare ("get_closest",
116 "SELECT discard_time,type,value,path,key FROM gn011dc " 112 "SELECT discard_time,type,value,path,key FROM gn011dc "
117 "WHERE key>=$1 AND discard_time >= $2 ORDER BY key ASC LIMIT $3", 113 "WHERE key>=$1 AND discard_time >= $2 ORDER BY key ASC LIMIT $3",
@@ -410,96 +406,6 @@ postgres_plugin_del (void *cls)
410 406
411 407
412/** 408/**
413 * Obtain a random key-value pair from the datacache.
414 *
415 * @param cls closure (our `struct Plugin`)
416 * @param iter maybe NULL (to just count)
417 * @param iter_cls closure for @a iter
418 * @return the number of results found, zero (datacache empty) or one
419 */
420static unsigned int
421postgres_plugin_get_random (void *cls,
422 GNUNET_DATACACHE_Iterator iter,
423 void *iter_cls)
424{
425 struct Plugin *plugin = cls;
426 uint32_t off;
427 struct GNUNET_TIME_Absolute now = { 0 };
428 struct GNUNET_TIME_Absolute expiration_time;
429 size_t data_size;
430 void *data;
431 size_t path_len;
432 struct GNUNET_PeerIdentity *path;
433 struct GNUNET_HashCode key;
434 uint32_t type;
435 enum GNUNET_DB_QueryStatus res;
436 struct GNUNET_PQ_QueryParam params[] = {
437 GNUNET_PQ_query_param_absolute_time (&now),
438 GNUNET_PQ_query_param_uint32 (&off),
439 GNUNET_PQ_query_param_end
440 };
441 struct GNUNET_PQ_ResultSpec rs[] = {
442 GNUNET_PQ_result_spec_absolute_time ("discard_time",
443 &expiration_time),
444 GNUNET_PQ_result_spec_uint32 ("type",
445 &type),
446 GNUNET_PQ_result_spec_variable_size ("value",
447 &data,
448 &data_size),
449 GNUNET_PQ_result_spec_variable_size ("path",
450 (void **) &path,
451 &path_len),
452 GNUNET_PQ_result_spec_auto_from_type ("key",
453 &key),
454 GNUNET_PQ_result_spec_end
455 };
456
457 if (0 == plugin->num_items)
458 return 0;
459 if (NULL == iter)
460 return 1;
461 now = GNUNET_TIME_absolute_get ();
462 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
463 plugin->num_items);
464 res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh,
465 "get_random",
466 params,
467 rs);
468 if (0 > res)
469 {
470 GNUNET_break (0);
471 return 0;
472 }
473 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
474 {
475 GNUNET_break (0);
476 return 0;
477 }
478 if (0 != (path_len % sizeof(struct GNUNET_PeerIdentity)))
479 {
480 GNUNET_break (0);
481 path_len = 0;
482 }
483 path_len %= sizeof(struct GNUNET_PeerIdentity);
484 LOG (GNUNET_ERROR_TYPE_DEBUG,
485 "Found random value with key %s of size %u bytes and type %u in database\n",
486 GNUNET_h2s (&key),
487 (unsigned int) data_size,
488 (unsigned int) type);
489 (void) iter (iter_cls,
490 &key,
491 data_size,
492 data,
493 (enum GNUNET_BLOCK_Type) type,
494 expiration_time,
495 path_len,
496 path);
497 GNUNET_PQ_cleanup_result (rs);
498 return 1;
499}
500
501
502/**
503 * Closure for #extract_result_cb. 409 * Closure for #extract_result_cb.
504 */ 410 */
505struct ExtractResultContext 411struct ExtractResultContext
@@ -681,7 +587,6 @@ libgnunet_plugin_datacache_postgres_init (void *cls)
681 api->get = &postgres_plugin_get; 587 api->get = &postgres_plugin_get;
682 api->put = &postgres_plugin_put; 588 api->put = &postgres_plugin_put;
683 api->del = &postgres_plugin_del; 589 api->del = &postgres_plugin_del;
684 api->get_random = &postgres_plugin_get_random;
685 api->get_closest = &postgres_plugin_get_closest; 590 api->get_closest = &postgres_plugin_get_closest;
686 LOG (GNUNET_ERROR_TYPE_INFO, 591 LOG (GNUNET_ERROR_TYPE_INFO,
687 "Postgres datacache running\n"); 592 "Postgres datacache running\n");
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index 66ff9e82c..0c894556b 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -92,11 +92,6 @@ struct Plugin
92 sqlite3_stmt *del_stmt; 92 sqlite3_stmt *del_stmt;
93 93
94 /** 94 /**
95 * Prepared statement for #sqlite_plugin_get_random.
96 */
97 sqlite3_stmt *get_random_stmt;
98
99 /**
100 * Prepared statement for #sqlite_plugin_get_closest. 95 * Prepared statement for #sqlite_plugin_get_closest.
101 */ 96 */
102 sqlite3_stmt *get_closest_stmt; 97 sqlite3_stmt *get_closest_stmt;
@@ -452,85 +447,6 @@ sqlite_plugin_del (void *cls)
452 447
453 448
454/** 449/**
455 * Obtain a random key-value pair from the datacache.
456 *
457 * @param cls closure (our `struct Plugin`)
458 * @param iter maybe NULL (to just count)
459 * @param iter_cls closure for @a iter
460 * @return the number of results found, zero (datacache empty) or one
461 */
462static unsigned int
463sqlite_plugin_get_random (void *cls,
464 GNUNET_DATACACHE_Iterator iter,
465 void *iter_cls)
466{
467 struct Plugin *plugin = cls;
468 struct GNUNET_TIME_Absolute exp;
469 size_t size;
470 void *dat;
471 uint32_t off = 0;
472 size_t psize;
473 uint32_t type;
474 struct GNUNET_PeerIdentity *path;
475 struct GNUNET_HashCode key;
476 struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint32 (&off),
477 GNUNET_SQ_query_param_end };
478 struct GNUNET_SQ_ResultSpec rs[] =
479 { GNUNET_SQ_result_spec_variable_size (&dat, &size),
480 GNUNET_SQ_result_spec_absolute_time (&exp),
481 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
482 GNUNET_SQ_result_spec_auto_from_type (&key),
483 GNUNET_SQ_result_spec_uint32 (&type),
484 GNUNET_SQ_result_spec_end };
485
486 if (0 == plugin->num_items)
487 return 0;
488 if (NULL == iter)
489 return 1;
490 off =
491 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, plugin->num_items);
492 if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_random_stmt, params))
493 {
494 return 0;
495 }
496 if (SQLITE_ROW != sqlite3_step (plugin->get_random_stmt))
497 {
498 GNUNET_break (0);
499 GNUNET_SQ_reset (plugin->dbh, plugin->get_random_stmt);
500 return 0;
501 }
502 if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_random_stmt, rs))
503 {
504 GNUNET_break (0);
505 GNUNET_SQ_reset (plugin->dbh, plugin->get_random_stmt);
506 return 0;
507 }
508 if (0 != psize % sizeof(struct GNUNET_PeerIdentity))
509 {
510 GNUNET_break (0);
511 psize = 0;
512 path = NULL;
513 }
514 psize /= sizeof(struct GNUNET_PeerIdentity);
515 LOG (GNUNET_ERROR_TYPE_DEBUG,
516 "Found %u-byte result with key %s when processing GET-RANDOM\n",
517 (unsigned int) size,
518 GNUNET_h2s (&key));
519 (void) iter (iter_cls,
520 &key,
521 size,
522 dat,
523 (enum GNUNET_BLOCK_Type) type,
524 exp,
525 psize,
526 path);
527 GNUNET_SQ_cleanup_result (rs);
528 GNUNET_SQ_reset (plugin->dbh, plugin->get_random_stmt);
529 return 1;
530}
531
532
533/**
534 * Iterate over the results that are "close" to a particular key in 450 * Iterate over the results that are "close" to a particular key in
535 * the datacache. "close" is defined as numerically larger than @a 451 * the datacache. "close" is defined as numerically larger than @a
536 * key (when interpreted as a circular address space), with small 452 * key (when interpreted as a circular address space), with small
@@ -714,10 +630,6 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
714 (SQLITE_OK != sq_prepare (plugin->dbh, 630 (SQLITE_OK != sq_prepare (plugin->dbh,
715 "DELETE FROM ds091 WHERE _ROWID_=?", 631 "DELETE FROM ds091 WHERE _ROWID_=?",
716 &plugin->del_stmt)) || 632 &plugin->del_stmt)) ||
717 (SQLITE_OK != sq_prepare (plugin->dbh,
718 "SELECT value,expire,path,key,type FROM ds091 "
719 "ORDER BY key LIMIT 1 OFFSET ?",
720 &plugin->get_random_stmt)) ||
721 (SQLITE_OK != 633 (SQLITE_OK !=
722 sq_prepare (plugin->dbh, 634 sq_prepare (plugin->dbh,
723 "SELECT value,expire,path,type,key FROM ds091 " 635 "SELECT value,expire,path,type,key FROM ds091 "
@@ -737,7 +649,6 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
737 api->get = &sqlite_plugin_get; 649 api->get = &sqlite_plugin_get;
738 api->put = &sqlite_plugin_put; 650 api->put = &sqlite_plugin_put;
739 api->del = &sqlite_plugin_del; 651 api->del = &sqlite_plugin_del;
740 api->get_random = &sqlite_plugin_get_random;
741 api->get_closest = &sqlite_plugin_get_closest; 652 api->get_closest = &sqlite_plugin_get_closest;
742 LOG (GNUNET_ERROR_TYPE_INFO, "Sqlite datacache running\n"); 653 LOG (GNUNET_ERROR_TYPE_INFO, "Sqlite datacache running\n");
743 return api; 654 return api;
@@ -772,7 +683,6 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
772 sqlite3_finalize (plugin->del_select_stmt); 683 sqlite3_finalize (plugin->del_select_stmt);
773 sqlite3_finalize (plugin->del_expired_stmt); 684 sqlite3_finalize (plugin->del_expired_stmt);
774 sqlite3_finalize (plugin->del_stmt); 685 sqlite3_finalize (plugin->del_stmt);
775 sqlite3_finalize (plugin->get_random_stmt);
776 sqlite3_finalize (plugin->get_closest_stmt); 686 sqlite3_finalize (plugin->get_closest_stmt);
777 result = sqlite3_close (plugin->dbh); 687 result = sqlite3_close (plugin->dbh);
778#if SQLITE_VERSION_NUMBER >= 3007000 688#if SQLITE_VERSION_NUMBER >= 3007000
diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c
index 329bfd9a4..09279f55c 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -109,24 +109,6 @@ template_plugin_del (void *cls)
109 109
110 110
111/** 111/**
112 * Return a random value from the datastore.
113 *
114 * @param cls closure (internal context for the plugin)
115 * @param iter maybe NULL (to just count)
116 * @param iter_cls closure for @a iter
117 * @return the number of results found (zero or one)
118 */
119static unsigned int
120template_plugin_get_random (void *cls,
121 GNUNET_DATACACHE_Iterator iter,
122 void *iter_cls)
123{
124 GNUNET_break (0);
125 return 0;
126}
127
128
129/**
130 * Iterate over the results that are "close" to a particular key in 112 * Iterate over the results that are "close" to a particular key in
131 * the datacache. "close" is defined as numerically larger than @a 113 * the datacache. "close" is defined as numerically larger than @a
132 * key (when interpreted as a circular address space), with small 114 * key (when interpreted as a circular address space), with small
@@ -171,7 +153,6 @@ libgnunet_plugin_datacache_template_init (void *cls)
171 api->get = &template_plugin_get; 153 api->get = &template_plugin_get;
172 api->put = &template_plugin_put; 154 api->put = &template_plugin_put;
173 api->del = &template_plugin_del; 155 api->del = &template_plugin_del;
174 api->get_random = &template_plugin_get_random;
175 api->get_closest = &template_plugin_get_closest; 156 api->get_closest = &template_plugin_get_closest;
176 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, 157 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
177 "template", 158 "template",
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index 97888ce03..498a7b3e6 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -599,7 +599,8 @@ handle_reserve (void *cls, const struct ReserveMessage *msg)
599 * message happens, the insertion request could be blocked 599 * message happens, the insertion request could be blocked
600 * by less-important content from migration because it is 600 * by less-important content from migration because it is
601 * larger than 1/8th of the overall available space, and 601 * larger than 1/8th of the overall available space, and
602 * we only reserve 1/8th for "fresh" insertions */GNUNET_log ( 602 * we only reserve 1/8th for "fresh" insertions */
603 GNUNET_log (
603 GNUNET_ERROR_TYPE_WARNING, 604 GNUNET_ERROR_TYPE_WARNING,
604 _ ( 605 _ (
605 "The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"), 606 "The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"),
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 96399cb5a..727f1a1f6 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -1048,8 +1048,7 @@ GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph)
1048 1048
1049 1049
1050/** 1050/**
1051 * Perform an asynchronous GET operation on the DHT identified. See 1051 * Perform an asynchronous GET operation on the DHT identified.
1052 * also #GNUNET_BLOCK_evaluate.
1053 * 1052 *
1054 * @param handle handle to the DHT service 1053 * @param handle handle to the DHT service
1055 * @param type expected type of the response object 1054 * @param type expected type of the response object
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index 6741efb4e..e9b1ff63a 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -26,10 +26,10 @@
26#ifndef GNUNET_SERVICE_DHT_H 26#ifndef GNUNET_SERVICE_DHT_H
27#define GNUNET_SERVICE_DHT_H 27#define GNUNET_SERVICE_DHT_H
28 28
29#include "gnunet_util_lib.h" 29#include "gnunet-service-dht_datacache.h"
30#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
31#include "gnunet_transport_service.h" 31#include "gnunet_transport_service.h"
32#include "gnunet_block_lib.h" 32
33 33
34#define DEBUG_DHT GNUNET_EXTRA_LOGGING 34#define DEBUG_DHT GNUNET_EXTRA_LOGGING
35 35
@@ -64,26 +64,16 @@ extern struct GNUNET_MessageHeader *GDS_my_hello;
64 * matches any of our pending queries, forward it to the respective 64 * matches any of our pending queries, forward it to the respective
65 * client(s). 65 * client(s).
66 * 66 *
67 * @param expiration when will the reply expire 67 * @param bd block details
68 * @param key the query this reply is for 68 * @param query_hash hash of the original query, might not match key in @a bd
69 * @param get_path_length number of peers in @a get_path 69 * @param get_path_length number of entries in @a get_path
70 * @param get_path path the reply took on get 70 * @param get_path path the reply has taken
71 * @param put_path_length number of peers in @a put_path
72 * @param put_path path the reply took on put
73 * @param type type of the reply
74 * @param data_size number of bytes in @a data
75 * @param data application payload data
76 */ 71 */
77void 72void
78GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, 73GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
79 const struct GNUNET_HashCode *key, 74 const struct GNUNET_HashCode *query_hash,
80 unsigned int get_path_length, 75 unsigned int get_path_length,
81 const struct GNUNET_PeerIdentity *get_path, 76 const struct GNUNET_PeerIdentity *get_path);
82 unsigned int put_path_length,
83 const struct GNUNET_PeerIdentity *put_path,
84 enum GNUNET_BLOCK_Type type,
85 size_t data_size,
86 const void *data);
87 77
88 78
89/** 79/**
@@ -99,7 +89,7 @@ GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
99 * @param key Key of the requested data. 89 * @param key Key of the requested data.
100 */ 90 */
101void 91void
102GDS_CLIENTS_process_get (uint32_t options, 92GDS_CLIENTS_process_get (enum GNUNET_DHT_RouteOption options,
103 enum GNUNET_BLOCK_Type type, 93 enum GNUNET_BLOCK_Type type,
104 uint32_t hop_count, 94 uint32_t hop_count,
105 uint32_t desired_replication_level, 95 uint32_t desired_replication_level,
@@ -112,53 +102,30 @@ GDS_CLIENTS_process_get (uint32_t options,
112 * Check if some client is monitoring GET RESP messages and notify 102 * Check if some client is monitoring GET RESP messages and notify
113 * them in that case. 103 * them in that case.
114 * 104 *
115 * @param type The type of data in the result. 105 * @param bd block details
116 * @param get_path Peers on GET path (or NULL if not recorded). 106 * @param get_path Peers on GET path (or NULL if not recorded).
117 * @param get_path_length number of entries in @a get_path. 107 * @param get_path_length number of entries in @a get_path.
118 * @param put_path peers on the PUT path (or NULL if not recorded).
119 * @param put_path_length number of entries in @a get_path.
120 * @param exp Expiration time of the data.
121 * @param key Key of the @a data.
122 * @param data Pointer to the result data.
123 * @param size Number of bytes in @a data.
124 */ 108 */
125void 109void
126GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, 110GDS_CLIENTS_process_get_resp (const struct GDS_DATACACHE_BlockData *bd,
127 const struct GNUNET_PeerIdentity *get_path, 111 const struct GNUNET_PeerIdentity *get_path,
128 unsigned int get_path_length, 112 unsigned int get_path_length);
129 const struct GNUNET_PeerIdentity *put_path,
130 unsigned int put_path_length,
131 struct GNUNET_TIME_Absolute exp,
132 const struct GNUNET_HashCode *key,
133 const void *data,
134 size_t size);
135 113
136 114
137/** 115/**
138 * Check if some client is monitoring PUT messages and notify 116 * Check if some client is monitoring PUT messages and notify
139 * them in that case. 117 * them in that case. The @a path should include our own
118 * peer ID (if recorded).
140 * 119 *
141 * @param options Options, for instance RecordRoute, DemultiplexEverywhere. 120 * @param options routing options to apply
142 * @param type The type of data in the request. 121 * @param bd details about the block
143 * @param hop_count Hop count so far. 122 * @param hop_count Hop count so far.
144 * @param path_length number of entries in path (or 0 if not recorded).
145 * @param path peers on the PUT path (or NULL if not recorded).
146 * @param desired_replication_level Desired replication level. 123 * @param desired_replication_level Desired replication level.
147 * @param exp Expiration time of the data.
148 * @param key Key under which data is to be stored.
149 * @param data Pointer to the data carried.
150 * @param size Number of bytes in data.
151 */ 124 */
152void 125void
153GDS_CLIENTS_process_put (uint32_t options, 126GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
154 enum GNUNET_BLOCK_Type type, 127 const struct GDS_DATACACHE_BlockData *bd,
155 uint32_t hop_count, 128 uint32_t hop_count,
156 uint32_t desired_replication_level, 129 uint32_t desired_replication_level);
157 unsigned int path_length,
158 const struct GNUNET_PeerIdentity *path,
159 struct GNUNET_TIME_Absolute exp,
160 const struct GNUNET_HashCode *key,
161 const void *data,
162 size_t size);
163 130
164#endif 131#endif
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index cfcb25336..245130dbc 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2016, 2017 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 2016, 2017, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -83,7 +83,7 @@ struct ClientQueryRecord
83 const void *xquery; 83 const void *xquery;
84 84
85 /** 85 /**
86 * Replies we have already seen for this request. 86 * Array of (hashes of) replies we have already seen for this request.
87 */ 87 */
88 struct GNUNET_HashCode *seen_replies; 88 struct GNUNET_HashCode *seen_replies;
89 89
@@ -114,7 +114,7 @@ struct ClientQueryRecord
114 size_t xquery_size; 114 size_t xquery_size;
115 115
116 /** 116 /**
117 * Number of entries in 'seen_replies'. 117 * Number of entries in @e seen_replies.
118 */ 118 */
119 unsigned int seen_replies_count; 119 unsigned int seen_replies_count;
120 120
@@ -126,7 +126,7 @@ struct ClientQueryRecord
126 /** 126 /**
127 * Any message options for this request 127 * Any message options for this request
128 */ 128 */
129 uint32_t msg_options; 129 enum GNUNET_DHT_RouteOption msg_options;
130 130
131 /** 131 /**
132 * The type for the data for the GET request. 132 * The type for the data for the GET request.
@@ -151,14 +151,19 @@ struct ClientMonitorRecord
151 struct ClientMonitorRecord *prev; 151 struct ClientMonitorRecord *prev;
152 152
153 /** 153 /**
154 * Type of blocks that are of interest 154 * Client to notify of these requests.
155 */ 155 */
156 enum GNUNET_BLOCK_Type type; 156 struct ClientHandle *ch;
157
158 /**
159 * Key of data of interest. All bits zero for 'all'.
160 */
161 struct GNUNET_HashCode key;
157 162
158 /** 163 /**
159 * Key of data of interest, NULL for all. 164 * Type of blocks that are of interest
160 */ 165 */
161 struct GNUNET_HashCode *key; 166 enum GNUNET_BLOCK_Type type;
162 167
163 /** 168 /**
164 * Flag whether to notify about GET messages. 169 * Flag whether to notify about GET messages.
@@ -175,10 +180,6 @@ struct ClientMonitorRecord
175 */ 180 */
176 uint16_t put; 181 uint16_t put;
177 182
178 /**
179 * Client to notify of these requests.
180 */
181 struct ClientHandle *ch;
182}; 183};
183 184
184 185
@@ -210,6 +211,7 @@ struct ClientHandle
210 struct GNUNET_MQ_Handle *mq; 211 struct GNUNET_MQ_Handle *mq;
211}; 212};
212 213
214
213/** 215/**
214 * Our handle to the BLOCK library. 216 * Our handle to the BLOCK library.
215 */ 217 */
@@ -262,7 +264,7 @@ static struct GNUNET_SCHEDULER_Task *retry_task;
262 * @param record record to remove 264 * @param record record to remove
263 */ 265 */
264static void 266static void
265remove_client_record (struct ClientQueryRecord *record) 267remove_client_query_record (struct ClientQueryRecord *record)
266{ 268{
267 struct ClientHandle *ch = record->ch; 269 struct ClientHandle *ch = record->ch;
268 270
@@ -298,6 +300,7 @@ client_connect_cb (void *cls,
298{ 300{
299 struct ClientHandle *ch; 301 struct ClientHandle *ch;
300 302
303 (void) cls;
301 ch = GNUNET_new (struct ClientHandle); 304 ch = GNUNET_new (struct ClientHandle);
302 ch->client = client; 305 ch->client = client;
303 ch->mq = mq; 306 ch->mq = mq;
@@ -319,34 +322,35 @@ client_disconnect_cb (void *cls,
319 void *app_ctx) 322 void *app_ctx)
320{ 323{
321 struct ClientHandle *ch = app_ctx; 324 struct ClientHandle *ch = app_ctx;
322 struct ClientQueryRecord *cqr;
323 struct ClientMonitorRecord *monitor;
324 325
326 (void) cls;
327 (void) client;
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326 "Local client %p disconnects\n", 329 "Local client %p disconnects\n",
327 ch); 330 ch);
328 monitor = monitor_head;
329 while (NULL != monitor)
330 { 331 {
331 if (monitor->ch == ch) 332 struct ClientMonitorRecord *next;
332 {
333 struct ClientMonitorRecord *next;
334 333
334 for (struct ClientMonitorRecord *monitor = monitor_head;
335 NULL != monitor;
336 monitor = next)
337 {
335 next = monitor->next; 338 next = monitor->next;
336 GNUNET_free (monitor->key); 339 if (monitor->ch != ch)
340 continue;
337 GNUNET_CONTAINER_DLL_remove (monitor_head, 341 GNUNET_CONTAINER_DLL_remove (monitor_head,
338 monitor_tail, 342 monitor_tail,
339 monitor); 343 monitor);
340 GNUNET_free (monitor); 344 GNUNET_free (monitor);
341 monitor = next;
342 }
343 else
344 {
345 monitor = monitor->next;
346 } 345 }
347 } 346 }
348 while (NULL != (cqr = ch->cqr_head)) 347
349 remove_client_record (cqr); 348 {
349 struct ClientQueryRecord *cqr;
350
351 while (NULL != (cqr = ch->cqr_head))
352 remove_client_query_record (cqr);
353 }
350 GNUNET_free (ch); 354 GNUNET_free (ch);
351} 355}
352 356
@@ -355,6 +359,8 @@ client_disconnect_cb (void *cls,
355 * Route the given request via the DHT. This includes updating 359 * Route the given request via the DHT. This includes updating
356 * the bloom filter and retransmission times, building the P2P 360 * the bloom filter and retransmission times, building the P2P
357 * message and initiating the routing operation. 361 * message and initiating the routing operation.
362 *
363 * @param cqr request to transmit
358 */ 364 */
359static void 365static void
360transmit_request (struct ClientQueryRecord *cqr) 366transmit_request (struct ClientQueryRecord *cqr)
@@ -363,8 +369,7 @@ transmit_request (struct ClientQueryRecord *cqr)
363 struct GNUNET_CONTAINER_BloomFilter *peer_bf; 369 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
364 370
365 GNUNET_STATISTICS_update (GDS_stats, 371 GNUNET_STATISTICS_update (GDS_stats,
366 gettext_noop ( 372 "# GET requests from clients injected",
367 "# GET requests from clients injected"),
368 1, 373 1,
369 GNUNET_NO); 374 GNUNET_NO);
370 bg = GNUNET_BLOCK_group_create (GDS_block_context, 375 bg = GNUNET_BLOCK_group_create (GDS_block_context,
@@ -372,8 +377,8 @@ transmit_request (struct ClientQueryRecord *cqr)
372 GNUNET_CRYPTO_random_u32 ( 377 GNUNET_CRYPTO_random_u32 (
373 GNUNET_CRYPTO_QUALITY_WEAK, 378 GNUNET_CRYPTO_QUALITY_WEAK,
374 UINT32_MAX), 379 UINT32_MAX),
375 NULL, 380 NULL, /* raw data */
376 0, 381 0, /* raw data size */
377 "seen-set-size", 382 "seen-set-size",
378 cqr->seen_replies_count, 383 cqr->seen_replies_count,
379 NULL); 384 NULL);
@@ -401,8 +406,8 @@ transmit_request (struct ClientQueryRecord *cqr)
401 GNUNET_BLOCK_group_destroy (bg); 406 GNUNET_BLOCK_group_destroy (bg);
402 GNUNET_CONTAINER_bloomfilter_free (peer_bf); 407 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
403 408
404 /* exponential back-off for retries. 409 /* Exponential back-off for retries.
405 * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */ 410 * max. is #GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */
406 cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency); 411 cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency);
407 cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency); 412 cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency);
408} 413}
@@ -419,14 +424,13 @@ static void
419transmit_next_request_task (void *cls) 424transmit_next_request_task (void *cls)
420{ 425{
421 struct ClientQueryRecord *cqr; 426 struct ClientQueryRecord *cqr;
422 struct GNUNET_TIME_Relative delay;
423 427
428 (void) cls;
424 retry_task = NULL; 429 retry_task = NULL;
425 while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap))) 430 while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap)))
426 { 431 {
427 cqr->hnode = NULL; 432 cqr->hnode = NULL;
428 delay = GNUNET_TIME_absolute_get_remaining (cqr->retry_time); 433 if (! GNUNET_TIME_absolute_is_past (cqr->retry_time))
429 if (delay.rel_value_us > 0)
430 { 434 {
431 cqr->hnode 435 cqr->hnode
432 = GNUNET_CONTAINER_heap_insert (retry_heap, 436 = GNUNET_CONTAINER_heap_insert (retry_heap,
@@ -454,11 +458,18 @@ transmit_next_request_task (void *cls)
454 * @param dht_msg the actual message received 458 * @param dht_msg the actual message received
455 * @return #GNUNET_OK (always) 459 * @return #GNUNET_OK (always)
456 */ 460 */
457static int 461static enum GNUNET_GenericReturnValue
458check_dht_local_put (void *cls, 462check_dht_local_put (void *cls,
459 const struct GNUNET_DHT_ClientPutMessage *dht_msg) 463 const struct GNUNET_DHT_ClientPutMessage *dht_msg)
460{ 464{
461 /* always well-formed */ 465 uint32_t replication_level = ntohl (dht_msg->desired_replication_level);
466
467 (void) cls;
468 if (replication_level > GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL)
469 {
470 GNUNET_break_op (0);
471 return GNUNET_SYSERR;
472 }
462 return GNUNET_OK; 473 return GNUNET_OK;
463} 474}
464 475
@@ -474,125 +485,108 @@ handle_dht_local_put (void *cls,
474 const struct GNUNET_DHT_ClientPutMessage *dht_msg) 485 const struct GNUNET_DHT_ClientPutMessage *dht_msg)
475{ 486{
476 struct ClientHandle *ch = cls; 487 struct ClientHandle *ch = cls;
477 struct GNUNET_CONTAINER_BloomFilter *peer_bf; 488 uint16_t size = ntohs (dht_msg->header.size);
478 uint16_t size; 489 enum GNUNET_DHT_RouteOption options
490 = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options);
491 uint32_t replication_level
492 = ntohl (dht_msg->desired_replication_level);
493 struct GDS_DATACACHE_BlockData bd = {
494 .key = dht_msg->key,
495 .expiration_time = GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
496 .data = &dht_msg[1],
497 .data_size = size - sizeof (*dht_msg),
498 .type = ntohl (dht_msg->type)
499 };
479 500
480 size = ntohs (dht_msg->header.size); 501 LOG (GNUNET_ERROR_TYPE_DEBUG,
502 "Handling local PUT of %lu-bytes for query %s of type %u\n",
503 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
504 GNUNET_h2s (&dht_msg->key),
505 (unsigned int) bd.type);
481 GNUNET_STATISTICS_update (GDS_stats, 506 GNUNET_STATISTICS_update (GDS_stats,
482 gettext_noop ( 507 "# PUT requests received from clients",
483 "# PUT requests received from clients"),
484 1, 508 1,
485 GNUNET_NO); 509 GNUNET_NO);
486 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 510 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
487 "CLIENT-PUT %s\n", 511 "CLIENT-PUT %s\n",
488 GNUNET_h2s_full (&dht_msg->key)); 512 GNUNET_h2s_full (&dht_msg->key));
489 /* give to local clients */ 513 /* give to local clients */
490 LOG (GNUNET_ERROR_TYPE_DEBUG, 514 GDS_CLIENTS_handle_reply (&bd,
491 "Handling local PUT of %lu-bytes for query %s\n", 515 &bd.key,
492 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)), 516 0, NULL /* get path */);
493 GNUNET_h2s (&dht_msg->key)); 517
494 GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 518 {
495 &dht_msg->key, 519 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
496 0, 520
497 NULL, 521 peer_bf
498 0, 522 = GNUNET_CONTAINER_bloomfilter_init (NULL,
499 NULL, 523 DHT_BLOOM_SIZE,
500 ntohl (dht_msg->type), 524 GNUNET_CONSTANTS_BLOOMFILTER_K);
501 size - sizeof(struct GNUNET_DHT_ClientPutMessage), 525 /* store locally */
502 &dht_msg[1]); 526 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
503 /* store locally */ 527 (GDS_am_closest_peer (&dht_msg->key,
504 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 528 peer_bf)))
505 &dht_msg->key, 529 GDS_DATACACHE_handle_put (&bd);
506 0, 530 /* route to other peers */
507 NULL, 531 if (GNUNET_OK !=
508 ntohl (dht_msg->type), 532 GDS_NEIGHBOURS_handle_put (&bd,
509 size - sizeof(struct GNUNET_DHT_ClientPutMessage), 533 options,
510 &dht_msg[1]); 534 replication_level,
511 /* route to other peers */ 535 0 /* hop count */,
512 peer_bf 536 peer_bf))
513 = GNUNET_CONTAINER_bloomfilter_init (NULL, 537 {
514 DHT_BLOOM_SIZE, 538 GNUNET_STATISTICS_update (GDS_stats,
515 GNUNET_CONSTANTS_BLOOMFILTER_K); 539 "# Local PUT requests not routed",
516 GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type), 540 1,
517 ntohl (dht_msg->options), 541 GNUNET_NO);
518 ntohl (dht_msg->desired_replication_level), 542 }
519 GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 543 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
520 0 /* hop count */, 544 }
521 peer_bf, 545 GDS_CLIENTS_process_put (
522 &dht_msg->key, 546 options,
523 0, 547 &bd,
524 NULL, 548 0, /* hop count */
525 &dht_msg[1], 549 replication_level);
526 size - sizeof(struct GNUNET_DHT_ClientPutMessage));
527 GDS_CLIENTS_process_put (ntohl (dht_msg->options),
528 ntohl (dht_msg->type),
529 0,
530 ntohl (dht_msg->desired_replication_level),
531 1,
532 GDS_NEIGHBOURS_get_id (),
533 GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
534 &dht_msg->key,
535 &dht_msg[1],
536 size - sizeof(struct GNUNET_DHT_ClientPutMessage));
537 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
538 GNUNET_SERVICE_client_continue (ch->client); 550 GNUNET_SERVICE_client_continue (ch->client);
539} 551}
540 552
541 553
542/** 554/**
555 * Handle a result from local datacache for a GET operation.
556 *
557 * @param cls the `struct ClientHandle` of the client doing the query
558 * @param bd details about the block that was found
559 */
560static void
561handle_local_result (void *cls,
562 const struct GDS_DATACACHE_BlockData *bd)
563{
564 /* FIXME: use 'cls' instead of looking up the client? */
565 GDS_CLIENTS_handle_reply (bd,
566 &bd->key,
567 0, NULL /* get_path */);
568}
569
570
571/**
543 * Check DHT GET messages from the client. 572 * Check DHT GET messages from the client.
544 * 573 *
545 * @param cls the client we received this message from 574 * @param cls the client we received this message from
546 * @param message the actual message received 575 * @param message the actual message received
547 * @return #GNUNET_OK (always) 576 * @return #GNUNET_OK (always)
548 */ 577 */
549static int 578static enum GNUNET_GenericReturnValue
550check_dht_local_get (void *cls, 579check_dht_local_get (void *cls,
551 const struct GNUNET_DHT_ClientGetMessage *get) 580 const struct GNUNET_DHT_ClientGetMessage *get)
552{ 581{
582 (void) cls;
583 (void) get;
553 /* always well-formed */ 584 /* always well-formed */
554 return GNUNET_OK; 585 return GNUNET_OK;
555} 586}
556 587
557 588
558/** 589/**
559 * Handle a result from local datacache for a GET operation.
560 *
561 * @param cls the `struct ClientHandle` of the client doing the query
562 * @param type type of the block
563 * @param expiration_time when does the content expire
564 * @param key key for the content
565 * @param put_path_length number of entries in @a put_path
566 * @param put_path peers the original PUT traversed (if tracked)
567 * @param get_path_length number of entries in @a get_path
568 * @param get_path peers this reply has traversed so far (if tracked)
569 * @param data payload of the reply
570 * @param data_size number of bytes in @a data
571 */
572static void
573handle_local_result (void *cls,
574 enum GNUNET_BLOCK_Type type,
575 struct GNUNET_TIME_Absolute expiration_time,
576 const struct GNUNET_HashCode *key,
577 unsigned int put_path_length,
578 const struct GNUNET_PeerIdentity *put_path,
579 unsigned int get_path_length,
580 const struct GNUNET_PeerIdentity *get_path,
581 const void *data,
582 size_t data_size)
583{
584 // FIXME: this needs some clean up: inline the function,
585 // possibly avoid even looking up the client!
586 GDS_CLIENTS_handle_reply (expiration_time,
587 key,
588 0, NULL,
589 put_path_length, put_path,
590 type,
591 data_size, data);
592}
593
594
595/**
596 * Handler for DHT GET messages from the client. 590 * Handler for DHT GET messages from the client.
597 * 591 *
598 * @param cls the client we received this message from 592 * @param cls the client we received this message from
@@ -604,23 +598,20 @@ handle_dht_local_get (void *cls,
604{ 598{
605 struct ClientHandle *ch = cls; 599 struct ClientHandle *ch = cls;
606 struct ClientQueryRecord *cqr; 600 struct ClientQueryRecord *cqr;
607 size_t xquery_size; 601 uint16_t size = ntohs (get->header.size);
608 const char *xquery; 602 const char *xquery = (const char *) &get[1];
609 uint16_t size; 603 size_t xquery_size = size - sizeof(struct GNUNET_DHT_ClientGetMessage);
610 604
611 size = ntohs (get->header.size);
612 xquery_size = size - sizeof(struct GNUNET_DHT_ClientGetMessage);
613 xquery = (const char *) &get[1];
614 GNUNET_STATISTICS_update (GDS_stats,
615 gettext_noop
616 ("# GET requests received from clients"), 1,
617 GNUNET_NO);
618 LOG (GNUNET_ERROR_TYPE_DEBUG, 605 LOG (GNUNET_ERROR_TYPE_DEBUG,
619 "Received GET request for %s from local client %p, xq: %.*s\n", 606 "Received GET request for %s from local client %p, xq: %.*s\n",
620 GNUNET_h2s (&get->key), 607 GNUNET_h2s (&get->key),
621 ch->client, 608 ch->client,
622 (int) xquery_size, 609 (int) xquery_size,
623 xquery); 610 xquery);
611 GNUNET_STATISTICS_update (GDS_stats,
612 "# GET requests received from clients",
613 1,
614 GNUNET_NO);
624 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 615 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
625 "CLIENT-GET %s\n", 616 "CLIENT-GET %s\n",
626 GNUNET_h2s_full (&get->key)); 617 GNUNET_h2s_full (&get->key));
@@ -628,15 +619,19 @@ handle_dht_local_get (void *cls,
628 cqr = GNUNET_malloc (sizeof(struct ClientQueryRecord) + xquery_size); 619 cqr = GNUNET_malloc (sizeof(struct ClientQueryRecord) + xquery_size);
629 cqr->key = get->key; 620 cqr->key = get->key;
630 cqr->ch = ch; 621 cqr->ch = ch;
631 cqr->xquery = (void *) &cqr[1]; 622 cqr->xquery = (const void *) &cqr[1];
632 GNUNET_memcpy (&cqr[1], xquery, xquery_size); 623 GNUNET_memcpy (&cqr[1],
633 cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0); 624 xquery,
625 xquery_size);
626 cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap,
627 cqr,
628 0);
634 cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS; 629 cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS;
635 cqr->retry_time = GNUNET_TIME_absolute_get (); 630 cqr->retry_time = GNUNET_TIME_absolute_get ();
636 cqr->unique_id = get->unique_id; 631 cqr->unique_id = get->unique_id;
637 cqr->xquery_size = xquery_size; 632 cqr->xquery_size = xquery_size;
638 cqr->replication = ntohl (get->desired_replication_level); 633 cqr->replication = ntohl (get->desired_replication_level);
639 cqr->msg_options = ntohl (get->options); 634 cqr->msg_options = (enum GNUNET_DHT_RouteOption) ntohl (get->options);
640 cqr->type = ntohl (get->type); 635 cqr->type = ntohl (get->type);
641 GNUNET_CONTAINER_DLL_insert (ch->cqr_head, 636 GNUNET_CONTAINER_DLL_insert (ch->cqr_head,
642 ch->cqr_tail, 637 ch->cqr_tail,
@@ -645,11 +640,11 @@ handle_dht_local_get (void *cls,
645 &cqr->key, 640 &cqr->key,
646 cqr, 641 cqr,
647 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 642 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
648 GDS_CLIENTS_process_get (ntohl (get->options), 643 GDS_CLIENTS_process_get (cqr->msg_options,
649 ntohl (get->type), 644 cqr->type,
650 0, 645 0, /* hop count */
651 ntohl (get->desired_replication_level), 646 cqr->replication,
652 1, 647 1, /* path length */
653 GDS_NEIGHBOURS_get_id (), 648 GDS_NEIGHBOURS_get_id (),
654 &get->key); 649 &get->key);
655 /* start remote requests */ 650 /* start remote requests */
@@ -679,6 +674,9 @@ struct FindByUniqueIdContext
679 */ 674 */
680 struct ClientQueryRecord *cqr; 675 struct ClientQueryRecord *cqr;
681 676
677 /**
678 * Unique ID to look for.
679 */
682 uint64_t unique_id; 680 uint64_t unique_id;
683}; 681};
684 682
@@ -693,7 +691,7 @@ struct FindByUniqueIdContext
693 * @param value the `struct ClientQueryRecord` 691 * @param value the `struct ClientQueryRecord`
694 * @return #GNUNET_YES to continue iteration (result not yet found) 692 * @return #GNUNET_YES to continue iteration (result not yet found)
695 */ 693 */
696static int 694static enum GNUNET_GenericReturnValue
697find_by_unique_id (void *cls, 695find_by_unique_id (void *cls,
698 const struct GNUNET_HashCode *key, 696 const struct GNUNET_HashCode *key,
699 void *value) 697 void *value)
@@ -715,19 +713,17 @@ find_by_unique_id (void *cls,
715 * @param message the actual message received 713 * @param message the actual message received
716 * @return #GNUNET_OK if @a seen is well-formed 714 * @return #GNUNET_OK if @a seen is well-formed
717 */ 715 */
718static int 716static enum GNUNET_GenericReturnValue
719check_dht_local_get_result_seen (void *cls, 717check_dht_local_get_result_seen (
720 const struct 718 void *cls,
721 GNUNET_DHT_ClientGetResultSeenMessage *seen) 719 const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
722{ 720{
723 uint16_t size; 721 uint16_t size = ntohs (seen->header.size);
724 unsigned int hash_count; 722 unsigned int hash_count =
725 723 (size - sizeof(*seen))
726 size = ntohs (seen->header.size); 724 / sizeof(struct GNUNET_HashCode);
727 hash_count = (size - sizeof(struct GNUNET_DHT_ClientGetResultSeenMessage)) 725
728 / sizeof(struct GNUNET_HashCode); 726 if (size != sizeof(*seen) + hash_count * sizeof(struct GNUNET_HashCode))
729 if (size != sizeof(struct GNUNET_DHT_ClientGetResultSeenMessage)
730 + hash_count * sizeof(struct GNUNET_HashCode))
731 { 727 {
732 GNUNET_break (0); 728 GNUNET_break (0);
733 return GNUNET_SYSERR; 729 return GNUNET_SYSERR;
@@ -743,24 +739,21 @@ check_dht_local_get_result_seen (void *cls,
743 * @param message the actual message received 739 * @param message the actual message received
744 */ 740 */
745static void 741static void
746handle_dht_local_get_result_seen (void *cls, 742handle_dht_local_get_result_seen (
747 const struct 743 void *cls,
748 GNUNET_DHT_ClientGetResultSeenMessage *seen) 744 const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
749{ 745{
750 struct ClientHandle *ch = cls; 746 struct ClientHandle *ch = cls;
751 uint16_t size; 747 uint16_t size = ntohs (seen->header.size);
752 unsigned int hash_count; 748 unsigned int hash_count = (size - sizeof(*seen))
749 / sizeof(struct GNUNET_HashCode);
750 const struct GNUNET_HashCode *hc = (const struct GNUNET_HashCode*) &seen[1];
751 struct FindByUniqueIdContext fui_ctx = {
752 .unique_id = seen->unique_id
753 };
753 unsigned int old_count; 754 unsigned int old_count;
754 const struct GNUNET_HashCode *hc;
755 struct FindByUniqueIdContext fui_ctx;
756 struct ClientQueryRecord *cqr; 755 struct ClientQueryRecord *cqr;
757 756
758 size = ntohs (seen->header.size);
759 hash_count = (size - sizeof(struct GNUNET_DHT_ClientGetResultSeenMessage))
760 / sizeof(struct GNUNET_HashCode);
761 hc = (const struct GNUNET_HashCode*) &seen[1];
762 fui_ctx.unique_id = seen->unique_id;
763 fui_ctx.cqr = NULL;
764 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, 757 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
765 &seen->key, 758 &seen->key,
766 &find_by_unique_id, 759 &find_by_unique_id,
@@ -808,7 +801,7 @@ struct RemoveByUniqueIdContext
808 * @param value value in the hash map, a ClientQueryRecord 801 * @param value value in the hash map, a ClientQueryRecord
809 * @return #GNUNET_YES (we should continue to iterate) 802 * @return #GNUNET_YES (we should continue to iterate)
810 */ 803 */
811static int 804static enum GNUNET_GenericReturnValue
812remove_by_unique_id (void *cls, 805remove_by_unique_id (void *cls,
813 const struct GNUNET_HashCode *key, 806 const struct GNUNET_HashCode *key,
814 void *value) 807 void *value)
@@ -822,7 +815,7 @@ remove_by_unique_id (void *cls,
822 "Removing client %p's record for key %s (by unique id)\n", 815 "Removing client %p's record for key %s (by unique id)\n",
823 ctx->ch->client, 816 ctx->ch->client,
824 GNUNET_h2s (key)); 817 GNUNET_h2s (key));
825 remove_client_record (cqr); 818 remove_client_query_record (cqr);
826 return GNUNET_YES; 819 return GNUNET_YES;
827} 820}
828 821
@@ -836,16 +829,16 @@ remove_by_unique_id (void *cls,
836 * 829 *
837 */ 830 */
838static void 831static void
839handle_dht_local_get_stop (void *cls, 832handle_dht_local_get_stop (
840 const struct 833 void *cls,
841 GNUNET_DHT_ClientGetStopMessage *dht_stop_msg) 834 const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg)
842{ 835{
843 struct ClientHandle *ch = cls; 836 struct ClientHandle *ch = cls;
844 struct RemoveByUniqueIdContext ctx; 837 struct RemoveByUniqueIdContext ctx;
845 838
846 GNUNET_STATISTICS_update (GDS_stats, 839 GNUNET_STATISTICS_update (GDS_stats,
847 gettext_noop 840 "# GET STOP requests received from clients",
848 ("# GET STOP requests received from clients"), 1, 841 1,
849 GNUNET_NO); 842 GNUNET_NO);
850 LOG (GNUNET_ERROR_TYPE_DEBUG, 843 LOG (GNUNET_ERROR_TYPE_DEBUG,
851 "Received GET STOP request for %s from local client %p\n", 844 "Received GET STOP request for %s from local client %p\n",
@@ -862,99 +855,14 @@ handle_dht_local_get_stop (void *cls,
862 855
863 856
864/** 857/**
865 * Handler for monitor start messages
866 *
867 * @param cls the client we received this message from
868 * @param msg the actual message received
869 *
870 */
871static void
872handle_dht_local_monitor (void *cls,
873 const struct GNUNET_DHT_MonitorStartStopMessage *msg)
874{
875 struct ClientHandle *ch = cls;
876 struct ClientMonitorRecord *r;
877
878 r = GNUNET_new (struct ClientMonitorRecord);
879 r->ch = ch;
880 r->type = ntohl (msg->type);
881 r->get = ntohs (msg->get);
882 r->get_resp = ntohs (msg->get_resp);
883 r->put = ntohs (msg->put);
884 if (0 == ntohs (msg->filter_key))
885 {
886 r->key = NULL;
887 }
888 else
889 {
890 r->key = GNUNET_new (struct GNUNET_HashCode);
891 GNUNET_memcpy (r->key,
892 &msg->key,
893 sizeof(struct GNUNET_HashCode));
894 }
895 GNUNET_CONTAINER_DLL_insert (monitor_head,
896 monitor_tail,
897 r);
898 GNUNET_SERVICE_client_continue (ch->client);
899}
900
901
902/**
903 * Handler for monitor stop messages
904 *
905 * @param cls the client we received this message from
906 * @param msg the actual message received
907 */
908static void
909handle_dht_local_monitor_stop (void *cls,
910 const struct
911 GNUNET_DHT_MonitorStartStopMessage *msg)
912{
913 struct ClientHandle *ch = cls;
914 struct ClientMonitorRecord *r;
915 int keys_match;
916
917 GNUNET_SERVICE_client_continue (ch->client);
918 for (r = monitor_head; NULL != r; r = r->next)
919 {
920 if (NULL == r->key)
921 {
922 keys_match = (0 == ntohs (msg->filter_key));
923 }
924 else
925 {
926 keys_match = ((0 != ntohs (msg->filter_key)) &&
927 (! memcmp (r->key,
928 &msg->key,
929 sizeof(struct GNUNET_HashCode))));
930 }
931 if ((ch == r->ch) &&
932 (ntohl (msg->type) == r->type) &&
933 (r->get == msg->get) &&
934 (r->get_resp == msg->get_resp) &&
935 (r->put == msg->put) &&
936 keys_match)
937 {
938 GNUNET_CONTAINER_DLL_remove (monitor_head,
939 monitor_tail,
940 r);
941 GNUNET_free (r->key);
942 GNUNET_free (r);
943 return; /* Delete only ONE entry */
944 }
945 }
946}
947
948
949/**
950 * Closure for #forward_reply() 858 * Closure for #forward_reply()
951 */ 859 */
952struct ForwardReplyContext 860struct ForwardReplyContext
953{ 861{
954 /** 862 /**
955 * Expiration time of the reply. 863 * Block details.
956 */ 864 */
957 struct GNUNET_TIME_Absolute expiration; 865 const struct GDS_DATACACHE_BlockData *bd;
958 866
959 /** 867 /**
960 * GET path taken. 868 * GET path taken.
@@ -962,34 +870,10 @@ struct ForwardReplyContext
962 const struct GNUNET_PeerIdentity *get_path; 870 const struct GNUNET_PeerIdentity *get_path;
963 871
964 /** 872 /**
965 * PUT path taken.
966 */
967 const struct GNUNET_PeerIdentity *put_path;
968
969 /**
970 * Embedded payload.
971 */
972 const void *data;
973
974 /**
975 * Number of bytes in data.
976 */
977 size_t data_size;
978
979 /**
980 * Number of entries in @e get_path. 873 * Number of entries in @e get_path.
981 */ 874 */
982 unsigned int get_path_length; 875 unsigned int get_path_length;
983 876
984 /**
985 * Number of entries in @e put_path.
986 */
987 unsigned int put_path_length;
988
989 /**
990 * Type of the data.
991 */
992 enum GNUNET_BLOCK_Type type;
993}; 877};
994 878
995 879
@@ -998,334 +882,298 @@ struct ForwardReplyContext
998 * each of the matching clients. With some tricky recycling 882 * each of the matching clients. With some tricky recycling
999 * of the buffer. 883 * of the buffer.
1000 * 884 *
1001 * @param cls the 'struct ForwardReplyContext' 885 * @param cls the `struct ForwardReplyContext`
1002 * @param key current key 886 * @param query_hash hash of the query for which this may be a reply
1003 * @param value value in the hash map, a ClientQueryRecord 887 * @param value value in the hash map, a ClientQueryRecord
1004 * @return #GNUNET_YES (we should continue to iterate), 888 * @return #GNUNET_YES (we should continue to iterate),
1005 * if the result is mal-formed, #GNUNET_NO 889 * if the result is mal-formed, #GNUNET_NO
1006 */ 890 */
1007static int 891static enum GNUNET_GenericReturnValue
1008forward_reply (void *cls, 892forward_reply (void *cls,
1009 const struct GNUNET_HashCode *key, 893 const struct GNUNET_HashCode *query_hash,
1010 void *value) 894 void *value)
1011{ 895{
1012 struct ForwardReplyContext *frc = cls; 896 struct ForwardReplyContext *frc = cls;
1013 struct ClientQueryRecord *record = value; 897 struct ClientQueryRecord *record = value;
1014 struct GNUNET_MQ_Envelope *env; 898 struct GNUNET_MQ_Envelope *env;
1015 struct GNUNET_DHT_ClientResultMessage *reply; 899 struct GNUNET_DHT_ClientResultMessage *reply;
1016 enum GNUNET_BLOCK_EvaluationResult eval; 900 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
1017 int do_free; 901 bool do_free;
1018 struct GNUNET_HashCode ch; 902 struct GNUNET_HashCode ch;
1019 struct GNUNET_PeerIdentity *paths; 903 struct GNUNET_PeerIdentity *paths;
1020 904
1021 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 905 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
1022 "CLIENT-RESULT %s\n", 906 "CLIENT-RESULT %s\n",
1023 GNUNET_h2s_full (key)); 907 GNUNET_h2s_full (&frc->bd->key));
1024 if ((record->type != GNUNET_BLOCK_TYPE_ANY) && 908 if ( (record->type != GNUNET_BLOCK_TYPE_ANY) &&
1025 (record->type != frc->type)) 909 (record->type != frc->bd->type) )
1026 { 910 {
1027 LOG (GNUNET_ERROR_TYPE_DEBUG, 911 LOG (GNUNET_ERROR_TYPE_DEBUG,
1028 "Record type mismatch, not passing request for key %s to local client\n", 912 "Record type mismatch, not passing request for key %s to local client\n",
1029 GNUNET_h2s (key)); 913 GNUNET_h2s (&frc->bd->key));
1030 GNUNET_STATISTICS_update (GDS_stats, 914 GNUNET_STATISTICS_update (GDS_stats,
1031 gettext_noop 915 "# Key match, type mismatches in REPLY to CLIENT",
1032 ( 916 1,
1033 "# Key match, type mismatches in REPLY to CLIENT"), 917 GNUNET_NO);
1034 1, GNUNET_NO);
1035 return GNUNET_YES; /* type mismatch */ 918 return GNUNET_YES; /* type mismatch */
1036 } 919 }
1037 GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch); 920 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) &&
921 (0 != GNUNET_memcmp (&frc->bd->key,
922 query_hash)) )
923 {
924 GNUNET_STATISTICS_update (GDS_stats,
925 "# Inexact key match, but exact match required",
926 1,
927 GNUNET_NO);
928 return GNUNET_YES; /* type mismatch */
929 }
930 GNUNET_CRYPTO_hash (frc->bd->data,
931 frc->bd->data_size,
932 &ch);
1038 for (unsigned int i = 0; i < record->seen_replies_count; i++) 933 for (unsigned int i = 0; i < record->seen_replies_count; i++)
1039 if (0 == memcmp (&record->seen_replies[i], 934 if (0 ==
1040 &ch, 935 GNUNET_memcmp (&record->seen_replies[i],
1041 sizeof(struct GNUNET_HashCode))) 936 &ch))
1042 { 937 {
1043 LOG (GNUNET_ERROR_TYPE_DEBUG, 938 LOG (GNUNET_ERROR_TYPE_DEBUG,
1044 "Duplicate reply, not passing request for key %s to local client\n", 939 "Duplicate reply, not passing request for key %s to local client\n",
1045 GNUNET_h2s (key)); 940 GNUNET_h2s (&frc->bd->key));
1046 GNUNET_STATISTICS_update (GDS_stats, 941 GNUNET_STATISTICS_update (GDS_stats,
1047 gettext_noop 942 "# Duplicate REPLIES to CLIENT request dropped",
1048 ( 943 1,
1049 "# Duplicate REPLIES to CLIENT request dropped"), 944 GNUNET_NO);
1050 1, GNUNET_NO);
1051 return GNUNET_YES; /* duplicate */ 945 return GNUNET_YES; /* duplicate */
1052 } 946 }
1053 eval 947 eval
1054 = GNUNET_BLOCK_evaluate (GDS_block_context, 948 = GNUNET_BLOCK_check_reply (GDS_block_context,
1055 record->type, 949 record->type,
1056 NULL, 950 NULL,
1057 GNUNET_BLOCK_EO_NONE, 951 &frc->bd->key,
1058 key, 952 record->xquery,
1059 record->xquery, 953 record->xquery_size,
1060 record->xquery_size, 954 frc->bd->data,
1061 frc->data, 955 frc->bd->data_size);
1062 frc->data_size);
1063 LOG (GNUNET_ERROR_TYPE_DEBUG, 956 LOG (GNUNET_ERROR_TYPE_DEBUG,
1064 "Evaluation result is %d for key %s for local client's query\n", 957 "Evaluation result is %d for key %s for local client's query\n",
1065 (int) eval, 958 (int) eval,
1066 GNUNET_h2s (key)); 959 GNUNET_h2s (&frc->bd->key));
1067 switch (eval) 960 switch (eval)
1068 { 961 {
1069 case GNUNET_BLOCK_EVALUATION_OK_LAST: 962 case GNUNET_BLOCK_REPLY_OK_LAST:
1070 do_free = GNUNET_YES; 963 do_free = true;
1071 break; 964 break;
1072 965 case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
1073 case GNUNET_BLOCK_EVALUATION_OK_MORE: 966 case GNUNET_BLOCK_REPLY_OK_MORE:
1074 GNUNET_array_append (record->seen_replies, 967 GNUNET_array_append (record->seen_replies,
1075 record->seen_replies_count, 968 record->seen_replies_count,
1076 ch); 969 ch);
1077 do_free = GNUNET_NO; 970 do_free = false;
1078 break; 971 break;
1079 972 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
1080 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
1081 /* should be impossible to encounter here */ 973 /* should be impossible to encounter here */
1082 GNUNET_break (0); 974 GNUNET_break (0);
1083 return GNUNET_YES; 975 return GNUNET_YES;
1084 976 case GNUNET_BLOCK_REPLY_INVALID:
1085 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
1086 GNUNET_break_op (0); 977 GNUNET_break_op (0);
1087 return GNUNET_NO; 978 return GNUNET_NO;
1088 979 case GNUNET_BLOCK_REPLY_IRRELEVANT:
1089 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
1090 GNUNET_break (0);
1091 return GNUNET_NO;
1092
1093 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
1094 GNUNET_break (0);
1095 return GNUNET_NO;
1096
1097 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
1098 return GNUNET_YES; 980 return GNUNET_YES;
1099
1100 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
1101 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1102 _ ("Unsupported block type (%u) in request!\n"), record->type);
1103 return GNUNET_NO;
1104
1105 default: 981 default:
1106 GNUNET_break (0); 982 GNUNET_break (0);
1107 return GNUNET_NO; 983 return GNUNET_NO;
1108 } 984 }
1109 GNUNET_STATISTICS_update (GDS_stats, 985 GNUNET_STATISTICS_update (GDS_stats,
1110 gettext_noop ("# RESULTS queued for clients"), 986 "# RESULTS queued for clients",
1111 1, 987 1,
1112 GNUNET_NO); 988 GNUNET_NO);
1113 env = GNUNET_MQ_msg_extra (reply, 989 env = GNUNET_MQ_msg_extra (reply,
1114 frc->data_size 990 frc->bd->data_size
1115 + (frc->get_path_length + frc->put_path_length) 991 + (frc->get_path_length + frc->bd->put_path_length)
1116 * sizeof(struct GNUNET_PeerIdentity), 992 * sizeof(struct GNUNET_PeerIdentity),
1117 GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT); 993 GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT);
1118 reply->type = htonl (frc->type); 994 reply->type = htonl (frc->bd->type);
1119 reply->get_path_length = htonl (frc->get_path_length); 995 reply->get_path_length = htonl (frc->get_path_length);
1120 reply->put_path_length = htonl (frc->put_path_length); 996 reply->put_path_length = htonl (frc->bd->put_path_length);
1121 reply->unique_id = record->unique_id; 997 reply->unique_id = record->unique_id;
1122 reply->expiration = GNUNET_TIME_absolute_hton (frc->expiration); 998 reply->expiration = GNUNET_TIME_absolute_hton (frc->bd->expiration_time);
1123 reply->key = *key; 999 reply->key = frc->bd->key;
1124 paths = (struct GNUNET_PeerIdentity *) &reply[1]; 1000 paths = (struct GNUNET_PeerIdentity *) &reply[1];
1125 GNUNET_memcpy (paths, 1001 GNUNET_memcpy (paths,
1126 frc->put_path, 1002 frc->bd->put_path,
1127 sizeof(struct GNUNET_PeerIdentity) * frc->put_path_length); 1003 sizeof(struct GNUNET_PeerIdentity) * frc->bd->put_path_length);
1128 GNUNET_memcpy (&paths[frc->put_path_length], 1004 GNUNET_memcpy (&paths[frc->bd->put_path_length],
1129 frc->get_path, 1005 frc->get_path,
1130 sizeof(struct GNUNET_PeerIdentity) * frc->get_path_length); 1006 sizeof(struct GNUNET_PeerIdentity) * frc->get_path_length);
1131 GNUNET_memcpy (&paths[frc->get_path_length + frc->put_path_length], 1007 GNUNET_memcpy (&paths[frc->get_path_length + frc->bd->put_path_length],
1132 frc->data, 1008 frc->bd->data,
1133 frc->data_size); 1009 frc->bd->data_size);
1134 LOG (GNUNET_ERROR_TYPE_DEBUG, 1010 LOG (GNUNET_ERROR_TYPE_DEBUG,
1135 "Sending reply to query %s for client %p\n", 1011 "Sending reply to query %s for client %p\n",
1136 GNUNET_h2s (key), 1012 GNUNET_h2s (query_hash),
1137 record->ch->client); 1013 record->ch->client);
1138 GNUNET_MQ_send (record->ch->mq, 1014 GNUNET_MQ_send (record->ch->mq,
1139 env); 1015 env);
1140 if (GNUNET_YES == do_free) 1016 if (GNUNET_YES == do_free)
1141 remove_client_record (record); 1017 remove_client_query_record (record);
1142 return GNUNET_YES; 1018 return GNUNET_YES;
1143} 1019}
1144 1020
1145 1021
1146/**
1147 * Handle a reply we've received from another peer. If the reply
1148 * matches any of our pending queries, forward it to the respective
1149 * client(s).
1150 *
1151 * @param expiration when will the reply expire
1152 * @param key the query this reply is for
1153 * @param get_path_length number of peers in @a get_path
1154 * @param get_path path the reply took on get
1155 * @param put_path_length number of peers in @a put_path
1156 * @param put_path path the reply took on put
1157 * @param type type of the reply
1158 * @param data_size number of bytes in @a data
1159 * @param data application payload data
1160 */
1161void 1022void
1162GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, 1023GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
1163 const struct GNUNET_HashCode *key, 1024 const struct GNUNET_HashCode *query_hash,
1164 unsigned int get_path_length, 1025 unsigned int get_path_length,
1165 const struct GNUNET_PeerIdentity *get_path, 1026 const struct GNUNET_PeerIdentity *get_path)
1166 unsigned int put_path_length,
1167 const struct GNUNET_PeerIdentity *put_path,
1168 enum GNUNET_BLOCK_Type type,
1169 size_t data_size,
1170 const void *data)
1171{ 1027{
1172 struct ForwardReplyContext frc; 1028 struct ForwardReplyContext frc;
1173 size_t msize; 1029 size_t msize = sizeof (struct GNUNET_DHT_ClientResultMessage)
1030 + bd->data_size
1031 + (get_path_length + bd->put_path_length)
1032 * sizeof(struct GNUNET_PeerIdentity);
1174 1033
1175 msize = sizeof(struct GNUNET_DHT_ClientResultMessage) + data_size
1176 + (get_path_length + put_path_length) * sizeof(struct
1177 GNUNET_PeerIdentity);
1178 if (msize >= GNUNET_MAX_MESSAGE_SIZE) 1034 if (msize >= GNUNET_MAX_MESSAGE_SIZE)
1179 { 1035 {
1180 GNUNET_break (0); 1036 GNUNET_break (0);
1181 return; 1037 return;
1182 } 1038 }
1183 if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, 1039 frc.bd = bd;
1184 key)) 1040 frc.get_path = get_path;
1041 frc.get_path_length = get_path_length;
1042 LOG (GNUNET_ERROR_TYPE_DEBUG,
1043 "Forwarding reply for query hash %s to client\n",
1044 GNUNET_h2s (query_hash));
1045 if (0 ==
1046 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
1047 query_hash,
1048 &forward_reply,
1049 &frc))
1185 { 1050 {
1186 LOG (GNUNET_ERROR_TYPE_DEBUG, 1051 LOG (GNUNET_ERROR_TYPE_DEBUG,
1187 "No matching client for reply for key %s\n", 1052 "No matching client for reply for query %s\n",
1188 GNUNET_h2s (key)); 1053 GNUNET_h2s (query_hash));
1189 GNUNET_STATISTICS_update (GDS_stats, 1054 GNUNET_STATISTICS_update (GDS_stats,
1190 gettext_noop ( 1055 "# REPLIES ignored for CLIENTS (no match)",
1191 "# REPLIES ignored for CLIENTS (no match)"),
1192 1, 1056 1,
1193 GNUNET_NO); 1057 GNUNET_NO);
1194 return; /* no matching request, fast exit! */
1195 } 1058 }
1196 frc.expiration = expiration;
1197 frc.get_path = get_path;
1198 frc.put_path = put_path;
1199 frc.data = data;
1200 frc.data_size = data_size;
1201 frc.get_path_length = get_path_length;
1202 frc.put_path_length = put_path_length;
1203 frc.type = type;
1204 LOG (GNUNET_ERROR_TYPE_DEBUG,
1205 "Forwarding reply for key %s to client\n",
1206 GNUNET_h2s (key));
1207 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
1208 key,
1209 &forward_reply,
1210 &frc);
1211} 1059}
1212 1060
1213 1061
1062/* ************* logic for monitors ************** */
1063
1064
1214/** 1065/**
1215 * Check if some client is monitoring GET messages and notify 1066 * Handler for monitor start messages
1216 * them in that case. 1067 *
1068 * @param cls the client we received this message from
1069 * @param msg the actual message received
1217 * 1070 *
1218 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
1219 * @param type The type of data in the request.
1220 * @param hop_count Hop count so far.
1221 * @param path_length number of entries in path (or 0 if not recorded).
1222 * @param path peers on the GET path (or NULL if not recorded).
1223 * @param desired_replication_level Desired replication level.
1224 * @param key Key of the requested data.
1225 */ 1071 */
1226void 1072static void
1227GDS_CLIENTS_process_get (uint32_t options, 1073handle_dht_local_monitor (void *cls,
1228 enum GNUNET_BLOCK_Type type, 1074 const struct GNUNET_DHT_MonitorStartStopMessage *msg)
1229 uint32_t hop_count,
1230 uint32_t desired_replication_level,
1231 unsigned int path_length,
1232 const struct GNUNET_PeerIdentity *path,
1233 const struct GNUNET_HashCode *key)
1234{ 1075{
1235 struct ClientMonitorRecord *m; 1076 struct ClientHandle *ch = cls;
1236 struct ClientHandle **cl; 1077 struct ClientMonitorRecord *r;
1237 unsigned int cl_size;
1238 1078
1239 cl = NULL; 1079 r = GNUNET_new (struct ClientMonitorRecord);
1240 cl_size = 0; 1080 r->ch = ch;
1241 for (m = monitor_head; NULL != m; m = m->next) 1081 r->type = ntohl (msg->type);
1242 { 1082 r->get = ntohs (msg->get);
1243 if (((GNUNET_BLOCK_TYPE_ANY == m->type) || 1083 r->get_resp = ntohs (msg->get_resp);
1244 (m->type == type)) && 1084 r->put = ntohs (msg->put);
1245 ((NULL == m->key) || 1085 if (0 != ntohs (msg->filter_key))
1246 (0 == memcmp (key, 1086 r->key = msg->key;
1247 m->key, 1087 GNUNET_CONTAINER_DLL_insert (monitor_head,
1248 sizeof(struct GNUNET_HashCode))))) 1088 monitor_tail,
1249 { 1089 r);
1250 struct GNUNET_MQ_Envelope *env; 1090 GNUNET_SERVICE_client_continue (ch->client);
1251 struct GNUNET_DHT_MonitorGetMessage *mmsg; 1091}
1252 struct GNUNET_PeerIdentity *msg_path;
1253 size_t msize;
1254 unsigned int i;
1255 1092
1256 /* Don't send duplicates */
1257 for (i = 0; i < cl_size; i++)
1258 if (cl[i] == m->ch)
1259 break;
1260 if (i < cl_size)
1261 continue;
1262 GNUNET_array_append (cl,
1263 cl_size,
1264 m->ch);
1265 1093
1266 msize = path_length * sizeof(struct GNUNET_PeerIdentity); 1094/**
1267 env = GNUNET_MQ_msg_extra (mmsg, 1095 * Handler for monitor stop messages
1268 msize, 1096 *
1269 GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET); 1097 * @param cls the client we received this message from
1270 mmsg->options = htonl (options); 1098 * @param msg the actual message received
1271 mmsg->type = htonl (type); 1099 */
1272 mmsg->hop_count = htonl (hop_count); 1100static void
1273 mmsg->desired_replication_level = htonl (desired_replication_level); 1101handle_dht_local_monitor_stop (
1274 mmsg->get_path_length = htonl (path_length); 1102 void *cls,
1275 mmsg->key = *key; 1103 const struct GNUNET_DHT_MonitorStartStopMessage *msg)
1276 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; 1104{
1277 GNUNET_memcpy (msg_path, 1105 struct ClientHandle *ch = cls;
1278 path, 1106
1279 path_length * sizeof(struct GNUNET_PeerIdentity)); 1107 GNUNET_SERVICE_client_continue (ch->client);
1280 GNUNET_MQ_send (m->ch->mq, 1108 for (struct ClientMonitorRecord *r = monitor_head;
1281 env); 1109 NULL != r;
1110 r = r->next)
1111 {
1112 bool keys_match;
1113
1114 keys_match =
1115 (GNUNET_is_zero (&r->key))
1116 ? (0 == ntohs (msg->filter_key))
1117 : ( (0 != ntohs (msg->filter_key)) &&
1118 (! GNUNET_memcmp (&r->key,
1119 &msg->key)) );
1120 if ( (ch == r->ch) &&
1121 (ntohl (msg->type) == r->type) &&
1122 (r->get == msg->get) &&
1123 (r->get_resp == msg->get_resp) &&
1124 (r->put == msg->put) &&
1125 keys_match)
1126 {
1127 GNUNET_CONTAINER_DLL_remove (monitor_head,
1128 monitor_tail,
1129 r);
1130 GNUNET_free (r);
1131 return; /* Delete only ONE entry */
1282 } 1132 }
1283 } 1133 }
1284 GNUNET_free (cl);
1285} 1134}
1286 1135
1287 1136
1288/** 1137/**
1289 * Check if some client is monitoring GET RESP messages and notify 1138 * Function to call by #for_matching_monitors().
1290 * them in that case.
1291 * 1139 *
1292 * @param type The type of data in the result. 1140 * @param cls closure
1293 * @param get_path Peers on GET path (or NULL if not recorded). 1141 * @param m a matching monitor
1294 * @param get_path_length number of entries in get_path.
1295 * @param put_path peers on the PUT path (or NULL if not recorded).
1296 * @param put_path_length number of entries in get_path.
1297 * @param exp Expiration time of the data.
1298 * @param key Key of the data.
1299 * @param data Pointer to the result data.
1300 * @param size Number of bytes in @a data.
1301 */ 1142 */
1302void 1143typedef void
1303GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, 1144(*MonitorAction)(void *cls,
1304 const struct GNUNET_PeerIdentity *get_path, 1145 struct ClientMonitorRecord *m);
1305 unsigned int get_path_length, 1146
1306 const struct GNUNET_PeerIdentity *put_path, 1147
1307 unsigned int put_path_length, 1148/**
1308 struct GNUNET_TIME_Absolute exp, 1149 * Call @a cb on all monitors that watch for blocks of @a type
1309 const struct GNUNET_HashCode *key, 1150 * and key @a key.
1310 const void *data, 1151 *
1311 size_t size) 1152 * @param type the type to match
1153 * @param key the key to match
1154 * @param cb function to call
1155 * @param cb_cls closure for @a cb
1156 */
1157static void
1158for_matching_monitors (enum GNUNET_BLOCK_Type type,
1159 const struct GNUNET_HashCode *key,
1160 MonitorAction cb,
1161 void *cb_cls)
1312{ 1162{
1313 struct ClientMonitorRecord *m; 1163 struct ClientHandle **cl = NULL;
1314 struct ClientHandle **cl; 1164 unsigned int cl_size = 0;
1315 unsigned int cl_size;
1316 1165
1317 cl = NULL; 1166 for (struct ClientMonitorRecord *m = monitor_head;
1318 cl_size = 0; 1167 NULL != m;
1319 for (m = monitor_head; NULL != m; m = m->next) 1168 m = m->next)
1320 { 1169 {
1321 if (((GNUNET_BLOCK_TYPE_ANY == m->type) || (m->type == type) ) && 1170 if ( ( (GNUNET_BLOCK_TYPE_ANY == m->type) ||
1322 ((NULL == m->key) || 1171 (m->type == type) ) &&
1323 (memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0) )) 1172 ( (GNUNET_is_zero (&m->key)) ||
1173 (0 ==
1174 GNUNET_memcmp (key,
1175 &m->key)) ) )
1324 { 1176 {
1325 struct GNUNET_MQ_Envelope *env;
1326 struct GNUNET_DHT_MonitorGetRespMessage *mmsg;
1327 struct GNUNET_PeerIdentity *path;
1328 size_t msize;
1329 unsigned int i; 1177 unsigned int i;
1330 1178
1331 /* Don't send duplicates */ 1179 /* Don't send duplicates */
@@ -1337,30 +1185,8 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
1337 GNUNET_array_append (cl, 1185 GNUNET_array_append (cl,
1338 cl_size, 1186 cl_size,
1339 m->ch); 1187 m->ch);
1340 1188 cb (cb_cls,
1341 msize = size; 1189 m);
1342 msize += (get_path_length + put_path_length)
1343 * sizeof(struct GNUNET_PeerIdentity);
1344 env = GNUNET_MQ_msg_extra (mmsg,
1345 msize,
1346 GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP);
1347 mmsg->type = htonl (type);
1348 mmsg->put_path_length = htonl (put_path_length);
1349 mmsg->get_path_length = htonl (get_path_length);
1350 mmsg->expiration_time = GNUNET_TIME_absolute_hton (exp);
1351 mmsg->key = *key;
1352 path = (struct GNUNET_PeerIdentity *) &mmsg[1];
1353 GNUNET_memcpy (path,
1354 put_path,
1355 put_path_length * sizeof(struct GNUNET_PeerIdentity));
1356 GNUNET_memcpy (path,
1357 get_path,
1358 get_path_length * sizeof(struct GNUNET_PeerIdentity));
1359 GNUNET_memcpy (&path[get_path_length],
1360 data,
1361 size);
1362 GNUNET_MQ_send (m->ch->mq,
1363 env);
1364 } 1190 }
1365 } 1191 }
1366 GNUNET_free (cl); 1192 GNUNET_free (cl);
@@ -1368,94 +1194,254 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
1368 1194
1369 1195
1370/** 1196/**
1371 * Check if some client is monitoring PUT messages and notify 1197 * Closure for #get_action();
1372 * them in that case. 1198 */
1199struct GetActionContext
1200{
1201 enum GNUNET_DHT_RouteOption options;
1202 enum GNUNET_BLOCK_Type type;
1203 uint32_t hop_count;
1204 uint32_t desired_replication_level;
1205 unsigned int get_path_length;
1206 const struct GNUNET_PeerIdentity *get_path;
1207 const struct GNUNET_HashCode *key;
1208};
1209
1210
1211/**
1212 * Function called on monitors that match a GET.
1213 * Sends the GET notification to the monitor.
1214 *
1215 * @param cls a `struct GetActionContext`
1216 * @param m a matching monitor
1217 */
1218static void
1219get_action (void *cls,
1220 struct ClientMonitorRecord *m)
1221{
1222 struct GetActionContext *gac = cls;
1223 struct GNUNET_MQ_Envelope *env;
1224 struct GNUNET_DHT_MonitorGetMessage *mmsg;
1225 struct GNUNET_PeerIdentity *msg_path;
1226 size_t msize;
1227
1228 msize = gac->get_path_length * sizeof(struct GNUNET_PeerIdentity);
1229 env = GNUNET_MQ_msg_extra (mmsg,
1230 msize,
1231 GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET);
1232 mmsg->options = htonl (gac->options);
1233 mmsg->type = htonl (gac->type);
1234 mmsg->hop_count = htonl (gac->hop_count);
1235 mmsg->desired_replication_level = htonl (gac->desired_replication_level);
1236 mmsg->get_path_length = htonl (gac->get_path_length);
1237 mmsg->key = *gac->key;
1238 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
1239 GNUNET_memcpy (msg_path,
1240 gac->get_path,
1241 gac->get_path_length * sizeof(struct GNUNET_PeerIdentity));
1242 GNUNET_MQ_send (m->ch->mq,
1243 env);
1244}
1245
1246
1247/**
1248 * Check if some client is monitoring GET messages and notify
1249 * them in that case. If tracked, @a path should include the local peer.
1373 * 1250 *
1374 * @param options Options, for instance RecordRoute, DemultiplexEverywhere. 1251 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
1375 * @param type The type of data in the request. 1252 * @param type The type of data in the request.
1376 * @param hop_count Hop count so far. 1253 * @param hop_count Hop count so far.
1377 * @param path_length number of entries in path (or 0 if not recorded). 1254 * @param path_length number of entries in path (or 0 if not recorded).
1378 * @param path peers on the PUT path (or NULL if not recorded). 1255 * @param path peers on the GET path (or NULL if not recorded).
1379 * @param desired_replication_level Desired replication level. 1256 * @param desired_replication_level Desired replication level.
1380 * @param exp Expiration time of the data. 1257 * @param key Key of the requested data.
1381 * @param key Key under which data is to be stored.
1382 * @param data Pointer to the data carried.
1383 * @param size Number of bytes in data.
1384 */ 1258 */
1385void 1259void
1386GDS_CLIENTS_process_put (uint32_t options, 1260GDS_CLIENTS_process_get (enum GNUNET_DHT_RouteOption options,
1387 enum GNUNET_BLOCK_Type type, 1261 enum GNUNET_BLOCK_Type type,
1388 uint32_t hop_count, 1262 uint32_t hop_count,
1389 uint32_t desired_replication_level, 1263 uint32_t desired_replication_level,
1390 unsigned int path_length, 1264 unsigned int path_length,
1391 const struct GNUNET_PeerIdentity *path, 1265 const struct GNUNET_PeerIdentity *path,
1392 struct GNUNET_TIME_Absolute exp, 1266 const struct GNUNET_HashCode *key)
1393 const struct GNUNET_HashCode *key,
1394 const void *data,
1395 size_t size)
1396{ 1267{
1397 struct ClientMonitorRecord *m; 1268 struct GetActionContext gac = {
1398 struct ClientHandle **cl; 1269 .options = options,
1399 unsigned int cl_size; 1270 .type = type,
1271 .hop_count = hop_count,
1272 .desired_replication_level = desired_replication_level,
1273 .get_path_length = path_length,
1274 .get_path = path,
1275 .key = key
1276 };
1277
1278 for_matching_monitors (type,
1279 key,
1280 &get_action,
1281 &gac);
1282}
1400 1283
1401 cl = NULL;
1402 cl_size = 0;
1403 for (m = monitor_head; NULL != m; m = m->next)
1404 {
1405 if (((GNUNET_BLOCK_TYPE_ANY == m->type) || (m->type == type) ) &&
1406 ((NULL == m->key) ||
1407 (memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0) ))
1408 {
1409 struct GNUNET_MQ_Envelope *env;
1410 struct GNUNET_DHT_MonitorPutMessage *mmsg;
1411 struct GNUNET_PeerIdentity *msg_path;
1412 size_t msize;
1413 unsigned int i;
1414 1284
1415 /* Don't send duplicates */ 1285/**
1416 for (i = 0; i < cl_size; i++) 1286 * Closure for response_action().
1417 if (cl[i] == m->ch) 1287 */
1418 break; 1288struct ResponseActionContext
1419 if (i < cl_size) 1289{
1420 continue; 1290 const struct GDS_DATACACHE_BlockData *bd;
1421 GNUNET_array_append (cl, 1291 const struct GNUNET_PeerIdentity *get_path;
1422 cl_size, 1292 unsigned int get_path_length;
1423 m->ch); 1293};
1424 1294
1425 msize = size; 1295
1426 msize += path_length * sizeof(struct GNUNET_PeerIdentity); 1296/**
1427 env = GNUNET_MQ_msg_extra (mmsg, 1297 * Function called on monitors that match a response.
1428 msize, 1298 * Sends the response notification to the monitor.
1429 GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT); 1299 *
1430 mmsg->options = htonl (options); 1300 * @param cls a `struct ResponseActionContext`
1431 mmsg->type = htonl (type); 1301 * @param m a matching monitor
1432 mmsg->hop_count = htonl (hop_count); 1302 */
1433 mmsg->desired_replication_level = htonl (desired_replication_level); 1303static void
1434 mmsg->put_path_length = htonl (path_length); 1304response_action (void *cls,
1435 mmsg->key = *key; 1305 struct ClientMonitorRecord *m)
1436 mmsg->expiration_time = GNUNET_TIME_absolute_hton (exp); 1306{
1437 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; 1307 const struct ResponseActionContext *resp_ctx = cls;
1438 GNUNET_memcpy (msg_path, 1308 const struct GDS_DATACACHE_BlockData *bd = resp_ctx->bd;
1439 path, 1309
1440 path_length * sizeof(struct GNUNET_PeerIdentity)); 1310 struct GNUNET_MQ_Envelope *env;
1441 GNUNET_memcpy (&msg_path[path_length], 1311 struct GNUNET_DHT_MonitorGetRespMessage *mmsg;
1442 data, 1312 struct GNUNET_PeerIdentity *path;
1443 size); 1313 size_t msize;
1444 GNUNET_MQ_send (m->ch->mq, 1314
1445 env); 1315 msize = bd->data_size;
1446 } 1316 msize += (resp_ctx->get_path_length + bd->put_path_length)
1447 } 1317 * sizeof(struct GNUNET_PeerIdentity);
1448 GNUNET_free (cl); 1318 env = GNUNET_MQ_msg_extra (mmsg,
1319 msize,
1320 GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP);
1321 mmsg->type = htonl (bd->type);
1322 mmsg->put_path_length = htonl (bd->put_path_length);
1323 mmsg->get_path_length = htonl (resp_ctx->get_path_length);
1324 mmsg->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1325 mmsg->key = bd->key;
1326 path = (struct GNUNET_PeerIdentity *) &mmsg[1];
1327 GNUNET_memcpy (path,
1328 bd->put_path,
1329 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
1330 GNUNET_memcpy (path,
1331 resp_ctx->get_path,
1332 resp_ctx->get_path_length * sizeof(struct
1333 GNUNET_PeerIdentity));
1334 GNUNET_memcpy (&path[resp_ctx->get_path_length],
1335 bd->data,
1336 bd->data_size);
1337 GNUNET_MQ_send (m->ch->mq,
1338 env);
1339}
1340
1341
1342void
1343GDS_CLIENTS_process_get_resp (const struct GDS_DATACACHE_BlockData *bd,
1344 const struct GNUNET_PeerIdentity *get_path,
1345 unsigned int get_path_length)
1346{
1347 struct ResponseActionContext rac = {
1348 .bd = bd,
1349 .get_path = get_path,
1350 .get_path_length = get_path_length
1351 };
1352
1353 for_matching_monitors (bd->type,
1354 &bd->key,
1355 &response_action,
1356 &rac);
1357}
1358
1359
1360/**
1361 * Closure for put_action().
1362 */
1363struct PutActionContext
1364{
1365 const struct GDS_DATACACHE_BlockData *bd;
1366 enum GNUNET_DHT_RouteOption options;
1367 uint32_t hop_count;
1368 uint32_t desired_replication_level;
1369};
1370
1371
1372/**
1373 * Function called on monitors that match a PUT.
1374 * Sends the PUT notification to the monitor.
1375 *
1376 * @param cls a `struct PutActionContext`
1377 * @param m a matching monitor
1378 */
1379static void
1380put_action (void *cls,
1381 struct ClientMonitorRecord *m)
1382{
1383 const struct PutActionContext *put_ctx = cls;
1384 const struct GDS_DATACACHE_BlockData *bd = put_ctx->bd;
1385 struct GNUNET_MQ_Envelope *env;
1386 struct GNUNET_DHT_MonitorPutMessage *mmsg;
1387 struct GNUNET_PeerIdentity *msg_path;
1388 size_t msize;
1389
1390 msize = bd->data_size
1391 + bd->put_path_length
1392 * sizeof(struct GNUNET_PeerIdentity);
1393 env = GNUNET_MQ_msg_extra (mmsg,
1394 msize,
1395 GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
1396 mmsg->options = htonl (put_ctx->options);
1397 mmsg->type = htonl (bd->type);
1398 mmsg->hop_count = htonl (put_ctx->hop_count);
1399 mmsg->desired_replication_level = htonl (put_ctx->desired_replication_level);
1400 mmsg->put_path_length = htonl (bd->put_path_length);
1401 mmsg->key = bd->key;
1402 mmsg->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1403 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
1404 GNUNET_memcpy (msg_path,
1405 bd->put_path,
1406 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
1407 GNUNET_memcpy (&msg_path[bd->put_path_length],
1408 bd->data,
1409 bd->data_size);
1410 GNUNET_MQ_send (m->ch->mq,
1411 env);
1449} 1412}
1450 1413
1451 1414
1415void
1416GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
1417 const struct GDS_DATACACHE_BlockData *bd,
1418 uint32_t hop_count,
1419 uint32_t desired_replication_level)
1420{
1421 struct PutActionContext put_ctx = {
1422 .bd = bd,
1423 .hop_count = hop_count,
1424 .desired_replication_level = desired_replication_level,
1425 .options = options
1426 };
1427
1428 for_matching_monitors (bd->type,
1429 &bd->key,
1430 &put_action,
1431 &put_ctx);
1432}
1433
1434
1435/* ********************** Initialization logic ***************** */
1436
1437
1452/** 1438/**
1453 * Initialize client subsystem. 1439 * Initialize client subsystem.
1454 * 1440 *
1455 * @param server the initialized server 1441 * @param server the initialized server
1456 */ 1442 */
1457static void 1443static void
1458GDS_CLIENTS_init () 1444GDS_CLIENTS_init (void)
1459{ 1445{
1460 forward_map 1446 forward_map
1461 = GNUNET_CONTAINER_multihashmap_create (1024, 1447 = GNUNET_CONTAINER_multihashmap_create (1024,
@@ -1469,7 +1455,7 @@ GDS_CLIENTS_init ()
1469 * Shutdown client subsystem. 1455 * Shutdown client subsystem.
1470 */ 1456 */
1471static void 1457static void
1472GDS_CLIENTS_stop () 1458GDS_CLIENTS_stop (void)
1473{ 1459{
1474 if (NULL != retry_task) 1460 if (NULL != retry_task)
1475 { 1461 {
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
index 7eded2152..214c4a3f4 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2015, 2017 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 2015, 2017, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -38,67 +38,53 @@
38 */ 38 */
39#define NUM_CLOSEST 42 39#define NUM_CLOSEST 42
40 40
41
41/** 42/**
42 * Handle to the datacache service (for inserting/retrieving data) 43 * Handle to the datacache service (for inserting/retrieving data)
43 */ 44 */
44static struct GNUNET_DATACACHE_Handle *datacache; 45static struct GNUNET_DATACACHE_Handle *datacache;
45 46
46 47
47/**
48 * Handle a datum we've received from another peer. Cache if
49 * possible.
50 *
51 * @param expiration when will the reply expire
52 * @param key the query this reply is for
53 * @param put_path_length number of peers in @a put_path
54 * @param put_path path the reply took on put
55 * @param type type of the reply
56 * @param data_size number of bytes in @a data
57 * @param data application payload data
58 */
59void 48void
60GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, 49GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd)
61 const struct GNUNET_HashCode *key,
62 unsigned int put_path_length,
63 const struct GNUNET_PeerIdentity *put_path,
64 enum GNUNET_BLOCK_Type type,
65 size_t data_size,
66 const void *data)
67{ 50{
68 int r; 51 struct GNUNET_HashCode xor;
52 enum GNUNET_GenericReturnValue r;
69 53
70 if (NULL == datacache) 54 if (NULL == datacache)
71 { 55 {
72 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 56 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
73 _ ("%s request received, but have no datacache!\n"), "PUT"); 57 "PUT request received, but have no datacache!\n");
74 return; 58 return;
75 } 59 }
76 if (data_size >= GNUNET_MAX_MESSAGE_SIZE) 60 if (bd->data_size >= GNUNET_MAX_MESSAGE_SIZE)
77 { 61 {
78 GNUNET_break (0); 62 GNUNET_break (0);
79 return; 63 return;
80 } 64 }
81 /* Put size is actual data size plus struct overhead plus path length (if any) */ 65 /* Put size is actual data size plus struct overhead plus path length (if any) */
82 GNUNET_STATISTICS_update (GDS_stats, 66 GNUNET_STATISTICS_update (GDS_stats,
83 gettext_noop ("# ITEMS stored in datacache"), 67 "# ITEMS stored in datacache",
84 1, 68 1,
85 GNUNET_NO); 69 GNUNET_NO);
70 GNUNET_CRYPTO_hash_xor (&bd->key,
71 &my_identity_hash,
72 &xor);
86 r = GNUNET_DATACACHE_put (datacache, 73 r = GNUNET_DATACACHE_put (datacache,
87 key, 74 &bd->key,
88 GNUNET_CRYPTO_hash_matching_bits (key, 75 GNUNET_CRYPTO_hash_count_leading_zeros (&xor),
89 &my_identity_hash), 76 bd->data_size,
90 data_size, 77 bd->data,
91 data, 78 bd->type,
92 type, 79 bd->expiration_time,
93 expiration, 80 bd->put_path_length,
94 put_path_length, 81 bd->put_path);
95 put_path);
96 LOG (GNUNET_ERROR_TYPE_DEBUG, 82 LOG (GNUNET_ERROR_TYPE_DEBUG,
97 "DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n", 83 "DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n",
98 GNUNET_h2s (key), 84 GNUNET_h2s (&bd->key),
99 (unsigned long) data_size, 85 (unsigned long) bd->data_size,
100 r, 86 r,
101 put_path_length); 87 bd->put_path_length);
102} 88}
103 89
104 90
@@ -158,7 +144,7 @@ struct GetRequestContext
158 * @return #GNUNET_OK to continue iteration, anything else 144 * @return #GNUNET_OK to continue iteration, anything else
159 * to stop iteration. 145 * to stop iteration.
160 */ 146 */
161static int 147static enum GNUNET_GenericReturnValue
162datacache_get_iterator (void *cls, 148datacache_get_iterator (void *cls,
163 const struct GNUNET_HashCode *key, 149 const struct GNUNET_HashCode *key,
164 size_t data_size, 150 size_t data_size,
@@ -168,111 +154,74 @@ datacache_get_iterator (void *cls,
168 unsigned int put_path_length, 154 unsigned int put_path_length,
169 const struct GNUNET_PeerIdentity *put_path) 155 const struct GNUNET_PeerIdentity *put_path)
170{ 156{
171 static char non_null;
172 struct GetRequestContext *ctx = cls; 157 struct GetRequestContext *ctx = cls;
173 enum GNUNET_BLOCK_EvaluationResult eval; 158 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
174 159 struct GDS_DATACACHE_BlockData bd = {
175 if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us) 160 .key = *key,
161 .expiration_time = exp,
162 .put_path = put_path,
163 .data = data,
164 .data_size = data_size,
165 .put_path_length = put_path_length,
166 .type = type
167 };
168
169 if (GNUNET_TIME_absolute_is_past (exp))
176 { 170 {
177 GNUNET_break (0); /* why does datacache return expired values? */ 171 GNUNET_break (0); /* why does datacache return expired values? */
178 return GNUNET_OK; /* skip expired record */ 172 return GNUNET_OK; /* skip expired record */
179 } 173 }
180 if ((NULL == data) &&
181 (0 == data_size))
182 data = &non_null; /* point anywhere, but not to NULL */
183
184 eval 174 eval
185 = GNUNET_BLOCK_evaluate (GDS_block_context, 175 = GNUNET_BLOCK_check_reply (GDS_block_context,
186 type, 176 bd.type,
187 ctx->bg, 177 ctx->bg,
188 GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO, 178 &bd.key,
189 key, 179 ctx->xquery,
190 ctx->xquery, 180 ctx->xquery_size,
191 ctx->xquery_size, 181 bd.data,
192 data, 182 bd.data_size);
193 data_size);
194 LOG (GNUNET_ERROR_TYPE_DEBUG, 183 LOG (GNUNET_ERROR_TYPE_DEBUG,
195 "Found reply for query %s in datacache, evaluation result is %d\n", 184 "Evaluated reply for query %s in datacache, result is %d\n",
196 GNUNET_h2s (key), 185 GNUNET_h2s (key),
197 (int) eval); 186 (int) eval);
198 ctx->eval = eval; 187 ctx->eval = eval;
199 switch (eval) 188 switch (eval)
200 { 189 {
201 case GNUNET_BLOCK_EVALUATION_OK_MORE: 190 case GNUNET_BLOCK_REPLY_OK_MORE:
202 case GNUNET_BLOCK_EVALUATION_OK_LAST: 191 case GNUNET_BLOCK_REPLY_OK_LAST:
203 /* forward to local clients */ 192 case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
204 GNUNET_STATISTICS_update (GDS_stats, 193 /* forward to initiator */
205 gettext_noop
206 ("# Good RESULTS found in datacache"), 1,
207 GNUNET_NO);
208 ctx->gc (ctx->gc_cls,
209 type,
210 exp,
211 key,
212 put_path_length, put_path,
213 0, NULL,
214 data, data_size);
215 break;
216
217 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
218 GNUNET_STATISTICS_update (GDS_stats, 194 GNUNET_STATISTICS_update (GDS_stats,
219 gettext_noop ( 195 "# Good RESULTS found in datacache",
220 "# Duplicate RESULTS found in datacache"),
221 1, 196 1,
222 GNUNET_NO); 197 GNUNET_NO);
198 ctx->gc (ctx->gc_cls,
199 &bd);
223 break; 200 break;
224 201 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
225 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
226 GNUNET_STATISTICS_update (GDS_stats, 202 GNUNET_STATISTICS_update (GDS_stats,
227 gettext_noop ( 203 "# Duplicate RESULTS found in datacache",
228 "# Invalid RESULTS found in datacache"),
229 1, 204 1,
230 GNUNET_NO); 205 GNUNET_NO);
231 break; 206 break;
232 207 case GNUNET_BLOCK_REPLY_INVALID:
233 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: 208 /* maybe it expired? */
234 GNUNET_STATISTICS_update (GDS_stats, 209 GNUNET_STATISTICS_update (GDS_stats,
235 gettext_noop ( 210 "# Invalid RESULTS found in datacache",
236 "# Irrelevant RESULTS found in datacache"),
237 1, 211 1,
238 GNUNET_NO); 212 GNUNET_NO);
239 break; 213 break;
240 214 case GNUNET_BLOCK_REPLY_IRRELEVANT:
241 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
242 GNUNET_break (0);
243 break;
244
245 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
246 GNUNET_break_op (0);
247 return GNUNET_SYSERR;
248
249 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
250 GNUNET_STATISTICS_update (GDS_stats, 215 GNUNET_STATISTICS_update (GDS_stats,
251 gettext_noop ( 216 "# Irrelevant RESULTS found in datacache",
252 "# Unsupported RESULTS found in datacache"),
253 1, 217 1,
254 GNUNET_NO); 218 GNUNET_NO);
255 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
256 _ ("Unsupported block type (%u) in local response!\n"),
257 type);
258 break; 219 break;
259 } 220 }
260 return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK; 221 return (eval == GNUNET_BLOCK_REPLY_OK_LAST) ? GNUNET_NO : GNUNET_OK;
261} 222}
262 223
263 224
264/**
265 * Handle a GET request we've received from another peer.
266 *
267 * @param key the query
268 * @param type requested data type
269 * @param xquery extended query
270 * @param xquery_size number of bytes in @a xquery
271 * @param bg block group to use for reply evaluation
272 * @param gc function to call on the results
273 * @param gc_cls closure for @a gc
274 * @return evaluation result for the local replies
275 */
276enum GNUNET_BLOCK_EvaluationResult 225enum GNUNET_BLOCK_EvaluationResult
277GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key, 226GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
278 enum GNUNET_BLOCK_Type type, 227 enum GNUNET_BLOCK_Type type,
@@ -288,7 +237,7 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
288 if (NULL == datacache) 237 if (NULL == datacache)
289 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; 238 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
290 GNUNET_STATISTICS_update (GDS_stats, 239 GNUNET_STATISTICS_update (GDS_stats,
291 gettext_noop ("# GET requests given to datacache"), 240 "# GET requests given to datacache",
292 1, 241 1,
293 GNUNET_NO); 242 GNUNET_NO);
294 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID; 243 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
@@ -313,62 +262,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
313 262
314 263
315/** 264/**
316 * Function called with a random element from the datacache.
317 * Stores the key in the closure.
318 *
319 * @param cls a `struct GNUNET_HashCode *`, where to store the @a key
320 * @param key key for the content
321 * @param data_size number of bytes in @a data
322 * @param data content stored
323 * @param type type of the content
324 * @param exp when will the content expire?
325 * @param path_info_len number of entries in @a path_info
326 * @param path_info a path through the network
327 * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
328 */
329static int
330datacache_random_iterator (void *cls,
331 const struct GNUNET_HashCode *key,
332 size_t data_size,
333 const char *data,
334 enum GNUNET_BLOCK_Type type,
335 struct GNUNET_TIME_Absolute exp,
336 unsigned int path_info_len,
337 const struct GNUNET_PeerIdentity *path_info)
338{
339 struct GNUNET_HashCode *dest = cls;
340
341 *dest = *key;
342 return GNUNET_OK; /* should actually not matter which we return */
343}
344
345
346/**
347 * Obtain a random key from the datacache.
348 * Used by Whanau for load-balancing.
349 *
350 * @param[out] key where to store the key of a random element,
351 * randomized by PRNG if datacache is empty
352 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
353 */
354int
355GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key)
356{
357 if (0 ==
358 GNUNET_DATACACHE_get_random (datacache,
359 &datacache_random_iterator,
360 key))
361 {
362 /* randomize key in this case */
363 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
364 key);
365 return GNUNET_SYSERR;
366 }
367 return GNUNET_OK;
368}
369
370
371/**
372 * Closure for #datacache_get_successors_iterator(). 265 * Closure for #datacache_get_successors_iterator().
373 */ 266 */
374struct SuccContext 267struct SuccContext
@@ -376,12 +269,13 @@ struct SuccContext
376 /** 269 /**
377 * Function to call on the result 270 * Function to call on the result
378 */ 271 */
379 GDS_DATACACHE_SuccessorCallback cb; 272 GDS_DATACACHE_GetCallback cb;
380 273
381 /** 274 /**
382 * Closure for @e cb. 275 * Closure for @e cb.
383 */ 276 */
384 void *cb_cls; 277 void *cb_cls;
278
385}; 279};
386 280
387 281
@@ -399,7 +293,7 @@ struct SuccContext
399 * @return #GNUNET_OK to continue iteration, anything else 293 * @return #GNUNET_OK to continue iteration, anything else
400 * to stop iteration. 294 * to stop iteration.
401 */ 295 */
402static int 296static enum GNUNET_GenericReturnValue
403datacache_get_successors_iterator (void *cls, 297datacache_get_successors_iterator (void *cls,
404 const struct GNUNET_HashCode *key, 298 const struct GNUNET_HashCode *key,
405 size_t size, 299 size_t size,
@@ -410,40 +304,36 @@ datacache_get_successors_iterator (void *cls,
410 const struct GNUNET_PeerIdentity *put_path) 304 const struct GNUNET_PeerIdentity *put_path)
411{ 305{
412 const struct SuccContext *sc = cls; 306 const struct SuccContext *sc = cls;
307 struct GDS_DATACACHE_BlockData bd = {
308 .key = *key,
309 .expiration_time = exp,
310 .put_path = put_path,
311 .data = data,
312 .data_size = size,
313 .put_path_length = put_path_length,
314 .type = type
315 };
413 316
414 /* NOTE: The datacache currently does not store the RO from 317 /* NOTE: The datacache currently does not store the RO from
415 the original 'put', so we don't know the 'correct' option 318 the original 'put', so we don't know the 'correct' option
416 at this point anymore. Thus, we conservatively assume 319 at this point anymore. Thus, we conservatively assume
417 that recording is desired (for now). */ 320 that recording is desired (for now). */
418 sc->cb (sc->cb_cls, 321 sc->cb (sc->cb_cls,
419 GNUNET_DHT_RO_RECORD_ROUTE, 322 &bd);
420 key,
421 type,
422 put_path_length, put_path,
423 exp,
424 data,
425 size);
426 return GNUNET_OK; 323 return GNUNET_OK;
427} 324}
428 325
429 326
430/**
431 * Handle a request for data close to a key that we have received from
432 * another peer.
433 *
434 * @param key the location at which the peer is looking for data that is close
435 * @param cb function to call with the result
436 * @param cb_cls closure for @a cb
437 */
438void 327void
439GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key, 328GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
440 GDS_DATACACHE_SuccessorCallback cb, 329 GDS_DATACACHE_GetCallback cb,
441 void *cb_cls) 330 void *cb_cls)
442{ 331{
443 struct SuccContext sc; 332 struct SuccContext sc = {
333 .cb = cb,
334 .cb_cls = cb_cls
335 };
444 336
445 sc.cb = cb;
446 sc.cb_cls = cb_cls;
447 (void) GNUNET_DATACACHE_get_closest (datacache, 337 (void) GNUNET_DATACACHE_get_closest (datacache,
448 key, 338 key,
449 NUM_CLOSEST, 339 NUM_CLOSEST,
@@ -452,19 +342,14 @@ GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key,
452} 342}
453 343
454 344
455/**
456 * Initialize datacache subsystem.
457 */
458void 345void
459GDS_DATACACHE_init () 346GDS_DATACACHE_init ()
460{ 347{
461 datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache"); 348 datacache = GNUNET_DATACACHE_create (GDS_cfg,
349 "dhtcache");
462} 350}
463 351
464 352
465/**
466 * Shutdown datacache subsystem.
467 */
468void 353void
469GDS_DATACACHE_done () 354GDS_DATACACHE_done ()
470{ 355{
diff --git a/src/dht/gnunet-service-dht_datacache.h b/src/dht/gnunet-service-dht_datacache.h
index 5be59c90e..249bb8ee3 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -31,53 +31,68 @@
31#include "gnunet_block_lib.h" 31#include "gnunet_block_lib.h"
32#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
33 33
34
35/**
36 * Information about a block stored in the datacache.
37 */
38struct GDS_DATACACHE_BlockData
39{
40 /**
41 * Key of the block.
42 */
43 struct GNUNET_HashCode key;
44
45 /**
46 * When does the block expire?
47 */
48 struct GNUNET_TIME_Absolute expiration_time;
49
50 /**
51 * PUT path taken by the block, array of peer identities.
52 */
53 const struct GNUNET_PeerIdentity *put_path;
54
55 /**
56 * Actual block data.
57 */
58 const void *data;
59
60 /**
61 * Number of bytes in @a data.
62 */
63 size_t data_size;
64
65 /**
66 * Length of the @e put_path array.
67 */
68 unsigned int put_path_length;
69
70 /**
71 * Type of the block.
72 */
73 enum GNUNET_BLOCK_Type type;
74};
75
76
34/** 77/**
35 * Handle a datum we've received from another peer. Cache if 78 * Handle a datum we've received from another peer. Cache if
36 * possible. 79 * possible.
37 * 80 *
38 * @param expiration when will the reply expire 81 * @param bd block data to cache
39 * @param key the query this reply is for
40 * @param put_path_length number of peers in 'put_path'
41 * @param put_path path the reply took on put
42 * @param type type of the reply
43 * @param data_size number of bytes in 'data'
44 * @param data application payload data
45 */ 82 */
46void 83void
47GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, 84GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd);
48 const struct GNUNET_HashCode *key,
49 unsigned int put_path_length,
50 const struct GNUNET_PeerIdentity *put_path,
51 enum GNUNET_BLOCK_Type type,
52 size_t data_size,
53 const void *data);
54 85
55 86
56/** 87/**
57 * Handle a result for a GET operation. 88 * Handle a result for a GET operation.
58 * 89 *
59 * @param cls closure 90 * @param cls closure
60 * @param type type of the block 91 * @param bd block details
61 * @param expiration_time when does the content expire
62 * @param key key for the content
63 * @param put_path_length number of entries in @a put_path
64 * @param put_path peers the original PUT traversed (if tracked)
65 * @param get_path_length number of entries in @a get_path
66 * @param get_path peers this reply has traversed so far (if tracked)
67 * @param data payload of the reply
68 * @param data_size number of bytes in @a data
69 */ 92 */
70typedef void 93typedef void
71(*GDS_DATACACHE_GetCallback)(void *cls, 94(*GDS_DATACACHE_GetCallback)(void *cls,
72 enum GNUNET_BLOCK_Type type, 95 const struct GDS_DATACACHE_BlockData *bd);
73 struct GNUNET_TIME_Absolute expiration_time,
74 const struct GNUNET_HashCode *key,
75 unsigned int put_path_length,
76 const struct GNUNET_PeerIdentity *put_path,
77 unsigned int get_path_length,
78 const struct GNUNET_PeerIdentity *get_path,
79 const void *data,
80 size_t data_size);
81 96
82 97
83/** 98/**
@@ -103,43 +118,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
103 118
104 119
105/** 120/**
106 * Obtain a random key from the datacache.
107 * Used by Whanau for load-balancing.
108 *
109 * @param[out] key where to store the key of a random element,
110 * randomized by PRNG if datacache is empty
111 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
112 */
113int
114GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key);
115
116
117/**
118 * Send the get result to requesting client.
119 *
120 * @param cls closure
121 * @param options routing options (from GET request)
122 * @param key key of the requested data.
123 * @param type block type
124 * @param put_path_length number of peers in @a put_path
125 * @param put_path path taken to put the data at its stored location.
126 * @param expiration when will this result expire?
127 * @param data payload to store
128 * @param data_size size of the @a data
129 */
130typedef void
131(*GDS_DATACACHE_SuccessorCallback)(void *cls,
132 enum GNUNET_DHT_RouteOption options,
133 const struct GNUNET_HashCode *key,
134 enum GNUNET_BLOCK_Type type,
135 unsigned int put_path_length,
136 const struct GNUNET_PeerIdentity *put_path,
137 struct GNUNET_TIME_Absolute expiration,
138 const void *data,
139 size_t data_size);
140
141
142/**
143 * Handle a request for data close to a key that we have received from 121 * Handle a request for data close to a key that we have received from
144 * another peer. 122 * another peer.
145 * 123 *
@@ -148,9 +126,9 @@ typedef void
148 * @param cb_cls closure for @a cb 126 * @param cb_cls closure for @a cb
149 */ 127 */
150void 128void
151GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key, 129GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
152 GDS_DATACACHE_SuccessorCallback cb, 130 GDS_DATACACHE_GetCallback cb,
153 void *cb_cls); 131 void *cb_cls);
154 132
155 133
156/** 134/**
diff --git a/src/dht/gnunet-service-dht_hello.c b/src/dht/gnunet-service-dht_hello.c
index 906391334..949456575 100644
--- a/src/dht/gnunet-service-dht_hello.c
+++ b/src/dht/gnunet-service-dht_hello.c
@@ -54,7 +54,8 @@ GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
54{ 54{
55 if (NULL == peer_to_hello) 55 if (NULL == peer_to_hello)
56 return NULL; 56 return NULL;
57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); 57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
58 peer);
58} 59}
59 60
60 61
@@ -83,15 +84,20 @@ process_hello (void *cls,
83 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us) 84 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
84 return; 85 return;
85 GNUNET_STATISTICS_update (GDS_stats, 86 GNUNET_STATISTICS_update (GDS_stats,
86 gettext_noop ("# HELLOs obtained from peerinfo"), 1, 87 "# HELLOs obtained from peerinfo",
88 1,
87 GNUNET_NO); 89 GNUNET_NO);
88 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); 90 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
91 peer);
89 GNUNET_free (hm); 92 GNUNET_free (hm);
90 hm = GNUNET_malloc (GNUNET_HELLO_size (hello)); 93 hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
91 GNUNET_memcpy (hm, hello, GNUNET_HELLO_size (hello)); 94 GNUNET_memcpy (hm,
95 hello,
96 GNUNET_HELLO_size (hello));
92 GNUNET_assert (GNUNET_SYSERR != 97 GNUNET_assert (GNUNET_SYSERR !=
93 GNUNET_CONTAINER_multipeermap_put (peer_to_hello, 98 GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
94 peer, hm, 99 peer,
100 hm,
95 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); 101 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
96} 102}
97 103
@@ -114,7 +120,7 @@ GDS_HELLO_init ()
114/** 120/**
115 * Free memory occopied by the HELLO. 121 * Free memory occopied by the HELLO.
116 */ 122 */
117static int 123static enum GNUNET_GenericReturnValue
118free_hello (void *cls, 124free_hello (void *cls,
119 const struct GNUNET_PeerIdentity *key, 125 const struct GNUNET_PeerIdentity *key,
120 void *hello) 126 void *hello)
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index 02dab849b..35502e0f5 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009-2017, 2021 GNUnet e.V. 3 Copyright (C) 2009-2017, 2021, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -25,21 +25,12 @@
25 * @author Nathan Evans 25 * @author Nathan Evans
26 */ 26 */
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_block_lib.h"
30#include "gnunet_hello_lib.h"
31#include "gnunet_constants.h" 28#include "gnunet_constants.h"
32#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
33#include "gnunet_nse_service.h"
34#include "gnunet_ats_service.h" 30#include "gnunet_ats_service.h"
35#include "gnunet_core_service.h" 31#include "gnunet_core_service.h"
36#include "gnunet_datacache_lib.h"
37#include "gnunet_transport_service.h"
38#include "gnunet_hello_lib.h" 32#include "gnunet_hello_lib.h"
39#include "gnunet_dht_service.h"
40#include "gnunet_statistics_service.h"
41#include "gnunet-service-dht.h" 33#include "gnunet-service-dht.h"
42#include "gnunet-service-dht_datacache.h"
43#include "gnunet-service-dht_hello.h" 34#include "gnunet-service-dht_hello.h"
44#include "gnunet-service-dht_neighbours.h" 35#include "gnunet-service-dht_neighbours.h"
45#include "gnunet-service-dht_nse.h" 36#include "gnunet-service-dht_nse.h"
@@ -55,7 +46,7 @@
55#define SANITY_CHECKS 1 46#define SANITY_CHECKS 1
56 47
57/** 48/**
58 * How many buckets will we allow total. 49 * How many buckets will we allow in total.
59 */ 50 */
60#define MAX_BUCKETS sizeof(struct GNUNET_HashCode) * 8 51#define MAX_BUCKETS sizeof(struct GNUNET_HashCode) * 8
61 52
@@ -70,26 +61,29 @@
70#define FIND_PEER_REPLICATION_LEVEL 4 61#define FIND_PEER_REPLICATION_LEVEL 4
71 62
72/** 63/**
73 * Maximum allowed replication level for all requests.
74 */
75#define MAXIMUM_REPLICATION_LEVEL 16
76
77/**
78 * Maximum allowed number of pending messages per peer. 64 * Maximum allowed number of pending messages per peer.
79 */ 65 */
80#define MAXIMUM_PENDING_PER_PEER 64 66#define MAXIMUM_PENDING_PER_PEER 64
81 67
82/** 68/**
83 * How long at least to wait before sending another find peer request. 69 * How long at least to wait before sending another find peer request.
70 * This is basically the frequency at which we will usually send out
71 * requests when we are 'perfectly' connected.
84 */ 72 */
85#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \ 73#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
86 GNUNET_TIME_UNIT_SECONDS, 30) 74 GNUNET_TIME_UNIT_MINUTES, 2)
87 75
88/** 76/**
89 * How long at most to wait before sending another find peer request. 77 * How long to additionally wait on average per #bucket_size to send out the
78 * FIND PEER requests if we did successfully connect (!) to a a new peer and
79 * added it to a bucket (as counted in #newly_found_peers). This time is
80 * Multiplied by 100 * newly_found_peers / bucket_size to get the new delay
81 * for finding peers (the #DHT_MINIMUM_FIND_PEER_INTERVAL is still added on
82 * top). Also the range in which we randomize, so the effective value
83 * is half of the number given here.
90 */ 84 */
91#define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \ 85#define DHT_AVG_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
92 GNUNET_TIME_UNIT_MINUTES, 10) 86 GNUNET_TIME_UNIT_SECONDS, 6)
93 87
94/** 88/**
95 * How long at most to wait for transmission of a GET request to another peer? 89 * How long at most to wait for transmission of a GET request to another peer?
@@ -424,20 +418,24 @@ static struct GNUNET_ATS_ConnectivityHandle *ats_ch;
424 * Find the optimal bucket for this key. 418 * Find the optimal bucket for this key.
425 * 419 *
426 * @param hc the hashcode to compare our identity to 420 * @param hc the hashcode to compare our identity to
427 * @return the proper bucket index, or #GNUNET_SYSERR 421 * @return the proper bucket index, or -1
428 * on error (same hashcode) 422 * on error (same hashcode)
429 */ 423 */
430static int 424static int
431find_bucket (const struct GNUNET_HashCode *hc) 425find_bucket (const struct GNUNET_HashCode *hc)
432{ 426{
427 struct GNUNET_HashCode xor;
433 unsigned int bits; 428 unsigned int bits;
434 429
435 bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, hc); 430 GNUNET_CRYPTO_hash_xor (hc,
431 &my_identity_hash,
432 &xor);
433 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
436 if (bits == MAX_BUCKETS) 434 if (bits == MAX_BUCKETS)
437 { 435 {
438 /* How can all bits match? Got my own ID? */ 436 /* How can all bits match? Got my own ID? */
439 GNUNET_break (0); 437 GNUNET_break (0);
440 return GNUNET_SYSERR; 438 return -1;
441 } 439 }
442 return MAX_BUCKETS - bits - 1; 440 return MAX_BUCKETS - bits - 1;
443} 441}
@@ -466,7 +464,7 @@ offer_hello_done (void *cls)
466 * @param value the value to remove 464 * @param value the value to remove
467 * @return #GNUNET_YES 465 * @return #GNUNET_YES
468 */ 466 */
469static int 467static enum GNUNET_GenericReturnValue
470free_connect_info (void *cls, 468free_connect_info (void *cls,
471 const struct GNUNET_PeerIdentity *peer, 469 const struct GNUNET_PeerIdentity *peer,
472 void *value) 470 void *value)
@@ -505,33 +503,34 @@ static void
505try_connect (const struct GNUNET_PeerIdentity *pid, 503try_connect (const struct GNUNET_PeerIdentity *pid,
506 const struct GNUNET_MessageHeader *h) 504 const struct GNUNET_MessageHeader *h)
507{ 505{
508 int bucket; 506 int bucket_idx;
509 struct GNUNET_HashCode pid_hash; 507 struct GNUNET_HashCode pid_hash;
510 struct ConnectInfo *ci; 508 struct ConnectInfo *ci;
511 uint32_t strength; 509 uint32_t strength;
510 struct PeerBucket *bucket;
512 511
513 GNUNET_CRYPTO_hash (pid, 512 GNUNET_CRYPTO_hash (pid,
514 sizeof(struct GNUNET_PeerIdentity), 513 sizeof(struct GNUNET_PeerIdentity),
515 &pid_hash); 514 &pid_hash);
516 bucket = find_bucket (&pid_hash); 515 bucket_idx = find_bucket (&pid_hash);
517 if (bucket < 0) 516 if (bucket_idx < 0)
518 return; /* self? */ 517 {
518 GNUNET_break (0);
519 return; /* self!? */
520 }
521 bucket = &k_buckets[bucket_idx];
519 ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers, 522 ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
520 pid); 523 pid);
521 524 if (bucket->peers_size < bucket_size)
522 if (k_buckets[bucket].peers_size < bucket_size) 525 strength = (bucket_size - bucket->peers_size) * bucket_idx;
523 strength = (bucket_size - k_buckets[bucket].peers_size) * bucket;
524 else 526 else
525 strength = bucket; /* minimum value of connectivity */ 527 strength = 0;
526 if (GNUNET_YES == 528 if (GNUNET_YES ==
527 GNUNET_CONTAINER_multipeermap_contains (all_connected_peers, 529 GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
528 pid)) 530 pid))
529 strength *= 2; /* double for connected peers */ 531 strength *= 2; /* double for connected peers */
530 else if (k_buckets[bucket].peers_size > bucket_size) 532 if ( (0 == strength) &&
531 strength = 0; /* bucket full, we really do not care about more */ 533 (NULL != ci) )
532
533 if ((0 == strength) &&
534 (NULL != ci))
535 { 534 {
536 /* release request */ 535 /* release request */
537 GNUNET_assert (GNUNET_YES == 536 GNUNET_assert (GNUNET_YES ==
@@ -549,22 +548,24 @@ try_connect (const struct GNUNET_PeerIdentity *pid,
549 ci, 548 ci,
550 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 549 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
551 } 550 }
552 if ((NULL != ci->oh) && 551 if ( (NULL != ci->oh) &&
553 (NULL != h)) 552 (NULL != h) )
554 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh); 553 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
555 if (NULL != h) 554 if (NULL != h)
556 ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg, 555 ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg,
557 h, 556 h,
558 &offer_hello_done, 557 &offer_hello_done,
559 ci); 558 ci);
560 if ((NULL != ci->sh) && 559 if ( (NULL != ci->sh) &&
561 (ci->strength != strength)) 560 (ci->strength != strength) )
562 GNUNET_ATS_connectivity_suggest_cancel (ci->sh); 561 GNUNET_ATS_connectivity_suggest_cancel (ci->sh);
563 if (ci->strength != strength) 562 if (ci->strength != strength)
563 {
564 ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch, 564 ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch,
565 pid, 565 pid,
566 strength); 566 strength);
567 ci->strength = strength; 567 ci->strength = strength;
568 }
568} 569}
569 570
570 571
@@ -580,7 +581,7 @@ try_connect (const struct GNUNET_PeerIdentity *pid,
580 * @param value unused 581 * @param value unused
581 * @return #GNUNET_YES (continue to iterate) 582 * @return #GNUNET_YES (continue to iterate)
582 */ 583 */
583static int 584static enum GNUNET_GenericReturnValue
584update_desire_strength (void *cls, 585update_desire_strength (void *cls,
585 const struct GNUNET_PeerIdentity *pid, 586 const struct GNUNET_PeerIdentity *pid,
586 void *value) 587 void *value)
@@ -595,12 +596,9 @@ update_desire_strength (void *cls,
595 596
596/** 597/**
597 * Update our preferences for connectivity as given to ATS. 598 * Update our preferences for connectivity as given to ATS.
598 *
599 * @param cls the `struct PeerInfo` of the peer
600 * @param tc scheduler context.
601 */ 599 */
602static void 600static void
603update_connect_preferences () 601update_connect_preferences (void)
604{ 602{
605 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers, 603 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
606 &update_desire_strength, 604 &update_desire_strength,
@@ -609,32 +607,27 @@ update_connect_preferences ()
609 607
610 608
611/** 609/**
612 * Add each of the peers we already know to the bloom filter of 610 * Add each of the peers we already know to the Bloom filter of
613 * the request so that we don't get duplicate HELLOs. 611 * the request so that we don't get duplicate HELLOs.
614 * 612 *
615 * @param cls the `struct GNUNET_BLOCK_Group` 613 * @param cls the `struct GNUNET_BLOCK_Group`
616 * @param key peer identity to add to the bloom filter 614 * @param key peer identity to add to the bloom filter
617 * @param value value the peer information (unused) 615 * @param value the peer information
618 * @return #GNUNET_YES (we should continue to iterate) 616 * @return #GNUNET_YES (we should continue to iterate)
619 */ 617 */
620static int 618static enum GNUNET_GenericReturnValue
621add_known_to_bloom (void *cls, 619add_known_to_bloom (void *cls,
622 const struct GNUNET_PeerIdentity *key, 620 const struct GNUNET_PeerIdentity *key,
623 void *value) 621 void *value)
624{ 622{
625 struct GNUNET_BLOCK_Group *bg = cls; 623 struct GNUNET_BLOCK_Group *bg = cls;
626 struct GNUNET_HashCode key_hash; 624 struct PeerInfo *pi = value;
627 625
628 (void) cls;
629 (void) value;
630 GNUNET_CRYPTO_hash (key,
631 sizeof(struct GNUNET_PeerIdentity),
632 &key_hash);
633 GNUNET_BLOCK_group_set_seen (bg, 626 GNUNET_BLOCK_group_set_seen (bg,
634 &key_hash, 627 &pi->phash,
635 1); 628 1);
636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
637 "Adding known peer (%s) to bloomfilter for FIND PEER\n", 630 "Adding known peer (%s) to Bloom filter for FIND PEER\n",
638 GNUNET_i2s (key)); 631 GNUNET_i2s (key));
639 return GNUNET_YES; 632 return GNUNET_YES;
640} 633}
@@ -645,73 +638,88 @@ add_known_to_bloom (void *cls,
645 * so that we can find the closest peers in the network to ourselves 638 * so that we can find the closest peers in the network to ourselves
646 * and attempt to connect to them. 639 * and attempt to connect to them.
647 * 640 *
648 * @param cls closure for this task 641 * @param cls closure for this task, NULL
649 */ 642 */
650static void 643static void
651send_find_peer_message (void *cls) 644send_find_peer_message (void *cls)
652{ 645{
653 struct GNUNET_TIME_Relative next_send_time;
654 struct GNUNET_BLOCK_Group *bg;
655 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
656
657 (void) cls; 646 (void) cls;
658 find_peer_task = NULL; 647
659 if (newly_found_peers > bucket_size) 648 /* Compute when to do this again (and if we should
649 even send a message right now) */
660 { 650 {
661 /* If we are finding many peers already, no need to send out our request right now! */ 651 struct GNUNET_TIME_Relative next_send_time;
652 bool done_early;
653
654 find_peer_task = NULL;
655 done_early = (newly_found_peers > bucket_size);
656 /* schedule next round, taking longer if we found more peers
657 in the last round. */
658 next_send_time.rel_value_us =
659 DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us
660 + GNUNET_CRYPTO_random_u64 (
661 GNUNET_CRYPTO_QUALITY_WEAK,
662 GNUNET_TIME_relative_multiply (
663 DHT_AVG_FIND_PEER_INTERVAL,
664 100 * (1 + newly_found_peers) / bucket_size).rel_value_us);
665 newly_found_peers = 0;
666 GNUNET_assert (NULL == find_peer_task);
662 find_peer_task = 667 find_peer_task =
663 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, 668 GNUNET_SCHEDULER_add_delayed (next_send_time,
664 &send_find_peer_message, 669 &send_find_peer_message,
665 NULL); 670 NULL);
666 newly_found_peers = 0; 671 if (done_early)
667 return; 672 return;
673 }
674
675 /* actually send 'find peer' request */
676 {
677 struct GNUNET_BLOCK_Group *bg;
678 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
679
680 bg = GNUNET_BLOCK_group_create (GDS_block_context,
681 GNUNET_BLOCK_TYPE_DHT_HELLO,
682 GNUNET_CRYPTO_random_u32 (
683 GNUNET_CRYPTO_QUALITY_WEAK,
684 UINT32_MAX),
685 NULL,
686 0,
687 "filter-size",
688 DHT_BLOOM_SIZE,
689 NULL);
690 GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers,
691 &add_known_to_bloom,
692 bg);
693 peer_bf
694 = GNUNET_CONTAINER_bloomfilter_init (NULL,
695 DHT_BLOOM_SIZE,
696 GNUNET_CONSTANTS_BLOOMFILTER_K);
697 if (GNUNET_OK !=
698 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO,
699 GNUNET_DHT_RO_FIND_PEER
700 | GNUNET_DHT_RO_RECORD_ROUTE,
701 FIND_PEER_REPLICATION_LEVEL,
702 0, /* hop count */
703 &my_identity_hash,
704 NULL, 0, /* xquery */
705 bg,
706 peer_bf))
707 {
708 GNUNET_STATISTICS_update (GDS_stats,
709 "# Failed to initiate FIND PEER lookup",
710 1,
711 GNUNET_NO);
712 }
713 else
714 {
715 GNUNET_STATISTICS_update (GDS_stats,
716 "# FIND PEER messages initiated",
717 1,
718 GNUNET_NO);
719 }
720 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
721 GNUNET_BLOCK_group_destroy (bg);
668 } 722 }
669 bg = GNUNET_BLOCK_group_create (GDS_block_context,
670 GNUNET_BLOCK_TYPE_DHT_HELLO,
671 GNUNET_CRYPTO_random_u32 (
672 GNUNET_CRYPTO_QUALITY_WEAK,
673 UINT32_MAX),
674 NULL,
675 0,
676 "filter-size",
677 DHT_BLOOM_SIZE,
678 NULL);
679 GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers,
680 &add_known_to_bloom,
681 bg);
682 GNUNET_STATISTICS_update (GDS_stats,
683 gettext_noop ("# FIND PEER messages initiated"),
684 1,
685 GNUNET_NO);
686 peer_bf
687 = GNUNET_CONTAINER_bloomfilter_init (NULL,
688 DHT_BLOOM_SIZE,
689 GNUNET_CONSTANTS_BLOOMFILTER_K);
690 // FIXME: pass priority!?
691 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO,
692 GNUNET_DHT_RO_FIND_PEER
693 | GNUNET_DHT_RO_RECORD_ROUTE,
694 FIND_PEER_REPLICATION_LEVEL,
695 0,
696 &my_identity_hash,
697 NULL,
698 0,
699 bg,
700 peer_bf);
701 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
702 GNUNET_BLOCK_group_destroy (bg);
703 /* schedule next round */
704 next_send_time.rel_value_us =
705 DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us
706 + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
707 DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us
708 / (newly_found_peers + 1));
709 newly_found_peers = 0;
710 GNUNET_assert (NULL == find_peer_task);
711 find_peer_task =
712 GNUNET_SCHEDULER_add_delayed (next_send_time,
713 &send_find_peer_message,
714 NULL);
715} 723}
716 724
717 725
@@ -729,6 +737,7 @@ handle_core_connect (void *cls,
729 struct GNUNET_MQ_Handle *mq) 737 struct GNUNET_MQ_Handle *mq)
730{ 738{
731 struct PeerInfo *pi; 739 struct PeerInfo *pi;
740 struct PeerBucket *bucket;
732 741
733 (void) cls; 742 (void) cls;
734 /* Check for connect to self message */ 743 /* Check for connect to self message */
@@ -736,13 +745,13 @@ handle_core_connect (void *cls,
736 peer)) 745 peer))
737 return NULL; 746 return NULL;
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
739 "Connected to %s\n", 748 "Connected to peer %s\n",
740 GNUNET_i2s (peer)); 749 GNUNET_i2s (peer));
741 GNUNET_assert (GNUNET_NO == 750 GNUNET_assert (NULL ==
742 GNUNET_CONTAINER_multipeermap_get (all_connected_peers, 751 GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
743 peer)); 752 peer));
744 GNUNET_STATISTICS_update (GDS_stats, 753 GNUNET_STATISTICS_update (GDS_stats,
745 gettext_noop ("# peers connected"), 754 "# peers connected",
746 1, 755 1,
747 GNUNET_NO); 756 GNUNET_NO);
748 pi = GNUNET_new (struct PeerInfo); 757 pi = GNUNET_new (struct PeerInfo);
@@ -752,27 +761,27 @@ handle_core_connect (void *cls,
752 sizeof(struct GNUNET_PeerIdentity), 761 sizeof(struct GNUNET_PeerIdentity),
753 &pi->phash); 762 &pi->phash);
754 pi->peer_bucket = find_bucket (&pi->phash); 763 pi->peer_bucket = find_bucket (&pi->phash);
755 GNUNET_assert ((pi->peer_bucket >= 0) && 764 GNUNET_assert ( (pi->peer_bucket >= 0) &&
756 ((unsigned int) pi->peer_bucket < MAX_BUCKETS)); 765 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
757 GNUNET_CONTAINER_DLL_insert_tail (k_buckets[pi->peer_bucket].head, 766 bucket = &k_buckets[pi->peer_bucket];
758 k_buckets[pi->peer_bucket].tail, 767 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
768 bucket->tail,
759 pi); 769 pi);
760 k_buckets[pi->peer_bucket].peers_size++; 770 bucket->peers_size++;
761 closest_bucket = GNUNET_MAX (closest_bucket, 771 closest_bucket = GNUNET_MAX (closest_bucket,
762 (unsigned int) pi->peer_bucket); 772 (unsigned int) pi->peer_bucket + 1);
763 GNUNET_assert (GNUNET_OK == 773 GNUNET_assert (GNUNET_OK ==
764 GNUNET_CONTAINER_multipeermap_put (all_connected_peers, 774 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
765 pi->id, 775 pi->id,
766 pi, 776 pi,
767 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 777 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
768 if ((pi->peer_bucket > 0) && 778 if (bucket->peers_size <= bucket_size)
769 (k_buckets[pi->peer_bucket].peers_size <= bucket_size))
770 { 779 {
771 update_connect_preferences (); 780 update_connect_preferences ();
772 newly_found_peers++; 781 newly_found_peers++;
773 } 782 }
774 if ((1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) && 783 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
775 (GNUNET_YES != disable_try_connect)) 784 (GNUNET_YES != disable_try_connect) )
776 { 785 {
777 /* got a first connection, good time to start with FIND PEER requests... */ 786 /* got a first connection, good time to start with FIND PEER requests... */
778 GNUNET_assert (NULL == find_peer_task); 787 GNUNET_assert (NULL == find_peer_task);
@@ -796,38 +805,40 @@ handle_core_disconnect (void *cls,
796 void *internal_cls) 805 void *internal_cls)
797{ 806{
798 struct PeerInfo *to_remove = internal_cls; 807 struct PeerInfo *to_remove = internal_cls;
808 struct PeerBucket *bucket;
799 809
800 (void) cls; 810 (void) cls;
801 /* Check for disconnect from self message */ 811 /* Check for disconnect from self message (on shutdown) */
802 if (NULL == to_remove) 812 if (NULL == to_remove)
803 return; 813 return;
804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
805 "Disconnected %s\n", 815 "Disconnected from peer %s\n",
806 GNUNET_i2s (peer)); 816 GNUNET_i2s (peer));
807 GNUNET_STATISTICS_update (GDS_stats, 817 GNUNET_STATISTICS_update (GDS_stats,
808 gettext_noop ("# peers connected"), 818 "# peers connected",
809 -1, 819 -1,
810 GNUNET_NO); 820 GNUNET_NO);
811 GNUNET_assert (GNUNET_YES == 821 GNUNET_assert (GNUNET_YES ==
812 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers, 822 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
813 peer, 823 peer,
814 to_remove)); 824 to_remove));
815 if ((0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) && 825 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
816 (GNUNET_YES != disable_try_connect)) 826 (GNUNET_YES != disable_try_connect))
817 { 827 {
818 GNUNET_SCHEDULER_cancel (find_peer_task); 828 GNUNET_SCHEDULER_cancel (find_peer_task);
819 find_peer_task = NULL; 829 find_peer_task = NULL;
820 } 830 }
821 GNUNET_assert (to_remove->peer_bucket >= 0); 831 GNUNET_assert (to_remove->peer_bucket >= 0);
822 GNUNET_CONTAINER_DLL_remove (k_buckets[to_remove->peer_bucket].head, 832 bucket = &k_buckets[to_remove->peer_bucket];
823 k_buckets[to_remove->peer_bucket].tail, 833 GNUNET_CONTAINER_DLL_remove (bucket->head,
834 bucket->tail,
824 to_remove); 835 to_remove);
825 GNUNET_assert (k_buckets[to_remove->peer_bucket].peers_size > 0); 836 GNUNET_assert (bucket->peers_size > 0);
826 k_buckets[to_remove->peer_bucket].peers_size--; 837 bucket->peers_size--;
827 while ((closest_bucket > 0) && 838 while ( (closest_bucket > 0) &&
828 (0 == k_buckets[to_remove->peer_bucket].peers_size)) 839 (0 == k_buckets[closest_bucket - 1].peers_size))
829 closest_bucket--; 840 closest_bucket--;
830 if (k_buckets[to_remove->peer_bucket].peers_size < bucket_size) 841 if (bucket->peers_size < bucket_size)
831 update_connect_preferences (); 842 update_connect_preferences ();
832 GNUNET_free (to_remove); 843 GNUNET_free (to_remove);
833} 844}
@@ -851,14 +862,15 @@ get_forward_count (uint32_t hop_count,
851 862
852 if (0 == target_replication) 863 if (0 == target_replication)
853 target_replication = 1; /* 0 is verboten */ 864 target_replication = 1; /* 0 is verboten */
854 if (target_replication > MAXIMUM_REPLICATION_LEVEL) 865 if (target_replication > GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL)
855 target_replication = MAXIMUM_REPLICATION_LEVEL; 866 target_replication = GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL;
856 if (hop_count > GDS_NSE_get () * 4.0) 867 if (hop_count > GDS_NSE_get () * 4.0)
857 { 868 {
858 /* forcefully terminate */ 869 /* forcefully terminate */
859 GNUNET_STATISTICS_update (GDS_stats, 870 GNUNET_STATISTICS_update (GDS_stats,
860 gettext_noop ("# requests TTL-dropped"), 871 "# requests TTL-dropped",
861 1, GNUNET_NO); 872 1,
873 GNUNET_NO);
862 return 0; 874 return 0;
863 } 875 }
864 if (hop_count > GDS_NSE_get () * 2.0) 876 if (hop_count > GDS_NSE_get () * 2.0)
@@ -868,7 +880,8 @@ get_forward_count (uint32_t hop_count,
868 } 880 }
869 /* bound by system-wide maximum */ 881 /* bound by system-wide maximum */
870 target_replication = 882 target_replication =
871 GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL, target_replication); 883 GNUNET_MIN (GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL,
884 target_replication);
872 target_value = 885 target_value =
873 1 + (target_replication - 1.0) / (GDS_NSE_get () 886 1 + (target_replication - 1.0) / (GDS_NSE_get ()
874 + ((float) (target_replication - 1.0) 887 + ((float) (target_replication - 1.0)
@@ -879,46 +892,12 @@ get_forward_count (uint32_t hop_count,
879 forward_count = (uint32_t) target_value; 892 forward_count = (uint32_t) target_value;
880 /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */ 893 /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
881 target_value = target_value - forward_count; 894 target_value = target_value - forward_count;
882 random_value = 895 random_value = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
883 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); 896 UINT32_MAX);
884 if (random_value < (target_value * UINT32_MAX)) 897 if (random_value < (target_value * UINT32_MAX))
885 forward_count++; 898 forward_count++;
886 return GNUNET_MIN (forward_count, 899 return GNUNET_MIN (forward_count,
887 MAXIMUM_REPLICATION_LEVEL); 900 GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL);
888}
889
890
891/**
892 * Compute the distance between have and target as a 64-bit value.
893 * Differences in the lower bits must count stronger than differences
894 * in the higher bits.
895 *
896 * @param target
897 * @param have
898 * @param bucket up to which offset are @a target and @a have identical and thus those bits should not be considered
899 * @return 0 if have==target, otherwise a number
900 * that is larger as the distance between
901 * the two hash codes increases
902 */
903static uint64_t
904get_distance (const struct GNUNET_HashCode *target,
905 const struct GNUNET_HashCode *have,
906 unsigned int bucket)
907{
908 uint64_t lsb = 0;
909
910 for (unsigned int i = bucket + 1;
911 (i < sizeof(struct GNUNET_HashCode) * 8) &&
912 (i < bucket + 1 + 64);
913 i++)
914 {
915 if (GNUNET_CRYPTO_hash_get_bit_rtl (target, i) !=
916 GNUNET_CRYPTO_hash_get_bit_rtl (have, i))
917 lsb |= (1LLU << (bucket + 64 - i)); /* first bit set will be 1,
918 * last bit set will be 63 -- if
919 * i does not reach 512 first... */
920 }
921 return lsb;
922} 901}
923 902
924 903
@@ -932,60 +911,74 @@ get_distance (const struct GNUNET_HashCode *target,
932 * @return #GNUNET_YES if node location is closest, 911 * @return #GNUNET_YES if node location is closest,
933 * #GNUNET_NO otherwise. 912 * #GNUNET_NO otherwise.
934 */ 913 */
935int 914enum GNUNET_GenericReturnValue
936GDS_am_closest_peer (const struct GNUNET_HashCode *key, 915GDS_am_closest_peer (const struct GNUNET_HashCode *key,
937 const struct GNUNET_CONTAINER_BloomFilter *bloom) 916 const struct GNUNET_CONTAINER_BloomFilter *bloom)
938{ 917{
939 int bits;
940 int other_bits;
941 int bucket_num;
942 struct PeerInfo *pos;
943
944 if (0 == GNUNET_memcmp (&my_identity_hash, 918 if (0 == GNUNET_memcmp (&my_identity_hash,
945 key)) 919 key))
946 return GNUNET_YES; 920 return GNUNET_YES;
947 bucket_num = find_bucket (key); 921 for (int bucket_num = find_bucket (key);
948 GNUNET_assert (bucket_num >= 0); 922 bucket_num < closest_bucket;
949 bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, 923 bucket_num++)
950 key);
951 pos = k_buckets[bucket_num].head;
952 while (NULL != pos)
953 { 924 {
954 if ((NULL != bloom) && 925 unsigned int count = 0;
955 (GNUNET_YES == 926
956 GNUNET_CONTAINER_bloomfilter_test (bloom, 927 GNUNET_assert (bucket_num >= 0);
957 &pos->phash))) 928 for (struct PeerInfo *pos = k_buckets[bucket_num].head;
929 NULL != pos;
930 pos = pos->next)
958 { 931 {
959 pos = pos->next; 932 if (count >= bucket_size)
960 continue; /* Skip already checked entries */ 933 break; /* we only consider first #bucket_size entries per bucket */
934 count++;
935 if ( (NULL != bloom) &&
936 (GNUNET_YES ==
937 GNUNET_CONTAINER_bloomfilter_test (bloom,
938 &pos->phash)) )
939 continue; /* Ignore filtered peers */
940 /* All peers in this bucket must be closer than us, as
941 they mismatch with our PID on the pivotal bit. So
942 because an unfiltered peer exists, we are not the
943 closest. */
944 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
945 &my_identity_hash,
946 key);
947 switch (delta)
948 {
949 case -1: /* pos closer */
950 return GNUNET_NO;
951 case 0: /* identical, impossible! */
952 GNUNET_assert (0);
953 break;
954 case 1: /* I am closer */
955 break;
956 }
961 } 957 }
962 other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->phash,
963 key);
964 if (other_bits > bits)
965 return GNUNET_NO;
966 if (other_bits == bits) /* We match the same number of bits */
967 return GNUNET_YES;
968 pos = pos->next;
969 } 958 }
970 /* No peers closer, we are the closest! */ 959 /* No closer (unfiltered) peers found; we must be the closest! */
971 return GNUNET_YES; 960 return GNUNET_YES;
972} 961}
973 962
974 963
975/** 964/**
976 * Select a peer from the routing table that would be a good routing 965 * Select a peer from the routing table that would be a good routing
977 * destination for sending a message for "key". The resulting peer 966 * destination for sending a message for @a key. The resulting peer
978 * must not be in the set of blocked peers.<p> 967 * must not be in the set of @a bloom blocked peers.
979 * 968 *
980 * Note that we should not ALWAYS select the closest peer to the 969 * Note that we should not ALWAYS select the closest peer to the
981 * target, peers further away from the target should be chosen with 970 * target, we do a "random" peer selection if the number of @a hops
982 * exponentially declining probability. 971 * is below the logarithm of the network size estimate.
983 *
984 * FIXME: double-check that this is fine
985 * 972 *
973 * In all cases, we only consider at most the first #bucket_size peers of any
974 * #k_buckets. The other peers in the bucket are there because GNUnet doesn't
975 * really allow the DHT to "reject" connections, but we only use the first
976 * #bucket_size, even if more exist. (The idea is to ensure that those
977 * connections are frequently used, and for others to be not used by the DHT,
978 * and thus possibly dropped by transport due to disuse).
986 * 979 *
987 * @param key the key we are selecting a peer to route to 980 * @param key the key we are selecting a peer to route to
988 * @param bloom a bloomfilter containing entries this request has seen already 981 * @param bloom a Bloom filter containing entries this request has seen already
989 * @param hops how many hops has this message traversed thus far 982 * @param hops how many hops has this message traversed thus far
990 * @return Peer to route to, or NULL on error 983 * @return Peer to route to, or NULL on error
991 */ 984 */
@@ -994,139 +987,194 @@ select_peer (const struct GNUNET_HashCode *key,
994 const struct GNUNET_CONTAINER_BloomFilter *bloom, 987 const struct GNUNET_CONTAINER_BloomFilter *bloom,
995 uint32_t hops) 988 uint32_t hops)
996{ 989{
997 unsigned int bc; 990 if (0 == closest_bucket)
998 unsigned int count; 991 {
999 unsigned int selected; 992 GNUNET_STATISTICS_update (GDS_stats,
1000 struct PeerInfo *pos; 993 "# Peer selection failed",
1001 struct PeerInfo *chosen; 994 1,
1002 995 GNUNET_NO);
996 return NULL; /* we have zero connections */
997 }
1003 if (hops >= GDS_NSE_get ()) 998 if (hops >= GDS_NSE_get ())
1004 { 999 {
1005 /* greedy selection (closest peer that is not in bloomfilter) */ 1000 /* greedy selection (closest peer that is not in Bloom filter) */
1006 unsigned int best_bucket = 0; 1001 struct PeerInfo *chosen = NULL;
1007 uint64_t best_in_bucket = UINT64_MAX; 1002 int best_bucket;
1003 int bucket_offset;
1008 1004
1009 chosen = NULL;
1010 for (bc = 0; bc <= closest_bucket; bc++)
1011 { 1005 {
1012 count = 0; 1006 struct GNUNET_HashCode xor;
1013 for (pos = k_buckets[bc].head; 1007
1014 (pos != NULL) && 1008 GNUNET_CRYPTO_hash_xor (key,
1015 (count < bucket_size); 1009 &my_identity_hash,
1010 &xor);
1011 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
1012 }
1013 if (best_bucket >= closest_bucket)
1014 bucket_offset = closest_bucket - 1;
1015 else
1016 bucket_offset = best_bucket;
1017 while (-1 != bucket_offset)
1018 {
1019 struct PeerBucket *bucket = &k_buckets[bucket_offset];
1020 unsigned int count = 0;
1021
1022 for (struct PeerInfo *pos = bucket->head;
1023 NULL != pos;
1016 pos = pos->next) 1024 pos = pos->next)
1017 { 1025 {
1018 unsigned int bucket; 1026 if (count >= bucket_size)
1019 uint64_t dist; 1027 break; /* we only consider first #bucket_size entries per bucket */
1020 1028 count++;
1021 bucket = GNUNET_CRYPTO_hash_matching_bits (key, 1029 if (GNUNET_YES ==
1022 &pos->phash); 1030 GNUNET_CONTAINER_bloomfilter_test (bloom,
1023 dist = get_distance (key, 1031 &pos->phash))
1024 &pos->phash, 1032 {
1025 bucket); 1033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1026 if (bucket < best_bucket) 1034 "Excluded peer `%s' due to BF match in greedy routing for %s\n",
1027 continue; 1035 GNUNET_i2s (pos->id),
1028 if (dist > best_in_bucket) 1036 GNUNET_h2s (key));
1029 continue; 1037 continue;
1030 best_bucket = bucket; 1038 }
1031 best_in_bucket = dist; 1039 if (NULL == chosen)
1032 if ( (NULL == bloom) ||
1033 (GNUNET_NO ==
1034 GNUNET_CONTAINER_bloomfilter_test (bloom,
1035 &pos->phash)) )
1036 { 1040 {
1041 /* First candidate */
1037 chosen = pos; 1042 chosen = pos;
1038 } 1043 }
1039 else 1044 else
1040 { 1045 {
1041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1046 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
1042 "Excluded peer `%s' due to BF match in greedy routing for %s\n", 1047 &chosen->phash,
1043 GNUNET_i2s (pos->id), 1048 key);
1044 GNUNET_h2s (key)); 1049 switch (delta)
1045 GNUNET_STATISTICS_update (GDS_stats, 1050 {
1046 gettext_noop ( 1051 case -1: /* pos closer */
1047 "# Peers excluded from routing due to Bloomfilter"), 1052 chosen = pos;
1048 1, 1053 break;
1049 GNUNET_NO); 1054 case 0: /* identical, impossible! */
1050 chosen = NULL; 1055 GNUNET_assert (0);
1056 break;
1057 case 1: /* chosen closer */
1058 break;
1059 }
1051 } 1060 }
1052 count++; 1061 count++;
1062 } /* for all (#bucket_size) peers in bucket */
1063 if (NULL != chosen)
1064 break;
1065
1066 /* If we chose nothing in first iteration, first go through deeper
1067 buckets (best chance to find a good match), and if we still found
1068 nothing, then to shallower buckets. Terminate on any match in the
1069 current bucket, as this search order guarantees that it can only get
1070 worse as we keep going. */
1071 if (bucket_offset > best_bucket)
1072 {
1073 /* Go through more deeper buckets */
1074 bucket_offset++;
1075 if (bucket_offset == closest_bucket)
1076 {
1077 /* Can't go any deeper, if nothing selected,
1078 go for shallower buckets */
1079 bucket_offset = best_bucket - 1;
1080 }
1053 } 1081 }
1054 } 1082 else
1083 {
1084 /* We're either at the 'best_bucket' or already moving
1085 on to shallower buckets. */
1086 if (bucket_offset == best_bucket)
1087 bucket_offset++; /* go for deeper buckets */
1088 else
1089 bucket_offset--; /* go for shallower buckets */
1090 }
1091 } /* for applicable buckets (starting at best match) */
1055 if (NULL == chosen) 1092 if (NULL == chosen)
1093 {
1056 GNUNET_STATISTICS_update (GDS_stats, 1094 GNUNET_STATISTICS_update (GDS_stats,
1057 gettext_noop ("# Peer selection failed"), 1095 "# Peer selection failed",
1058 1, 1096 1,
1059 GNUNET_NO); 1097 GNUNET_NO);
1060 else 1098 return NULL;
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1099 }
1062 "Selected peer `%s' in greedy routing for %s\n", 1100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1063 GNUNET_i2s (chosen->id), 1101 "Selected peer `%s' in greedy routing for %s\n",
1064 GNUNET_h2s (key)); 1102 GNUNET_i2s (chosen->id),
1103 GNUNET_h2s (key));
1065 return chosen; 1104 return chosen;
1066 } 1105 } /* end of 'greedy' peer selection */
1067 1106
1068 /* select "random" peer */ 1107 /* select "random" peer */
1069 /* count number of peers that are available and not filtered */ 1108 /* count number of peers that are available and not filtered,
1070 count = 0; 1109 but limit to at most #bucket_size peers, starting with
1071 for (bc = 0; bc <= closest_bucket; bc++) 1110 those 'furthest' from us. */
1072 { 1111 {
1073 pos = k_buckets[bc].head; 1112 unsigned int total = 0;
1074 while ((NULL != pos) && (count < bucket_size)) 1113 unsigned int selected;
1114
1115 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1075 { 1116 {
1076 if ((NULL != bloom) && 1117 unsigned int count = 0;
1077 (GNUNET_YES == 1118
1078 GNUNET_CONTAINER_bloomfilter_test (bloom, 1119 for (struct PeerInfo *pos = k_buckets[bc].head;
1079 &pos->phash))) 1120 NULL != pos;
1121 pos = pos->next)
1080 { 1122 {
1081 GNUNET_STATISTICS_update (GDS_stats, 1123 count++;
1082 gettext_noop 1124 if (count > bucket_size)
1083 ( 1125 break; /* limits search to #bucket_size peers per bucket */
1084 "# Peers excluded from routing due to Bloomfilter"), 1126 if (GNUNET_YES ==
1085 1, GNUNET_NO); 1127 GNUNET_CONTAINER_bloomfilter_test (bloom,
1086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1128 &pos->phash))
1087 "Excluded peer `%s' due to BF match in random routing for %s\n", 1129 {
1088 GNUNET_i2s (pos->id), 1130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089 GNUNET_h2s (key)); 1131 "Excluded peer `%s' due to BF match in random routing for %s\n",
1090 pos = pos->next; 1132 GNUNET_i2s (pos->id),
1091 continue; /* Ignore bloomfiltered peers */ 1133 GNUNET_h2s (key));
1092 } 1134 continue; /* Ignore filtered peers */
1093 count++; 1135 }
1094 pos = pos->next; 1136 total++;
1137 } /* for all peers in bucket */
1138 } /* for all buckets */
1139 if (0 == total) /* No peers to select from! */
1140 {
1141 GNUNET_STATISTICS_update (GDS_stats,
1142 "# Peer selection failed",
1143 1,
1144 GNUNET_NO);
1145 return NULL;
1095 } 1146 }
1096 } 1147
1097 if (0 == count) /* No peers to select from! */ 1148 /* Now actually choose a peer */
1098 { 1149 selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1099 GNUNET_STATISTICS_update (GDS_stats, 1150 total);
1100 gettext_noop ("# Peer selection failed"), 1, 1151 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1101 GNUNET_NO);
1102 return NULL;
1103 }
1104 /* Now actually choose a peer */
1105 selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1106 count);
1107 count = 0;
1108 for (bc = 0; bc <= closest_bucket; bc++)
1109 {
1110 for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size));
1111 pos = pos->next)
1112 { 1152 {
1113 if ((bloom != NULL) && 1153 unsigned int count = 0;
1114 (GNUNET_YES == 1154
1115 GNUNET_CONTAINER_bloomfilter_test (bloom, 1155 for (struct PeerInfo *pos = k_buckets[bc].head;
1116 &pos->phash))) 1156 pos != NULL;
1117 { 1157 pos = pos->next)
1118 continue; /* Ignore bloomfiltered peers */
1119 }
1120 if (0 == selected--)
1121 { 1158 {
1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1159 count++;
1123 "Selected peer `%s' in random routing for %s\n", 1160 if (count > bucket_size)
1124 GNUNET_i2s (pos->id), 1161 break; /* limits search to #bucket_size peers per bucket */
1125 GNUNET_h2s (key)); 1162
1126 return pos; 1163 if (GNUNET_YES ==
1127 } 1164 GNUNET_CONTAINER_bloomfilter_test (bloom,
1128 } 1165 &pos->phash))
1129 } 1166 continue; /* Ignore bloomfiltered peers */
1167 if (0 == selected--)
1168 {
1169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1170 "Selected peer `%s' in random routing for %s\n",
1171 GNUNET_i2s (pos->id),
1172 GNUNET_h2s (key));
1173 return pos;
1174 }
1175 } /* for peers in bucket */
1176 } /* for all buckets */
1177 } /* random peer selection scope */
1130 GNUNET_break (0); 1178 GNUNET_break (0);
1131 return NULL; 1179 return NULL;
1132} 1180}
@@ -1137,13 +1185,13 @@ select_peer (const struct GNUNET_HashCode *key,
1137 * forwarded to. 1185 * forwarded to.
1138 * 1186 *
1139 * @param key routing key 1187 * @param key routing key
1140 * @param bloom bloom filter excluding peers as targets, all selected 1188 * @param[in,out] bloom Bloom filter excluding peers as targets,
1141 * peers will be added to the bloom filter 1189 * all selected peers will be added to the Bloom filter
1142 * @param hop_count number of hops the request has traversed so far 1190 * @param hop_count number of hops the request has traversed so far
1143 * @param target_replication desired number of replicas 1191 * @param target_replication desired number of replicas
1144 * @param targets where to store an array of target peers (to be 1192 * @param[out] targets where to store an array of target peers (to be
1145 * free'd by the caller) 1193 * free()ed by the caller)
1146 * @return number of peers returned in 'targets'. 1194 * @return number of peers returned in @a targets.
1147 */ 1195 */
1148static unsigned int 1196static unsigned int
1149get_target_peers (const struct GNUNET_HashCode *key, 1197get_target_peers (const struct GNUNET_HashCode *key,
@@ -1152,23 +1200,24 @@ get_target_peers (const struct GNUNET_HashCode *key,
1152 uint32_t target_replication, 1200 uint32_t target_replication,
1153 struct PeerInfo ***targets) 1201 struct PeerInfo ***targets)
1154{ 1202{
1155 unsigned int ret; 1203 unsigned int target;
1156 unsigned int off; 1204 unsigned int off;
1157 struct PeerInfo **rtargets; 1205 struct PeerInfo **rtargets;
1158 struct PeerInfo *nxt;
1159 1206
1160 GNUNET_assert (NULL != bloom); 1207 GNUNET_assert (NULL != bloom);
1161 ret = get_forward_count (hop_count, 1208 target = get_forward_count (hop_count,
1162 target_replication); 1209 target_replication);
1163 if (0 == ret) 1210 if (0 == target)
1164 { 1211 {
1165 *targets = NULL; 1212 *targets = NULL;
1166 return 0; 1213 return 0;
1167 } 1214 }
1168 rtargets = GNUNET_new_array (ret, 1215 rtargets = GNUNET_new_array (target,
1169 struct PeerInfo *); 1216 struct PeerInfo *);
1170 for (off = 0; off < ret; off++) 1217 for (off = 0; off < target; off++)
1171 { 1218 {
1219 struct PeerInfo *nxt;
1220
1172 nxt = select_peer (key, 1221 nxt = select_peer (key,
1173 bloom, 1222 bloom,
1174 hop_count); 1223 hop_count);
@@ -1187,7 +1236,7 @@ get_target_peers (const struct GNUNET_HashCode *key,
1187 GNUNET_CONTAINER_multipeermap_size (all_connected_peers), 1236 GNUNET_CONTAINER_multipeermap_size (all_connected_peers),
1188 (unsigned int) hop_count, 1237 (unsigned int) hop_count,
1189 GNUNET_h2s (key), 1238 GNUNET_h2s (key),
1190 ret); 1239 target);
1191 if (0 == off) 1240 if (0 == off)
1192 { 1241 {
1193 GNUNET_free (rtargets); 1242 GNUNET_free (rtargets);
@@ -1199,67 +1248,37 @@ get_target_peers (const struct GNUNET_HashCode *key,
1199 "Forwarding query `%s' to %u peers (goal was %u peers)\n", 1248 "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1200 GNUNET_h2s (key), 1249 GNUNET_h2s (key),
1201 off, 1250 off,
1202 ret); 1251 target);
1203 return off; 1252 return off;
1204} 1253}
1205 1254
1206 1255
1207/** 1256enum GNUNET_GenericReturnValue
1208 * Perform a PUT operation. Forwards the given request to other 1257GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1209 * peers. Does not store the data locally. Does not give the
1210 * data to local clients. May do nothing if this is the only
1211 * peer in the network (or if we are the closest peer in the
1212 * network).
1213 *
1214 * @param type type of the block
1215 * @param options routing options
1216 * @param desired_replication_level desired replication count
1217 * @param expiration_time when does the content expire
1218 * @param hop_count how many hops has this message traversed so far
1219 * @param bf Bloom filter of peers this PUT has already traversed
1220 * @param key key for the content
1221 * @param put_path_length number of entries in @a put_path
1222 * @param put_path peers this request has traversed so far (if tracked)
1223 * @param data payload to store
1224 * @param data_size number of bytes in @a data
1225 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
1226 */
1227int
1228GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1229 enum GNUNET_DHT_RouteOption options, 1258 enum GNUNET_DHT_RouteOption options,
1230 uint32_t desired_replication_level, 1259 uint32_t desired_replication_level,
1231 struct GNUNET_TIME_Absolute expiration_time,
1232 uint32_t hop_count, 1260 uint32_t hop_count,
1233 struct GNUNET_CONTAINER_BloomFilter *bf, 1261 struct GNUNET_CONTAINER_BloomFilter *bf)
1234 const struct GNUNET_HashCode *key,
1235 unsigned int put_path_length,
1236 struct GNUNET_PeerIdentity *put_path,
1237 const void *data,
1238 size_t data_size)
1239{ 1262{
1240 unsigned int target_count; 1263 unsigned int target_count;
1241 unsigned int i;
1242 struct PeerInfo **targets; 1264 struct PeerInfo **targets;
1243 struct PeerInfo *target;
1244 size_t msize; 1265 size_t msize;
1245 struct GNUNET_MQ_Envelope *env;
1246 struct PeerPutMessage *ppm;
1247 struct GNUNET_PeerIdentity *pp;
1248 unsigned int skip_count; 1266 unsigned int skip_count;
1267 unsigned int put_path_length = bd->put_path_length;
1249 1268
1250 GNUNET_assert (NULL != bf); 1269 GNUNET_assert (NULL != bf);
1251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1252 "Adding myself (%s) to PUT bloomfilter for %s\n", 1271 "Adding myself (%s) to PUT bloomfilter for %s\n",
1253 GNUNET_i2s (&my_identity), 1272 GNUNET_i2s (&my_identity),
1254 GNUNET_h2s (key)); 1273 GNUNET_h2s (&bd->key));
1255 GNUNET_CONTAINER_bloomfilter_add (bf, 1274 GNUNET_CONTAINER_bloomfilter_add (bf,
1256 &my_identity_hash); 1275 &my_identity_hash);
1257 GNUNET_STATISTICS_update (GDS_stats, 1276 GNUNET_STATISTICS_update (GDS_stats,
1258 gettext_noop ("# PUT requests routed"), 1277 "# PUT requests routed",
1259 1, 1278 1,
1260 GNUNET_NO); 1279 GNUNET_NO);
1261 target_count 1280 target_count
1262 = get_target_peers (key, 1281 = get_target_peers (&bd->key,
1263 bf, 1282 bf,
1264 hop_count, 1283 hop_count,
1265 desired_replication_level, 1284 desired_replication_level,
@@ -1268,17 +1287,18 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1268 { 1287 {
1269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1270 "Routing PUT for %s terminates after %u hops at %s\n", 1289 "Routing PUT for %s terminates after %u hops at %s\n",
1271 GNUNET_h2s (key), 1290 GNUNET_h2s (&bd->key),
1272 (unsigned int) hop_count, 1291 (unsigned int) hop_count,
1273 GNUNET_i2s (&my_identity)); 1292 GNUNET_i2s (&my_identity));
1274 return GNUNET_NO; 1293 return GNUNET_NO;
1275 } 1294 }
1276 msize = put_path_length * sizeof(struct GNUNET_PeerIdentity) + data_size; 1295 msize = bd->put_path_length * sizeof(struct GNUNET_PeerIdentity)
1296 + bd->data_size;
1277 if (msize + sizeof(struct PeerPutMessage) 1297 if (msize + sizeof(struct PeerPutMessage)
1278 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) 1298 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1279 { 1299 {
1280 put_path_length = 0; 1300 put_path_length = 0;
1281 msize = data_size; 1301 msize = bd->data_size;
1282 } 1302 }
1283 if (msize + sizeof(struct PeerPutMessage) 1303 if (msize + sizeof(struct PeerPutMessage)
1284 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) 1304 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
@@ -1287,21 +1307,19 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1287 GNUNET_free (targets); 1307 GNUNET_free (targets);
1288 return GNUNET_NO; 1308 return GNUNET_NO;
1289 } 1309 }
1290 GNUNET_STATISTICS_update (GDS_stats,
1291 gettext_noop (
1292 "# PUT messages queued for transmission"),
1293 target_count,
1294 GNUNET_NO);
1295 skip_count = 0; 1310 skip_count = 0;
1296 for (i = 0; i < target_count; i++) 1311 for (unsigned int i = 0; i < target_count; i++)
1297 { 1312 {
1298 target = targets[i]; 1313 struct PeerInfo *target = targets[i];
1314 struct GNUNET_MQ_Envelope *env;
1315 struct PeerPutMessage *ppm;
1316 struct GNUNET_PeerIdentity *pp;
1317
1299 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER) 1318 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1300 { 1319 {
1301 /* skip */ 1320 /* skip */
1302 GNUNET_STATISTICS_update (GDS_stats, 1321 GNUNET_STATISTICS_update (GDS_stats,
1303 gettext_noop ( 1322 "# P2P messages dropped due to full queue",
1304 "# P2P messages dropped due to full queue"),
1305 1, 1323 1,
1306 GNUNET_NO); 1324 GNUNET_NO);
1307 skip_count++; 1325 skip_count++;
@@ -1309,18 +1327,18 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1309 } 1327 }
1310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1311 "Routing PUT for %s after %u hops to %s\n", 1329 "Routing PUT for %s after %u hops to %s\n",
1312 GNUNET_h2s (key), 1330 GNUNET_h2s (&bd->key),
1313 (unsigned int) hop_count, 1331 (unsigned int) hop_count,
1314 GNUNET_i2s (target->id)); 1332 GNUNET_i2s (target->id));
1315 env = GNUNET_MQ_msg_extra (ppm, 1333 env = GNUNET_MQ_msg_extra (ppm,
1316 msize, 1334 msize,
1317 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); 1335 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1318 ppm->options = htonl (options); 1336 ppm->options = htonl (options);
1319 ppm->type = htonl (type); 1337 ppm->type = htonl (bd->type);
1320 ppm->hop_count = htonl (hop_count + 1); 1338 ppm->hop_count = htonl (hop_count + 1);
1321 ppm->desired_replication_level = htonl (desired_replication_level); 1339 ppm->desired_replication_level = htonl (desired_replication_level);
1322 ppm->put_path_length = htonl (put_path_length); 1340 ppm->put_path_length = htonl (put_path_length);
1323 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); 1341 ppm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1324 GNUNET_break (GNUNET_YES == 1342 GNUNET_break (GNUNET_YES ==
1325 GNUNET_CONTAINER_bloomfilter_test (bf, 1343 GNUNET_CONTAINER_bloomfilter_test (bf,
1326 &target->phash)); 1344 &target->phash));
@@ -1328,40 +1346,27 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1328 GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, 1346 GNUNET_CONTAINER_bloomfilter_get_raw_data (bf,
1329 ppm->bloomfilter, 1347 ppm->bloomfilter,
1330 DHT_BLOOM_SIZE)); 1348 DHT_BLOOM_SIZE));
1331 ppm->key = *key; 1349 ppm->key = bd->key;
1332 pp = (struct GNUNET_PeerIdentity *) &ppm[1]; 1350 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1333 GNUNET_memcpy (pp, 1351 GNUNET_memcpy (pp,
1334 put_path, 1352 bd->put_path,
1335 sizeof(struct GNUNET_PeerIdentity) * put_path_length); 1353 sizeof(struct GNUNET_PeerIdentity) * put_path_length);
1336 GNUNET_memcpy (&pp[put_path_length], 1354 GNUNET_memcpy (&pp[put_path_length],
1337 data, 1355 bd->data,
1338 data_size); 1356 bd->data_size);
1339 GNUNET_MQ_send (target->mq, 1357 GNUNET_MQ_send (target->mq,
1340 env); 1358 env);
1341 } 1359 }
1342 GNUNET_free (targets); 1360 GNUNET_free (targets);
1361 GNUNET_STATISTICS_update (GDS_stats,
1362 "# PUT messages queued for transmission",
1363 target_count - skip_count,
1364 GNUNET_NO);
1343 return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO; 1365 return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1344} 1366}
1345 1367
1346 1368
1347/** 1369enum GNUNET_GenericReturnValue
1348 * Perform a GET operation. Forwards the given request to other
1349 * peers. Does not lookup the key locally. May do nothing if this is
1350 * the only peer in the network (or if we are the closest peer in the
1351 * network).
1352 *
1353 * @param type type of the block
1354 * @param options routing options
1355 * @param desired_replication_level desired replication count
1356 * @param hop_count how many hops did this request traverse so far?
1357 * @param key key for the content
1358 * @param xquery extended query
1359 * @param xquery_size number of bytes in @a xquery
1360 * @param bg group to use for filtering replies
1361 * @param peer_bf filter for peers not to select (again)
1362 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
1363 */
1364int
1365GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 1370GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1366 enum GNUNET_DHT_RouteOption options, 1371 enum GNUNET_DHT_RouteOption options,
1367 uint32_t desired_replication_level, 1372 uint32_t desired_replication_level,
@@ -1374,11 +1379,7 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1374{ 1379{
1375 unsigned int target_count; 1380 unsigned int target_count;
1376 struct PeerInfo **targets; 1381 struct PeerInfo **targets;
1377 struct PeerInfo *target;
1378 struct GNUNET_MQ_Envelope *env;
1379 size_t msize; 1382 size_t msize;
1380 struct PeerGetMessage *pgm;
1381 char *xq;
1382 size_t reply_bf_size; 1383 size_t reply_bf_size;
1383 void *reply_bf; 1384 void *reply_bf;
1384 unsigned int skip_count; 1385 unsigned int skip_count;
@@ -1386,7 +1387,7 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1386 1387
1387 GNUNET_assert (NULL != peer_bf); 1388 GNUNET_assert (NULL != peer_bf);
1388 GNUNET_STATISTICS_update (GDS_stats, 1389 GNUNET_STATISTICS_update (GDS_stats,
1389 gettext_noop ("# GET requests routed"), 1390 "# GET requests routed",
1390 1, 1391 1,
1391 GNUNET_NO); 1392 GNUNET_NO);
1392 target_count = get_target_peers (key, 1393 target_count = get_target_peers (key,
@@ -1428,23 +1429,22 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1428 GNUNET_free (targets); 1429 GNUNET_free (targets);
1429 return GNUNET_NO; 1430 return GNUNET_NO;
1430 } 1431 }
1431 GNUNET_STATISTICS_update (GDS_stats,
1432 gettext_noop (
1433 "# GET messages queued for transmission"),
1434 target_count,
1435 GNUNET_NO);
1436 /* forward request */ 1432 /* forward request */
1437 skip_count = 0; 1433 skip_count = 0;
1438 for (unsigned int i = 0; i < target_count; i++) 1434 for (unsigned int i = 0; i < target_count; i++)
1439 { 1435 {
1440 target = targets[i]; 1436 struct PeerInfo *target = targets[i];
1437 struct GNUNET_MQ_Envelope *env;
1438 struct PeerGetMessage *pgm;
1439 char *xq;
1440
1441 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER) 1441 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1442 { 1442 {
1443 /* skip */ 1443 /* skip */
1444 GNUNET_STATISTICS_update (GDS_stats, 1444 GNUNET_STATISTICS_update (GDS_stats,
1445 gettext_noop ( 1445 "# P2P messages dropped due to full queue",
1446 "# P2P messages dropped due to full queue"), 1446 1,
1447 1, GNUNET_NO); 1447 GNUNET_NO);
1448 skip_count++; 1448 skip_count++;
1449 continue; 1449 continue;
1450 } 1450 }
@@ -1480,115 +1480,94 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1480 GNUNET_MQ_send (target->mq, 1480 GNUNET_MQ_send (target->mq,
1481 env); 1481 env);
1482 } 1482 }
1483 GNUNET_STATISTICS_update (GDS_stats,
1484 "# GET messages queued for transmission",
1485 target_count - skip_count,
1486 GNUNET_NO);
1483 GNUNET_free (targets); 1487 GNUNET_free (targets);
1484 GNUNET_free (reply_bf); 1488 GNUNET_free (reply_bf);
1485 return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO; 1489 return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
1486} 1490}
1487 1491
1488 1492
1489/** 1493struct PeerInfo *
1490 * Handle a reply (route to origin). Only forwards the reply back to 1494GDS_NEIGHBOURS_lookup_peer (const struct GNUNET_PeerIdentity *target)
1491 * the given peer. Does not do local caching or forwarding to local 1495{
1492 * clients. 1496 return GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
1493 * 1497 target);
1494 * @param target neighbour that should receive the block (if still connected) 1498}
1495 * @param type type of the block 1499
1496 * @param expiration_time when does the content expire 1500
1497 * @param key key for the content
1498 * @param put_path_length number of entries in @a put_path
1499 * @param put_path peers the original PUT traversed (if tracked)
1500 * @param get_path_length number of entries in @a get_path
1501 * @param get_path peers this reply has traversed so far (if tracked)
1502 * @param data payload of the reply
1503 * @param data_size number of bytes in @a data
1504 */
1505void 1501void
1506GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, 1502GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1507 enum GNUNET_BLOCK_Type type, 1503 const struct GDS_DATACACHE_BlockData *bd,
1508 struct GNUNET_TIME_Absolute expiration_time, 1504 const struct GNUNET_HashCode *query_hash,
1509 const struct GNUNET_HashCode *key,
1510 unsigned int put_path_length,
1511 const struct GNUNET_PeerIdentity *put_path,
1512 unsigned int get_path_length, 1505 unsigned int get_path_length,
1513 const struct GNUNET_PeerIdentity *get_path, 1506 const struct GNUNET_PeerIdentity *get_path)
1514 const void *data,
1515 size_t data_size)
1516{ 1507{
1517 struct PeerInfo *pi;
1518 struct GNUNET_MQ_Envelope *env; 1508 struct GNUNET_MQ_Envelope *env;
1519 size_t msize;
1520 struct PeerResultMessage *prm; 1509 struct PeerResultMessage *prm;
1521 struct GNUNET_PeerIdentity *paths; 1510 struct GNUNET_PeerIdentity *paths;
1511 size_t msize;
1522 1512
1523 msize = data_size + (get_path_length + put_path_length) 1513 msize = bd->data_size + (get_path_length + bd->put_path_length)
1524 * sizeof(struct GNUNET_PeerIdentity); 1514 * sizeof(struct GNUNET_PeerIdentity);
1525 if ((msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) || 1515 if ( (msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
1526 (get_path_length > 1516 (get_path_length >
1527 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) || 1517 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1528 (put_path_length > 1518 (bd->put_path_length >
1529 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) || 1519 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1530 (data_size > GNUNET_MAX_MESSAGE_SIZE)) 1520 (bd->data_size > GNUNET_MAX_MESSAGE_SIZE))
1531 { 1521 {
1532 GNUNET_break (0); 1522 GNUNET_break (0);
1533 return; 1523 return;
1534 } 1524 }
1535 pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
1536 target);
1537 if (NULL == pi)
1538 {
1539 /* peer disconnected in the meantime, drop reply */
1540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1541 "No matching peer for reply for key %s\n",
1542 GNUNET_h2s (key));
1543 return;
1544 }
1545 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER) 1525 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
1546 { 1526 {
1547 /* skip */ 1527 /* skip */
1548 GNUNET_STATISTICS_update (GDS_stats, 1528 GNUNET_STATISTICS_update (GDS_stats,
1549 gettext_noop ( 1529 "# P2P messages dropped due to full queue",
1550 "# P2P messages dropped due to full queue"),
1551 1, 1530 1,
1552 GNUNET_NO); 1531 GNUNET_NO);
1553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1554 "Peer queue full, ignoring reply for key %s\n", 1533 "Peer queue full, ignoring reply for key %s\n",
1555 GNUNET_h2s (key)); 1534 GNUNET_h2s (&bd->key));
1556 return; 1535 return;
1557 } 1536 }
1558 1537
1559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1560 "Forwarding reply for key %s to peer %s\n", 1539 "Forwarding reply for key %s to peer %s\n",
1561 GNUNET_h2s (key), 1540 GNUNET_h2s (query_hash),
1562 GNUNET_i2s (target)); 1541 GNUNET_i2s (pi->id));
1563 GNUNET_STATISTICS_update (GDS_stats, 1542 GNUNET_STATISTICS_update (GDS_stats,
1564 gettext_noop 1543 "# RESULT messages queued for transmission",
1565 ("# RESULT messages queued for transmission"), 1, 1544 1,
1566 GNUNET_NO); 1545 GNUNET_NO);
1567 env = GNUNET_MQ_msg_extra (prm, 1546 env = GNUNET_MQ_msg_extra (prm,
1568 msize, 1547 msize,
1569 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT); 1548 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1570 prm->type = htonl (type); 1549 prm->type = htonl (bd->type);
1571 prm->put_path_length = htonl (put_path_length); 1550 prm->put_path_length = htonl (bd->put_path_length);
1572 prm->get_path_length = htonl (get_path_length); 1551 prm->get_path_length = htonl (get_path_length);
1573 prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); 1552 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1574 prm->key = *key; 1553 prm->key = *query_hash;
1575 paths = (struct GNUNET_PeerIdentity *) &prm[1]; 1554 paths = (struct GNUNET_PeerIdentity *) &prm[1];
1576 GNUNET_memcpy (paths, 1555 GNUNET_memcpy (paths,
1577 put_path, 1556 bd->put_path,
1578 put_path_length * sizeof(struct GNUNET_PeerIdentity)); 1557 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
1579 GNUNET_memcpy (&paths[put_path_length], 1558 GNUNET_memcpy (&paths[bd->put_path_length],
1580 get_path, 1559 get_path,
1581 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 1560 get_path_length * sizeof(struct GNUNET_PeerIdentity));
1582 GNUNET_memcpy (&paths[put_path_length + get_path_length], 1561 GNUNET_memcpy (&paths[bd->put_path_length + get_path_length],
1583 data, 1562 bd->data,
1584 data_size); 1563 bd->data_size);
1585 GNUNET_MQ_send (pi->mq, 1564 GNUNET_MQ_send (pi->mq,
1586 env); 1565 env);
1587} 1566}
1588 1567
1589 1568
1590/** 1569/**
1591 * To be called on core init/fail. 1570 * To be called on core init.
1592 * 1571 *
1593 * @param cls service closure 1572 * @param cls service closure
1594 * @param identity the public identity of this peer 1573 * @param identity the public identity of this peer
@@ -1603,7 +1582,7 @@ core_init (void *cls,
1603 GNUNET_i2s (identity)); 1582 GNUNET_i2s (identity));
1604 my_identity = *identity; 1583 my_identity = *identity;
1605 GNUNET_CRYPTO_hash (identity, 1584 GNUNET_CRYPTO_hash (identity,
1606 sizeof(struct GNUNET_PeerIdentity), 1585 sizeof(struct GNUNET_PeerIdentity),
1607 &my_identity_hash); 1586 &my_identity_hash);
1608 GNUNET_SERVICE_resume (GDS_service); 1587 GNUNET_SERVICE_resume (GDS_service);
1609} 1588}
@@ -1616,21 +1595,19 @@ core_init (void *cls,
1616 * @param message message 1595 * @param message message
1617 * @return #GNUNET_OK if the message is valid 1596 * @return #GNUNET_OK if the message is valid
1618 */ 1597 */
1619static int 1598static enum GNUNET_GenericReturnValue
1620check_dht_p2p_put (void *cls, 1599check_dht_p2p_put (void *cls,
1621 const struct PeerPutMessage *put) 1600 const struct PeerPutMessage *put)
1622{ 1601{
1623 uint32_t putlen; 1602 uint16_t msize = ntohs (put->header.size);
1624 uint16_t msize; 1603 uint32_t putlen = ntohl (put->put_path_length);
1625 1604
1626 (void) cls; 1605 (void) cls;
1627 msize = ntohs (put->header.size); 1606 if ( (msize <
1628 putlen = ntohl (put->put_path_length); 1607 sizeof(struct PeerPutMessage)
1629 if ((msize < 1608 + putlen * sizeof(struct GNUNET_PeerIdentity)) ||
1630 sizeof(struct PeerPutMessage) 1609 (putlen >
1631 + putlen * sizeof(struct GNUNET_PeerIdentity)) || 1610 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) )
1632 (putlen >
1633 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
1634 { 1611 {
1635 GNUNET_break_op (0); 1612 GNUNET_break_op (0);
1636 return GNUNET_SYSERR; 1613 return GNUNET_SYSERR;
@@ -1650,51 +1627,55 @@ handle_dht_p2p_put (void *cls,
1650 const struct PeerPutMessage *put) 1627 const struct PeerPutMessage *put)
1651{ 1628{
1652 struct PeerInfo *peer = cls; 1629 struct PeerInfo *peer = cls;
1653 const struct GNUNET_PeerIdentity *put_path; 1630 uint16_t msize = ntohs (put->header.size);
1654 const void *payload; 1631 enum GNUNET_DHT_RouteOption options
1655 uint32_t putlen; 1632 = (enum GNUNET_DHT_RouteOption) ntohl (put->options);
1656 uint16_t msize; 1633 struct GDS_DATACACHE_BlockData bd = {
1657 size_t payload_size; 1634 .key = put->key,
1658 enum GNUNET_DHT_RouteOption options; 1635 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
1659 struct GNUNET_CONTAINER_BloomFilter *bf; 1636 .type = ntohl (put->type)
1660 struct GNUNET_HashCode test_key; 1637 };
1661 int forwarded; 1638 const struct GNUNET_PeerIdentity *put_path
1662 struct GNUNET_TIME_Absolute exp_time; 1639 = (const struct GNUNET_PeerIdentity *) &put[1];
1663 1640 uint32_t putlen
1664 exp_time = GNUNET_TIME_absolute_ntoh (put->expiration_time); 1641 = ntohl (put->put_path_length);
1665 if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us) 1642
1643 bd.data_size = msize - (sizeof(*put)
1644 + putlen * sizeof(struct GNUNET_PeerIdentity));
1645 bd.data = &put_path[putlen];
1646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1647 "PUT for `%s' from %s\n",
1648 GNUNET_h2s (&put->key),
1649 GNUNET_i2s (peer->id));
1650 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
1666 { 1651 {
1667 GNUNET_STATISTICS_update (GDS_stats, 1652 GNUNET_STATISTICS_update (GDS_stats,
1668 gettext_noop ("# Expired PUTs discarded"), 1653 "# Expired PUTs discarded",
1669 1, 1654 1,
1670 GNUNET_NO); 1655 GNUNET_NO);
1671 return; 1656 return;
1672 } 1657 }
1673 msize = ntohs (put->header.size);
1674 putlen = ntohl (put->put_path_length);
1675 GNUNET_STATISTICS_update (GDS_stats, 1658 GNUNET_STATISTICS_update (GDS_stats,
1676 gettext_noop ("# P2P PUT requests received"), 1659 "# P2P PUT requests received",
1677 1, 1660 1,
1678 GNUNET_NO); 1661 GNUNET_NO);
1679 GNUNET_STATISTICS_update (GDS_stats, 1662 GNUNET_STATISTICS_update (GDS_stats,
1680 gettext_noop ("# P2P PUT bytes received"), 1663 "# P2P PUT bytes received",
1681 msize, 1664 msize,
1682 GNUNET_NO); 1665 GNUNET_NO);
1683 put_path = (const struct GNUNET_PeerIdentity *) &put[1];
1684 payload = &put_path[putlen];
1685 options = ntohl (put->options);
1686 payload_size = msize - (sizeof(struct PeerPutMessage)
1687 + putlen * sizeof(struct GNUNET_PeerIdentity));
1688
1689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1690 "PUT for `%s' from %s\n",
1691 GNUNET_h2s (&put->key),
1692 GNUNET_i2s (peer->id));
1693 if (GNUNET_YES == log_route_details_stderr) 1666 if (GNUNET_YES == log_route_details_stderr)
1694 { 1667 {
1695 char *tmp; 1668 char *tmp;
1696 char *pp; 1669 char *pp;
1697 1670 struct GNUNET_HashCode mxor;
1671 struct GNUNET_HashCode pxor;
1672
1673 GNUNET_CRYPTO_hash_xor (&my_identity_hash,
1674 &put->key,
1675 &mxor);
1676 GNUNET_CRYPTO_hash_xor (&peer->phash,
1677 &put->key,
1678 &pxor);
1698 pp = GNUNET_STRINGS_pp2s (put_path, 1679 pp = GNUNET_STRINGS_pp2s (put_path,
1699 putlen); 1680 putlen);
1700 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); 1681 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
@@ -1704,83 +1685,65 @@ handle_dht_p2p_put (void *cls,
1704 GNUNET_i2s (peer->id), 1685 GNUNET_i2s (peer->id),
1705 tmp, 1686 tmp,
1706 ntohl (put->hop_count), 1687 ntohl (put->hop_count),
1707 GNUNET_CRYPTO_hash_matching_bits (&peer->phash, 1688 GNUNET_CRYPTO_hash_count_leading_zeros (&pxor),
1708 &put->key), 1689 GNUNET_CRYPTO_hash_count_leading_zeros (&mxor),
1709 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
1710 &put->key),
1711 pp); 1690 pp);
1712 GNUNET_free (pp); 1691 GNUNET_free (pp);
1713 GNUNET_free (tmp); 1692 GNUNET_free (tmp);
1714 } 1693 }
1715 switch (GNUNET_BLOCK_get_key 1694
1716 (GDS_block_context,
1717 ntohl (put->type),
1718 payload,
1719 payload_size,
1720 &test_key))
1721 { 1695 {
1722 case GNUNET_YES: 1696 struct GNUNET_HashCode test_key;
1723 if (0 != memcmp (&test_key, 1697 enum GNUNET_GenericReturnValue ret;
1724 &put->key, 1698
1725 sizeof(struct GNUNET_HashCode))) 1699 ret = GNUNET_BLOCK_get_key (GDS_block_context,
1700 bd.type,
1701 bd.data,
1702 bd.data_size,
1703 &test_key);
1704 switch (ret)
1726 { 1705 {
1727 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key)); 1706 case GNUNET_YES:
1728 1707 if (0 != GNUNET_memcmp (&test_key,
1708 &bd.key))
1709 {
1710 GNUNET_break_op (0);
1711 return;
1712 }
1713 break;
1714 case GNUNET_NO:
1729 GNUNET_break_op (0); 1715 GNUNET_break_op (0);
1730 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1731 "PUT with key `%s' for block with key %s\n",
1732 put_s,
1733 GNUNET_h2s_full (&test_key));
1734 GNUNET_free (put_s);
1735 return; 1716 return;
1717 case GNUNET_SYSERR:
1718 /* cannot verify, good luck */
1719 break;
1736 } 1720 }
1737 break; 1721 }
1738 1722
1739 case GNUNET_NO: 1723 if (GNUNET_NO ==
1724 GNUNET_BLOCK_check_block (GDS_block_context,
1725 bd.type,
1726 &bd.key,
1727 bd.data,
1728 bd.data_size))
1729 {
1740 GNUNET_break_op (0); 1730 GNUNET_break_op (0);
1741 return; 1731 return;
1742
1743 case GNUNET_SYSERR:
1744 /* cannot verify, good luck */
1745 break;
1746 }
1747 if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
1748 {
1749 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
1750 ntohl (put->type),
1751 NULL, /* query group */
1752 GNUNET_BLOCK_EO_NONE,
1753 NULL, /* query */
1754 NULL, 0, /* xquery */
1755 payload,
1756 payload_size))
1757 {
1758 case GNUNET_BLOCK_EVALUATION_OK_MORE:
1759 case GNUNET_BLOCK_EVALUATION_OK_LAST:
1760 break;
1761
1762 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
1763 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
1764 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
1765 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
1766 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
1767 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
1768 default:
1769 GNUNET_break_op (0);
1770 return;
1771 }
1772 } 1732 }
1773 1733
1774 bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
1775 DHT_BLOOM_SIZE,
1776 GNUNET_CONSTANTS_BLOOMFILTER_K);
1777 GNUNET_break_op (GNUNET_YES ==
1778 GNUNET_CONTAINER_bloomfilter_test (bf,
1779 &peer->phash));
1780 { 1734 {
1735 struct GNUNET_CONTAINER_BloomFilter *bf;
1781 struct GNUNET_PeerIdentity pp[putlen + 1]; 1736 struct GNUNET_PeerIdentity pp[putlen + 1];
1782 1737
1738 bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
1739 DHT_BLOOM_SIZE,
1740 GNUNET_CONSTANTS_BLOOMFILTER_K);
1741 GNUNET_break_op (GNUNET_YES ==
1742 GNUNET_CONTAINER_bloomfilter_test (bf,
1743 &peer->phash));
1783 /* extend 'put path' by sender */ 1744 /* extend 'put path' by sender */
1745 bd.put_path = (const struct GNUNET_PeerIdentity *) pp;
1746 bd.put_path_length = putlen + 1;
1784 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) 1747 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1785 { 1748 {
1786#if SANITY_CHECKS 1749#if SANITY_CHECKS
@@ -1788,13 +1751,13 @@ handle_dht_p2p_put (void *cls,
1788 { 1751 {
1789 for (unsigned int j = 0; j < i; j++) 1752 for (unsigned int j = 0; j < i; j++)
1790 { 1753 {
1791 GNUNET_break (0 != memcmp (&pp[i], 1754 GNUNET_break (0 !=
1792 &pp[j], 1755 GNUNET_memcmp (&pp[i],
1793 sizeof(struct GNUNET_PeerIdentity))); 1756 &pp[j]));
1794 } 1757 }
1795 GNUNET_break (0 != memcmp (&pp[i], 1758 GNUNET_break (0 !=
1796 peer->id, 1759 GNUNET_memcmp (&pp[i],
1797 sizeof(struct GNUNET_PeerIdentity))); 1760 peer->id));
1798 } 1761 }
1799#endif 1762#endif
1800 GNUNET_memcpy (pp, 1763 GNUNET_memcpy (pp,
@@ -1804,56 +1767,41 @@ handle_dht_p2p_put (void *cls,
1804 putlen++; 1767 putlen++;
1805 } 1768 }
1806 else 1769 else
1807 putlen = 0; 1770 {
1771 bd.put_path_length = 0;
1772 }
1808 1773
1809 /* give to local clients */ 1774 /* give to local clients */
1810 GDS_CLIENTS_handle_reply (exp_time, 1775 GDS_CLIENTS_handle_reply (&bd,
1811 &put->key, 1776 &bd.key,
1812 0, 1777 0, NULL /* get path */);
1813 NULL, 1778
1814 putlen,
1815 pp,
1816 ntohl (put->type),
1817 payload_size,
1818 payload);
1819 /* store locally */ 1779 /* store locally */
1820 if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 1780 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1821 (GDS_am_closest_peer (&put->key, bf))) 1781 (GDS_am_closest_peer (&put->key,
1822 GDS_DATACACHE_handle_put (exp_time, 1782 bf)) )
1823 &put->key, 1783 GDS_DATACACHE_handle_put (&bd);
1824 putlen, 1784 {
1825 pp, 1785 enum GNUNET_GenericReturnValue forwarded;
1826 ntohl (put->type), 1786
1827 payload_size, 1787 /* route to other peers */
1828 payload); 1788 forwarded
1829 /* route to other peers */ 1789 = GDS_NEIGHBOURS_handle_put (&bd,
1830 forwarded = GDS_NEIGHBOURS_handle_put (ntohl (put->type), 1790 options,
1831 options, 1791 ntohl (put->desired_replication_level),
1832 ntohl ( 1792 ntohl (put->hop_count),
1833 put->desired_replication_level), 1793 bf);
1834 exp_time, 1794 /* notify monitoring clients */
1835 ntohl (put->hop_count), 1795 GDS_CLIENTS_process_put (options
1836 bf, 1796 | ((GNUNET_OK == forwarded)
1837 &put->key,
1838 putlen,
1839 pp,
1840 payload,
1841 payload_size);
1842 /* notify monitoring clients */
1843 GDS_CLIENTS_process_put (options
1844 | ((GNUNET_OK == forwarded)
1845 ? GNUNET_DHT_RO_LAST_HOP 1797 ? GNUNET_DHT_RO_LAST_HOP
1846 : 0), 1798 : 0),
1847 ntohl (put->type), 1799 &bd,
1848 ntohl (put->hop_count), 1800 ntohl (put->hop_count),
1849 ntohl (put->desired_replication_level), 1801 ntohl (put->desired_replication_level));
1850 putlen, pp, 1802 }
1851 exp_time, 1803 GNUNET_CONTAINER_bloomfilter_free (bf);
1852 &put->key,
1853 payload,
1854 payload_size);
1855 } 1804 }
1856 GNUNET_CONTAINER_bloomfilter_free (bf);
1857} 1805}
1858 1806
1859 1807
@@ -1861,55 +1809,51 @@ handle_dht_p2p_put (void *cls,
1861 * We have received a FIND PEER request. Send matching 1809 * We have received a FIND PEER request. Send matching
1862 * HELLOs back. 1810 * HELLOs back.
1863 * 1811 *
1864 * @param sender sender of the FIND PEER request 1812 * @param pi sender of the FIND PEER request
1865 * @param key peers close to this key are desired 1813 * @param key peers close to this key are desired
1866 * @param bg group for filtering peers 1814 * @param bg group for filtering peers
1867 */ 1815 */
1868static void 1816static void
1869handle_find_peer (const struct GNUNET_PeerIdentity *sender, 1817handle_find_peer (struct PeerInfo *pi,
1870 const struct GNUNET_HashCode *key, 1818 const struct GNUNET_HashCode *query_hash,
1871 struct GNUNET_BLOCK_Group *bg) 1819 struct GNUNET_BLOCK_Group *bg)
1872{ 1820{
1873 int bucket_idx; 1821 int bucket_idx;
1874 struct PeerBucket *bucket; 1822 struct PeerBucket *bucket;
1875 struct PeerInfo *peer; 1823 struct PeerInfo *peer;
1876 unsigned int choice; 1824 unsigned int choice;
1877 const struct GNUNET_HELLO_Message *hello; 1825 struct GDS_DATACACHE_BlockData bd = {
1878 size_t hello_size; 1826 .type = GNUNET_BLOCK_TYPE_DHT_HELLO
1827 };
1879 1828
1880 /* first, check about our own HELLO */ 1829 /* first, check about our own HELLO */
1881 if (NULL != GDS_my_hello) 1830 if (NULL != GDS_my_hello)
1882 { 1831 {
1883 hello_size = GNUNET_HELLO_size ((const struct 1832 bd.expiration_time = GNUNET_TIME_relative_to_absolute (
1884 GNUNET_HELLO_Message *) GDS_my_hello); 1833 hello_expiration),
1885 GNUNET_break (hello_size >= sizeof(struct GNUNET_MessageHeader)); 1834 bd.key = my_identity_hash,
1886 if (GNUNET_BLOCK_EVALUATION_OK_MORE == 1835 bd.data = GDS_my_hello;
1887 GNUNET_BLOCK_evaluate (GDS_block_context, 1836 bd.data_size = GNUNET_HELLO_size (
1888 GNUNET_BLOCK_TYPE_DHT_HELLO, 1837 (const struct GNUNET_HELLO_Message *) GDS_my_hello);
1889 bg, 1838 GNUNET_break (bd.data_size >= sizeof(struct GNUNET_MessageHeader));
1890 GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO, 1839 if (GNUNET_BLOCK_REPLY_OK_MORE ==
1891 &my_identity_hash, 1840 GNUNET_BLOCK_check_reply (GDS_block_context,
1892 NULL, 0, 1841 GNUNET_BLOCK_TYPE_DHT_HELLO,
1893 GDS_my_hello, 1842 bg,
1894 hello_size)) 1843 &my_identity_hash,
1844 NULL, 0,
1845 bd.data,
1846 bd.data_size))
1895 { 1847 {
1896 GDS_NEIGHBOURS_handle_reply (sender, 1848 GDS_NEIGHBOURS_handle_reply (pi,
1897 GNUNET_BLOCK_TYPE_DHT_HELLO, 1849 &bd,
1898 GNUNET_TIME_relative_to_absolute ( 1850 query_hash,
1899 hello_expiration), 1851 0, NULL /* get path */);
1900 key,
1901 0,
1902 NULL,
1903 0,
1904 NULL,
1905 GDS_my_hello,
1906 hello_size);
1907 } 1852 }
1908 else 1853 else
1909 { 1854 {
1910 GNUNET_STATISTICS_update (GDS_stats, 1855 GNUNET_STATISTICS_update (GDS_stats,
1911 gettext_noop ( 1856 "# FIND PEER requests ignored due to Bloomfilter",
1912 "# FIND PEER requests ignored due to Bloomfilter"),
1913 1, 1857 1,
1914 GNUNET_NO); 1858 GNUNET_NO);
1915 } 1859 }
@@ -1917,20 +1861,20 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1917 else 1861 else
1918 { 1862 {
1919 GNUNET_STATISTICS_update (GDS_stats, 1863 GNUNET_STATISTICS_update (GDS_stats,
1920 gettext_noop ( 1864 "# FIND PEER requests ignored due to lack of HELLO",
1921 "# FIND PEER requests ignored due to lack of HELLO"),
1922 1, 1865 1,
1923 GNUNET_NO); 1866 GNUNET_NO);
1924 } 1867 }
1925 1868
1926 /* then, also consider sending a random HELLO from the closest bucket */ 1869 /* then, also consider sending a random HELLO from the closest bucket */
1927 if (0 == memcmp (&my_identity_hash, 1870 /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */
1928 key, 1871 if (0 ==
1929 sizeof(struct GNUNET_HashCode))) 1872 GNUNET_memcmp (&my_identity_hash,
1930 bucket_idx = closest_bucket; 1873 query_hash))
1874 bucket_idx = closest_bucket - 1;
1931 else 1875 else
1932 bucket_idx = GNUNET_MIN ((int) closest_bucket, 1876 bucket_idx = GNUNET_MIN ((int) closest_bucket - 1,
1933 find_bucket (key)); 1877 find_bucket (query_hash));
1934 if (bucket_idx < 0) 1878 if (bucket_idx < 0)
1935 return; 1879 return;
1936 bucket = &k_buckets[bucket_idx]; 1880 bucket = &k_buckets[bucket_idx];
@@ -1946,82 +1890,69 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1946 choice--; 1890 choice--;
1947 } 1891 }
1948 choice = bucket->peers_size; 1892 choice = bucket->peers_size;
1949 do 1893
1950 { 1894 {
1951 peer = peer->next; 1895 const struct GNUNET_HELLO_Message *hello;
1952 if (0 == choice--) 1896 size_t hello_size;
1953 return; /* no non-masked peer available */ 1897
1954 if (NULL == peer) 1898 do
1955 peer = bucket->head; 1899 {
1956 hello = GDS_HELLO_get (peer->id); 1900 peer = peer->next;
1901 if (0 == choice--)
1902 return; /* no non-masked peer available */
1903 if (NULL == peer)
1904 peer = bucket->head;
1905 hello = GDS_HELLO_get (peer->id);
1906 } while ( (NULL == hello) ||
1907 (GNUNET_BLOCK_REPLY_OK_MORE !=
1908 GNUNET_BLOCK_check_reply (
1909 GDS_block_context,
1910 GNUNET_BLOCK_TYPE_DHT_HELLO,
1911 bg,
1912 &peer->phash,
1913 NULL, 0, /* xquery */
1914 hello,
1915 (hello_size = GNUNET_HELLO_size (hello)))));
1916 bd.expiration_time = GNUNET_TIME_relative_to_absolute (
1917 GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION);
1918 bd.key = peer->phash;
1919 bd.data = hello;
1920 bd.data_size = hello_size;
1921 GDS_NEIGHBOURS_handle_reply (pi,
1922 &bd,
1923 query_hash,
1924 0, NULL /* get path */);
1957 } 1925 }
1958 while ((NULL == hello) ||
1959 (GNUNET_BLOCK_EVALUATION_OK_MORE !=
1960 GNUNET_BLOCK_evaluate (GDS_block_context,
1961 GNUNET_BLOCK_TYPE_DHT_HELLO,
1962 bg,
1963 GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO,
1964 &peer->phash,
1965 NULL, 0,
1966 hello,
1967 (hello_size = GNUNET_HELLO_size (hello)))));
1968 GDS_NEIGHBOURS_handle_reply (sender,
1969 GNUNET_BLOCK_TYPE_DHT_HELLO,
1970 GNUNET_TIME_relative_to_absolute
1971 (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION),
1972 key,
1973 0,
1974 NULL,
1975 0,
1976 NULL,
1977 hello,
1978 hello_size);
1979} 1926}
1980 1927
1981 1928
1982/** 1929/**
1983 * Handle a result from local datacache for a GET operation. 1930 * Handle an exact result from local datacache for a GET operation.
1984 * 1931 *
1985 * @param cls the `struct PeerInfo` for which this is a reply 1932 * @param cls the `struct PeerInfo` for which this is a reply
1986 * @param type type of the block 1933 * @param bd details about the block we found locally
1987 * @param expiration_time when does the content expire
1988 * @param key key for the content
1989 * @param put_path_length number of entries in @a put_path
1990 * @param put_path peers the original PUT traversed (if tracked)
1991 * @param get_path_length number of entries in @a get_path
1992 * @param get_path peers this reply has traversed so far (if tracked)
1993 * @param data payload of the reply
1994 * @param data_size number of bytes in @a data
1995 */ 1934 */
1996static void 1935static void
1997handle_local_result (void *cls, 1936handle_local_result (void *cls,
1998 enum GNUNET_BLOCK_Type type, 1937 const struct GDS_DATACACHE_BlockData *bd)
1999 struct GNUNET_TIME_Absolute expiration_time,
2000 const struct GNUNET_HashCode *key,
2001 unsigned int put_path_length,
2002 const struct GNUNET_PeerIdentity *put_path,
2003 unsigned int get_path_length,
2004 const struct GNUNET_PeerIdentity *get_path,
2005 const void *data,
2006 size_t data_size)
2007{ 1938{
2008 struct PeerInfo *peer = cls; 1939 struct PeerInfo *peer = cls;
2009 char *pp;
2010 1940
2011 pp = GNUNET_STRINGS_pp2s (put_path, 1941 {
2012 put_path_length); 1942 char *pp;
2013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1943
2014 "Found local result for %s (PP: %s)\n", 1944 pp = GNUNET_STRINGS_pp2s (bd->put_path,
2015 GNUNET_h2s (key), 1945 bd->put_path_length);
2016 pp); 1946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2017 GNUNET_free (pp); 1947 "Found local result for %s (PP: %s)\n",
2018 GDS_NEIGHBOURS_handle_reply (peer->id, 1948 GNUNET_h2s (&bd->key),
2019 type, 1949 pp);
2020 expiration_time, 1950 GNUNET_free (pp);
2021 key, 1951 }
2022 put_path_length, put_path, 1952 GDS_NEIGHBOURS_handle_reply (peer,
2023 get_path_length, get_path, 1953 bd,
2024 data, data_size); 1954 &bd->key,
1955 0, NULL /* get path */);
2025} 1956}
2026 1957
2027 1958
@@ -2032,17 +1963,15 @@ handle_local_result (void *cls,
2032 * @param get the message 1963 * @param get the message
2033 * @return #GNUNET_OK if the message is well-formed 1964 * @return #GNUNET_OK if the message is well-formed
2034 */ 1965 */
2035static int 1966static enum GNUNET_GenericReturnValue
2036check_dht_p2p_get (void *cls, 1967check_dht_p2p_get (void *cls,
2037 const struct PeerGetMessage *get) 1968 const struct PeerGetMessage *get)
2038{ 1969{
2039 uint32_t xquery_size; 1970 uint16_t msize = ntohs (get->header.size);
2040 uint16_t msize; 1971 uint32_t xquery_size = ntohl (get->xquery_size);
2041 1972
2042 (void) cls; 1973 (void) cls;
2043 msize = ntohs (get->header.size); 1974 if (msize < sizeof(*get) + xquery_size)
2044 xquery_size = ntohl (get->xquery_size);
2045 if (msize < sizeof(struct PeerGetMessage) + xquery_size)
2046 { 1975 {
2047 GNUNET_break_op (0); 1976 GNUNET_break_op (0);
2048 return GNUNET_SYSERR; 1977 return GNUNET_SYSERR;
@@ -2062,265 +1991,236 @@ handle_dht_p2p_get (void *cls,
2062 const struct PeerGetMessage *get) 1991 const struct PeerGetMessage *get)
2063{ 1992{
2064 struct PeerInfo *peer = cls; 1993 struct PeerInfo *peer = cls;
2065 uint32_t xquery_size; 1994 uint16_t msize = ntohs (get->header.size);
2066 size_t reply_bf_size; 1995 uint32_t xquery_size = ntohl (get->xquery_size);
2067 uint16_t msize; 1996 uint32_t hop_count = ntohl (get->hop_count);
2068 enum GNUNET_BLOCK_Type type; 1997 size_t reply_bf_size = msize - (sizeof(*get) + xquery_size);
2069 enum GNUNET_DHT_RouteOption options; 1998 enum GNUNET_BLOCK_Type type = (enum GNUNET_BLOCK_Type) ntohl (get->type);
2070 enum GNUNET_BLOCK_EvaluationResult eval; 1999 enum GNUNET_DHT_RouteOption options = (enum GNUNET_DHT_RouteOption) ntohl (get->options);
2071 struct GNUNET_BLOCK_Group *bg; 2000 enum GNUNET_BLOCK_ReplyEvaluationResult eval = GNUNET_BLOCK_REPLY_OK_MORE;
2072 struct GNUNET_CONTAINER_BloomFilter *peer_bf; 2001 const void *xquery = (const void *) &get[1];
2073 const char *xquery;
2074 int forwarded;
2075 2002
2076 /* parse and validate message */ 2003 /* parse and validate message */
2077 msize = ntohs (get->header.size);
2078 xquery_size = ntohl (get->xquery_size);
2079 reply_bf_size = msize - (sizeof(struct PeerGetMessage) + xquery_size);
2080 type = ntohl (get->type);
2081 options = ntohl (get->options);
2082 xquery = (const char *) &get[1];
2083 GNUNET_STATISTICS_update (GDS_stats, 2004 GNUNET_STATISTICS_update (GDS_stats,
2084 gettext_noop ("# P2P GET requests received"), 2005 "# P2P GET requests received",
2085 1, 2006 1,
2086 GNUNET_NO); 2007 GNUNET_NO);
2087 GNUNET_STATISTICS_update (GDS_stats, 2008 GNUNET_STATISTICS_update (GDS_stats,
2088 gettext_noop ("# P2P GET bytes received"), 2009 "# P2P GET bytes received",
2089 msize, 2010 msize,
2090 GNUNET_NO); 2011 GNUNET_NO);
2091 if (GNUNET_YES == log_route_details_stderr) 2012 if (GNUNET_YES == log_route_details_stderr)
2092 { 2013 {
2093 char *tmp; 2014 char *tmp;
2094 2015 struct GNUNET_HashCode mxor;
2016 struct GNUNET_HashCode pxor;
2017
2018 GNUNET_CRYPTO_hash_xor (&my_identity_hash,
2019 &get->key,
2020 &mxor);
2021 GNUNET_CRYPTO_hash_xor (&peer->phash,
2022 &get->key,
2023 &pxor);
2095 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); 2024 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
2096 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 2025 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
2097 "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n", 2026 "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
2098 GNUNET_h2s (&get->key), 2027 GNUNET_h2s (&get->key),
2099 GNUNET_i2s (peer->id), 2028 GNUNET_i2s (peer->id),
2100 tmp, 2029 tmp,
2101 ntohl (get->hop_count), 2030 hop_count,
2102 GNUNET_CRYPTO_hash_matching_bits (&peer->phash, 2031 GNUNET_CRYPTO_hash_count_leading_zeros (&pxor),
2103 &get->key), 2032 GNUNET_CRYPTO_hash_count_leading_zeros (&mxor),
2104 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
2105 &get->key),
2106 ntohl (get->xquery_size), 2033 ntohl (get->xquery_size),
2107 xquery); 2034 (const char *) xquery);
2108 GNUNET_free (tmp); 2035 GNUNET_free (tmp);
2109 } 2036 }
2110 eval 2037 if (GNUNET_NO ==
2111 = GNUNET_BLOCK_evaluate (GDS_block_context, 2038 GNUNET_BLOCK_check_query (GDS_block_context,
2112 type, 2039 type,
2113 NULL, 2040 &get->key,
2114 GNUNET_BLOCK_EO_NONE, 2041 xquery,
2115 &get->key, 2042 xquery_size))
2116 xquery,
2117 xquery_size,
2118 NULL,
2119 0);
2120 if (eval != GNUNET_BLOCK_EVALUATION_REQUEST_VALID)
2121 { 2043 {
2122 /* request invalid or block type not supported */ 2044 /* request invalid */
2123 GNUNET_break_op (eval == GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED); 2045 GNUNET_break_op (0);
2124 return; 2046 return;
2125 } 2047 }
2126 peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter, 2048
2127 DHT_BLOOM_SIZE,
2128 GNUNET_CONSTANTS_BLOOMFILTER_K);
2129 GNUNET_break_op (GNUNET_YES ==
2130 GNUNET_CONTAINER_bloomfilter_test (peer_bf,
2131 &peer->phash));
2132 bg = GNUNET_BLOCK_group_create (GDS_block_context,
2133 type,
2134 get->bf_mutator,
2135 &xquery[xquery_size],
2136 reply_bf_size,
2137 "filter-size",
2138 reply_bf_size,
2139 NULL);
2140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2141 "GET for %s at %s after %u hops\n",
2142 GNUNET_h2s (&get->key),
2143 GNUNET_i2s (&my_identity),
2144 (unsigned int) ntohl (get->hop_count));
2145 /* local lookup (this may update the reply_bf) */
2146 if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2147 (GDS_am_closest_peer (&get->key,
2148 peer_bf)))
2149 { 2049 {
2150 if ((0 != (options & GNUNET_DHT_RO_FIND_PEER))) 2050 struct GNUNET_BLOCK_Group *bg;
2051 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2052
2053 peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
2054 DHT_BLOOM_SIZE,
2055 GNUNET_CONSTANTS_BLOOMFILTER_K);
2056 GNUNET_break_op (GNUNET_YES ==
2057 GNUNET_CONTAINER_bloomfilter_test (peer_bf,
2058 &peer->phash));
2059 bg = GNUNET_BLOCK_group_create (GDS_block_context,
2060 type,
2061 get->bf_mutator,
2062 xquery + xquery_size,
2063 reply_bf_size,
2064 "filter-size",
2065 reply_bf_size,
2066 NULL);
2067 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2068 "GET for %s at %s after %u hops\n",
2069 GNUNET_h2s (&get->key),
2070 GNUNET_i2s (&my_identity),
2071 (unsigned int) hop_count);
2072 /* local lookup (this may update the reply_bf) */
2073 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2074 (GDS_am_closest_peer (&get->key,
2075 peer_bf)) )
2151 { 2076 {
2152 GNUNET_STATISTICS_update (GDS_stats, 2077 if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
2153 gettext_noop ( 2078 {
2154 "# P2P FIND PEER requests processed"), 2079 GNUNET_STATISTICS_update (GDS_stats,
2155 1, 2080 "# P2P FIND PEER requests processed",
2156 GNUNET_NO); 2081 1,
2157 handle_find_peer (peer->id, 2082 GNUNET_NO);
2158 &get->key, 2083 handle_find_peer (peer,
2159 bg); 2084 &get->key,
2085 bg);
2086 }
2087 else
2088 {
2089 eval = GDS_DATACACHE_handle_get (&get->key,
2090 type,
2091 xquery,
2092 xquery_size,
2093 bg,
2094 &handle_local_result,
2095 peer);
2096 }
2160 } 2097 }
2161 else 2098 else
2099 {
2100 GNUNET_STATISTICS_update (GDS_stats,
2101 "# P2P GET requests ONLY routed",
2102 1,
2103 GNUNET_NO);
2104 }
2105
2106 /* remember request for routing replies */
2107 GDS_ROUTING_add (peer->id,
2108 type,
2109 bg, /* bg now owned by routing, but valid at least until end of this function! */
2110 options,
2111 &get->key,
2112 xquery,
2113 xquery_size);
2114
2115 /* P2P forwarding */
2162 { 2116 {
2163 eval = GDS_DATACACHE_handle_get (&get->key, 2117 bool forwarded = false;
2164 type, 2118 uint32_t desired_replication_level = ntohl (get->desired_replication_level);
2165 xquery, 2119
2166 xquery_size, 2120 if (eval != GNUNET_BLOCK_REPLY_OK_LAST)
2167 bg, 2121 forwarded = (GNUNET_OK ==
2168 &handle_local_result, 2122 GDS_NEIGHBOURS_handle_get (type,
2169 peer); 2123 options,
2124 desired_replication_level,
2125 hop_count,
2126 &get->key,
2127 xquery,
2128 xquery_size,
2129 bg,
2130 peer_bf));
2131 GDS_CLIENTS_process_get (
2132 options |
2133 (forwarded
2134 ? 0
2135 : GNUNET_DHT_RO_LAST_HOP),
2136 type,
2137 hop_count,
2138 desired_replication_level,
2139 0,
2140 NULL,
2141 &get->key);
2170 } 2142 }
2143 /* clean up; note that 'bg' is owned by routing now! */
2144 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
2171 } 2145 }
2172 else
2173 {
2174 GNUNET_STATISTICS_update (GDS_stats,
2175 gettext_noop ("# P2P GET requests ONLY routed"),
2176 1,
2177 GNUNET_NO);
2178 }
2179
2180 /* remember request for routing replies */
2181 GDS_ROUTING_add (peer->id,
2182 type,
2183 bg, /* bg now owned by routing, but valid at least until end of this function! */
2184 options,
2185 &get->key,
2186 xquery,
2187 xquery_size);
2188
2189 /* P2P forwarding */
2190 forwarded = GNUNET_NO;
2191 if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
2192 forwarded = GDS_NEIGHBOURS_handle_get (type,
2193 options,
2194 ntohl (
2195 get->desired_replication_level),
2196 ntohl (get->hop_count),
2197 &get->key,
2198 xquery,
2199 xquery_size,
2200 bg,
2201 peer_bf);
2202 GDS_CLIENTS_process_get (options
2203 | ((GNUNET_OK == forwarded)
2204 ? GNUNET_DHT_RO_LAST_HOP : 0),
2205 type,
2206 ntohl (get->hop_count),
2207 ntohl (get->desired_replication_level),
2208 0,
2209 NULL,
2210 &get->key);
2211
2212 /* clean up; note that 'bg' is owned by routing now! */
2213 GNUNET_CONTAINER_bloomfilter_free (peer_bf);
2214}
2215
2216
2217/**
2218 * Check validity of p2p result message.
2219 *
2220 * @param cls closure
2221 * @param message message
2222 * @return #GNUNET_YES if the message is well-formed
2223 */
2224static int
2225check_dht_p2p_result (void *cls,
2226 const struct PeerResultMessage *prm)
2227{
2228 uint32_t get_path_length;
2229 uint32_t put_path_length;
2230 uint16_t msize;
2231
2232 (void) cls;
2233 msize = ntohs (prm->header.size);
2234 put_path_length = ntohl (prm->put_path_length);
2235 get_path_length = ntohl (prm->get_path_length);
2236 if ((msize <
2237 sizeof(struct PeerResultMessage) + (get_path_length
2238 + put_path_length)
2239 * sizeof(struct GNUNET_PeerIdentity)) ||
2240 (get_path_length >
2241 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
2242 (put_path_length >
2243 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
2244 {
2245 GNUNET_break_op (0);
2246 return GNUNET_SYSERR;
2247 }
2248 return GNUNET_OK;
2249} 2146}
2250 2147
2251 2148
2252/** 2149/**
2253 * Process a reply, after the @a get_path has been updated. 2150 * Process a reply, after the @a get_path has been updated.
2254 * 2151 *
2255 * @param expiration_time when does the reply expire 2152 * @param bd block details
2256 * @param key key matching the query 2153 * @param query_hash hash of the original query, might not match key in @a bd
2257 * @param get_path_length number of entries in @a get_path 2154 * @param get_path_length number of entries in @a get_path
2258 * @param get_path path the reply has taken 2155 * @param get_path path the reply has taken
2259 * @param put_path_length number of entries in @a put_path
2260 * @param put_path path the PUT has taken
2261 * @param type type of the block
2262 * @param data_size number of bytes in @a data
2263 * @param data payload of the reply
2264 */ 2156 */
2265static void 2157static void
2266process_reply_with_path (struct GNUNET_TIME_Absolute expiration_time, 2158process_reply_with_path (const struct GDS_DATACACHE_BlockData *bd,
2267 const struct GNUNET_HashCode *key, 2159 const struct GNUNET_HashCode *query_hash,
2268 unsigned int get_path_length, 2160 unsigned int get_path_length,
2269 const struct GNUNET_PeerIdentity *get_path, 2161 const struct GNUNET_PeerIdentity *get_path)
2270 unsigned int put_path_length,
2271 const struct GNUNET_PeerIdentity *put_path,
2272 enum GNUNET_BLOCK_Type type,
2273 size_t data_size,
2274 const void *data)
2275{ 2162{
2276 /* forward to local clients */ 2163 /* forward to local clients */
2277 GDS_CLIENTS_handle_reply (expiration_time, 2164 GDS_CLIENTS_handle_reply (bd,
2278 key, 2165 query_hash,
2279 get_path_length, 2166 get_path_length,
2280 get_path, 2167 get_path);
2281 put_path_length, 2168 GDS_CLIENTS_process_get_resp (bd,
2282 put_path,
2283 type,
2284 data_size,
2285 data);
2286 GDS_CLIENTS_process_get_resp (type,
2287 get_path, 2169 get_path,
2288 get_path_length, 2170 get_path_length);
2289 put_path,
2290 put_path_length,
2291 expiration_time,
2292 key,
2293 data,
2294 data_size);
2295 if (GNUNET_YES == cache_results) 2171 if (GNUNET_YES == cache_results)
2296 { 2172 {
2297 struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length]; 2173 struct GNUNET_PeerIdentity xput_path[GNUNET_NZL (get_path_length
2174 + bd->put_path_length)];
2175 struct GDS_DATACACHE_BlockData bdx = *bd;
2298 2176
2299 GNUNET_memcpy (xput_path, 2177 GNUNET_memcpy (xput_path,
2300 put_path, 2178 bd->put_path,
2301 put_path_length * sizeof(struct GNUNET_PeerIdentity)); 2179 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
2302 GNUNET_memcpy (&xput_path[put_path_length], 2180 GNUNET_memcpy (&xput_path[bd->put_path_length],
2303 get_path, 2181 get_path,
2304 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 2182 get_path_length * sizeof(struct GNUNET_PeerIdentity));
2305 2183 bdx.put_path = xput_path;
2306 GDS_DATACACHE_handle_put (expiration_time, 2184 bdx.put_path_length += get_path_length;
2307 key, 2185 GDS_DATACACHE_handle_put (&bdx);
2308 get_path_length + put_path_length,
2309 xput_path,
2310 type,
2311 data_size,
2312 data);
2313 } 2186 }
2314 /* forward to other peers */ 2187 /* forward to other peers */
2315 GDS_ROUTING_process (type, 2188 GDS_ROUTING_process (bd,
2316 expiration_time, 2189 query_hash,
2317 key,
2318 put_path_length,
2319 put_path,
2320 get_path_length, 2190 get_path_length,
2321 get_path, 2191 get_path);
2322 data, 2192}
2323 data_size); 2193
2194
2195/**
2196 * Check validity of p2p result message.
2197 *
2198 * @param cls closure
2199 * @param message message
2200 * @return #GNUNET_YES if the message is well-formed
2201 */
2202static enum GNUNET_GenericReturnValue
2203check_dht_p2p_result (void *cls,
2204 const struct PeerResultMessage *prm)
2205{
2206 uint32_t get_path_length = ntohl (prm->get_path_length);
2207 uint32_t put_path_length = ntohl (prm->put_path_length);
2208 uint16_t msize = ntohs (prm->header.size);
2209
2210 (void) cls;
2211 if ( (msize <
2212 sizeof(struct PeerResultMessage)
2213 + (get_path_length + put_path_length)
2214 * sizeof(struct GNUNET_PeerIdentity)) ||
2215 (get_path_length >
2216 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
2217 (put_path_length >
2218 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) )
2219 {
2220 GNUNET_break_op (0);
2221 return GNUNET_SYSERR;
2222 }
2223 return GNUNET_OK;
2324} 2224}
2325 2225
2326 2226
@@ -2335,45 +2235,66 @@ handle_dht_p2p_result (void *cls,
2335 const struct PeerResultMessage *prm) 2235 const struct PeerResultMessage *prm)
2336{ 2236{
2337 struct PeerInfo *peer = cls; 2237 struct PeerInfo *peer = cls;
2338 const struct GNUNET_PeerIdentity *put_path; 2238 uint16_t msize = ntohs (prm->header.size);
2339 const struct GNUNET_PeerIdentity *get_path; 2239 uint32_t get_path_length = ntohl (prm->get_path_length);
2340 const void *data; 2240 struct GDS_DATACACHE_BlockData bd = {
2341 uint32_t get_path_length; 2241 .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2342 uint32_t put_path_length; 2242 .put_path = (const struct GNUNET_PeerIdentity *) &prm[1],
2343 uint16_t msize; 2243 .put_path_length = ntohl (prm->put_path_length),
2344 size_t data_size; 2244 .type = ntohl (prm->type)
2345 enum GNUNET_BLOCK_Type type; 2245 };
2346 struct GNUNET_TIME_Absolute exp_time; 2246 const struct GNUNET_PeerIdentity *get_path
2247 = &bd.put_path[bd.put_path_length];
2347 2248
2348 /* parse and validate message */ 2249 /* parse and validate message */
2349 exp_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time); 2250 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
2350 if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
2351 { 2251 {
2352 GNUNET_STATISTICS_update (GDS_stats, 2252 GNUNET_STATISTICS_update (GDS_stats,
2353 gettext_noop ("# Expired results discarded"), 2253 "# Expired results discarded",
2354 1, 2254 1,
2355 GNUNET_NO); 2255 GNUNET_NO);
2356 return; 2256 return;
2357 } 2257 }
2358 msize = ntohs (prm->header.size); 2258 get_path = &bd.put_path[bd.put_path_length];
2359 put_path_length = ntohl (prm->put_path_length); 2259 bd.data = (const void *) &get_path[get_path_length];
2360 get_path_length = ntohl (prm->get_path_length); 2260 bd.data_size = msize - (sizeof(struct PeerResultMessage)
2361 put_path = (const struct GNUNET_PeerIdentity *) &prm[1]; 2261 + (get_path_length + bd.put_path_length)
2362 get_path = &put_path[put_path_length]; 2262 * sizeof(struct GNUNET_PeerIdentity));
2363 type = ntohl (prm->type);
2364 data = (const void *) &get_path[get_path_length];
2365 data_size = msize - (sizeof(struct PeerResultMessage)
2366 + (get_path_length
2367 + put_path_length) * sizeof(struct
2368 GNUNET_PeerIdentity));
2369 GNUNET_STATISTICS_update (GDS_stats, 2263 GNUNET_STATISTICS_update (GDS_stats,
2370 gettext_noop ("# P2P RESULTS received"), 2264 "# P2P RESULTS received",
2371 1, 2265 1,
2372 GNUNET_NO); 2266 GNUNET_NO);
2373 GNUNET_STATISTICS_update (GDS_stats, 2267 GNUNET_STATISTICS_update (GDS_stats,
2374 gettext_noop ("# P2P RESULT bytes received"), 2268 "# P2P RESULT bytes received",
2375 msize, 2269 msize,
2376 GNUNET_NO); 2270 GNUNET_NO);
2271 {
2272 enum GNUNET_GenericReturnValue ret;
2273 const struct GNUNET_HashCode *pquery;
2274
2275 ret = GNUNET_BLOCK_get_key (GDS_block_context,
2276 bd.type,
2277 bd.data,
2278 bd.data_size,
2279 &bd.key);
2280 if (GNUNET_NO == ret)
2281 {
2282 GNUNET_break_op (0);
2283 return;
2284 }
2285 pquery = (GNUNET_OK == ret) ? &bd.key : &prm->key;
2286 if (GNUNET_OK !=
2287 GNUNET_BLOCK_check_block (GDS_block_context,
2288 bd.type,
2289 pquery,
2290 bd.data,
2291 bd.data_size))
2292 {
2293 GNUNET_break_op (0);
2294 return;
2295 }
2296 }
2297
2377 if (GNUNET_YES == log_route_details_stderr) 2298 if (GNUNET_YES == log_route_details_stderr)
2378 { 2299 {
2379 char *tmp; 2300 char *tmp;
@@ -2382,8 +2303,8 @@ handle_dht_p2p_result (void *cls,
2382 2303
2383 gp = GNUNET_STRINGS_pp2s (get_path, 2304 gp = GNUNET_STRINGS_pp2s (get_path,
2384 get_path_length); 2305 get_path_length);
2385 pp = GNUNET_STRINGS_pp2s (put_path, 2306 pp = GNUNET_STRINGS_pp2s (bd.put_path,
2386 put_path_length); 2307 bd.put_path_length);
2387 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); 2308 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
2388 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 2309 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
2389 "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n", 2310 "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n",
@@ -2396,22 +2317,22 @@ handle_dht_p2p_result (void *cls,
2396 GNUNET_free (pp); 2317 GNUNET_free (pp);
2397 GNUNET_free (tmp); 2318 GNUNET_free (tmp);
2398 } 2319 }
2320
2399 /* if we got a HELLO, consider it for our own routing table */ 2321 /* if we got a HELLO, consider it for our own routing table */
2400 if (GNUNET_BLOCK_TYPE_DHT_HELLO == type) 2322 if (GNUNET_BLOCK_TYPE_DHT_HELLO == bd.type)
2401 { 2323 {
2402 const struct GNUNET_MessageHeader *h; 2324 const struct GNUNET_MessageHeader *h = bd.data;
2403 struct GNUNET_PeerIdentity pid; 2325 struct GNUNET_PeerIdentity pid;
2404 2326
2405 /* Should be a HELLO, validate and consider using it! */ 2327 /* Should be a HELLO, validate and consider using it! */
2406 if (data_size < sizeof(struct GNUNET_HELLO_Message)) 2328 if (bd.data_size < sizeof(struct GNUNET_HELLO_Message))
2407 { 2329 {
2408 GNUNET_break_op (0); 2330 GNUNET_break (0);
2409 return; 2331 return;
2410 } 2332 }
2411 h = data; 2333 if (bd.data_size != ntohs (h->size))
2412 if (data_size != ntohs (h->size))
2413 { 2334 {
2414 GNUNET_break_op (0); 2335 GNUNET_break (0);
2415 return; 2336 return;
2416 } 2337 }
2417 if (GNUNET_OK != 2338 if (GNUNET_OK !=
@@ -2421,10 +2342,9 @@ handle_dht_p2p_result (void *cls,
2421 GNUNET_break_op (0); 2342 GNUNET_break_op (0);
2422 return; 2343 return;
2423 } 2344 }
2424 if ((GNUNET_YES != disable_try_connect) && 2345 if ( (GNUNET_YES != disable_try_connect) &&
2425 (0 != memcmp (&my_identity, 2346 (0 != GNUNET_memcmp (&my_identity,
2426 &pid, 2347 &pid)) )
2427 sizeof(struct GNUNET_PeerIdentity))))
2428 try_connect (&pid, 2348 try_connect (&pid,
2429 h); 2349 h);
2430 } 2350 }
@@ -2432,19 +2352,12 @@ handle_dht_p2p_result (void *cls,
2432 /* First, check if 'peer' is already on the path, and if 2352 /* First, check if 'peer' is already on the path, and if
2433 so, truncate it instead of expanding. */ 2353 so, truncate it instead of expanding. */
2434 for (unsigned int i = 0; i <= get_path_length; i++) 2354 for (unsigned int i = 0; i <= get_path_length; i++)
2435 if (0 == memcmp (&get_path[i], 2355 if (0 == GNUNET_memcmp (&get_path[i],
2436 peer->id, 2356 peer->id))
2437 sizeof(struct GNUNET_PeerIdentity)))
2438 { 2357 {
2439 process_reply_with_path (exp_time, 2358 process_reply_with_path (&bd,
2440 &prm->key, 2359 &prm->key,
2441 i, 2360 i, get_path);
2442 get_path,
2443 put_path_length,
2444 put_path,
2445 type,
2446 data_size,
2447 data);
2448 return; 2361 return;
2449 } 2362 }
2450 2363
@@ -2456,26 +2369,14 @@ handle_dht_p2p_result (void *cls,
2456 get_path, 2369 get_path,
2457 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 2370 get_path_length * sizeof(struct GNUNET_PeerIdentity));
2458 xget_path[get_path_length] = *peer->id; 2371 xget_path[get_path_length] = *peer->id;
2459 2372 process_reply_with_path (&bd,
2460 process_reply_with_path (exp_time,
2461 &prm->key, 2373 &prm->key,
2462 get_path_length + 1, 2374 get_path_length + 1, xget_path);
2463 xget_path,
2464 put_path_length,
2465 put_path,
2466 type,
2467 data_size,
2468 data);
2469 } 2375 }
2470} 2376}
2471 2377
2472 2378
2473/** 2379enum GNUNET_GenericReturnValue
2474 * Initialize neighbours subsystem.
2475 *
2476 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
2477 */
2478int
2479GDS_NEIGHBOURS_init () 2380GDS_NEIGHBOURS_init ()
2480{ 2381{
2481 struct GNUNET_MQ_MessageHandler core_handlers[] = { 2382 struct GNUNET_MQ_MessageHandler core_handlers[] = {
@@ -2529,9 +2430,6 @@ GDS_NEIGHBOURS_init ()
2529} 2430}
2530 2431
2531 2432
2532/**
2533 * Shutdown neighbours subsystem.
2534 */
2535void 2433void
2536GDS_NEIGHBOURS_done () 2434GDS_NEIGHBOURS_done ()
2537{ 2435{
@@ -2554,11 +2452,6 @@ GDS_NEIGHBOURS_done ()
2554} 2452}
2555 2453
2556 2454
2557/**
2558 * Get the ID of the local node.
2559 *
2560 * @return identity of the local node
2561 */
2562struct GNUNET_PeerIdentity * 2455struct GNUNET_PeerIdentity *
2563GDS_NEIGHBOURS_get_id () 2456GDS_NEIGHBOURS_get_id ()
2564{ 2457{
diff --git a/src/dht/gnunet-service-dht_neighbours.h b/src/dht/gnunet-service-dht_neighbours.h
index 55cc5b135..28468c740 100644
--- a/src/dht/gnunet-service-dht_neighbours.h
+++ b/src/dht/gnunet-service-dht_neighbours.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -30,6 +30,7 @@
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_block_lib.h" 31#include "gnunet_block_lib.h"
32#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
33#include "gnunet-service-dht_datacache.h"
33 34
34/** 35/**
35 * Hash of the identity of this peer. 36 * Hash of the identity of this peer.
@@ -37,6 +38,18 @@
37extern struct GNUNET_HashCode my_identity_hash; 38extern struct GNUNET_HashCode my_identity_hash;
38 39
39 40
41struct PeerInfo;
42
43/**
44 * Lookup peer by peer's identity.
45 *
46 * @param target peer to look up
47 * @return NULL if we are not connected to @a target
48 */
49struct PeerInfo *
50GDS_NEIGHBOURS_lookup_peer (const struct GNUNET_PeerIdentity *target);
51
52
40/** 53/**
41 * Perform a PUT operation. Forwards the given request to other 54 * Perform a PUT operation. Forwards the given request to other
42 * peers. Does not store the data locally. Does not give the 55 * peers. Does not store the data locally. Does not give the
@@ -44,30 +57,19 @@ extern struct GNUNET_HashCode my_identity_hash;
44 * peer in the network (or if we are the closest peer in the 57 * peer in the network (or if we are the closest peer in the
45 * network). 58 * network).
46 * 59 *
47 * @param type type of the block 60 * @param bd data about the block
48 * @param options routing options 61 * @param options routing options
49 * @param desired_replication_level desired replication level 62 * @param desired_replication_level desired replication level
50 * @param expiration_time when does the content expire
51 * @param hop_count how many hops has this message traversed so far 63 * @param hop_count how many hops has this message traversed so far
52 * @param bf Bloom filter of peers this PUT has already traversed 64 * @param bf Bloom filter of peers this PUT has already traversed
53 * @param key key for the content
54 * @param put_path_length number of entries in put_path
55 * @param put_path peers this request has traversed so far (if tracked)
56 * @param data payload to store
57 * @param data_size number of bytes in data
58 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not 65 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
59 */ 66 */
60int 67enum GNUNET_GenericReturnValue
61GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, 68GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
62 enum GNUNET_DHT_RouteOption options, 69 enum GNUNET_DHT_RouteOption options,
63 uint32_t desired_replication_level, 70 uint32_t desired_replication_level,
64 struct GNUNET_TIME_Absolute expiration_time,
65 uint32_t hop_count, 71 uint32_t hop_count,
66 struct GNUNET_CONTAINER_BloomFilter *bf, 72 struct GNUNET_CONTAINER_BloomFilter *bf);
67 const struct GNUNET_HashCode *key,
68 unsigned int put_path_length,
69 struct GNUNET_PeerIdentity *put_path,
70 const void *data, size_t data_size);
71 73
72 74
73/** 75/**
@@ -87,7 +89,7 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
87 * @param peer_bf filter for peers not to select (again, updated) 89 * @param peer_bf filter for peers not to select (again, updated)
88 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not 90 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
89 */ 91 */
90int 92enum GNUNET_GenericReturnValue
91GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 93GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
92 enum GNUNET_DHT_RouteOption options, 94 enum GNUNET_DHT_RouteOption options,
93 uint32_t desired_replication_level, 95 uint32_t desired_replication_level,
@@ -104,28 +106,19 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
104 * other peers waiting for it. Does not do local caching or 106 * other peers waiting for it. Does not do local caching or
105 * forwarding to local clients. 107 * forwarding to local clients.
106 * 108 *
107 * @param target neighbour that should receive the block (if still connected) 109 * @param pi neighbour that should receive the block
108 * @param type type of the block 110 * @param type type of the block
109 * @param expiration_time when does the content expire 111 * @param bd details about the reply
110 * @param key key for the content 112 * @param query_hash query that was used for the request
111 * @param put_path_length number of entries in put_path
112 * @param put_path peers the original PUT traversed (if tracked)
113 * @param get_path_length number of entries in put_path 113 * @param get_path_length number of entries in put_path
114 * @param get_path peers this reply has traversed so far (if tracked) 114 * @param get_path peers this reply has traversed so far (if tracked)
115 * @param data payload of the reply
116 * @param data_size number of bytes in data
117 */ 115 */
118void 116void
119GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, 117GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
120 enum GNUNET_BLOCK_Type type, 118 const struct GDS_DATACACHE_BlockData *bd,
121 struct GNUNET_TIME_Absolute expiration_time, 119 const struct GNUNET_HashCode *query_hash,
122 const struct GNUNET_HashCode *key,
123 unsigned int put_path_length,
124 const struct GNUNET_PeerIdentity *put_path,
125 unsigned int get_path_length, 120 unsigned int get_path_length,
126 const struct GNUNET_PeerIdentity *get_path, 121 const struct GNUNET_PeerIdentity *get_path);
127 const void *data,
128 size_t data_size);
129 122
130 123
131/** 124/**
@@ -138,7 +131,7 @@ GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
138 * @return #GNUNET_YES if node location is closest, 131 * @return #GNUNET_YES if node location is closest,
139 * #GNUNET_NO otherwise. 132 * #GNUNET_NO otherwise.
140 */ 133 */
141int 134enum GNUNET_GenericReturnValue
142GDS_am_closest_peer (const struct GNUNET_HashCode *key, 135GDS_am_closest_peer (const struct GNUNET_HashCode *key,
143 const struct GNUNET_CONTAINER_BloomFilter *bloom); 136 const struct GNUNET_CONTAINER_BloomFilter *bloom);
144 137
@@ -148,7 +141,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
148 * 141 *
149 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 142 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
150 */ 143 */
151int 144enum GNUNET_GenericReturnValue
152GDS_NEIGHBOURS_init (void); 145GDS_NEIGHBOURS_init (void);
153 146
154 147
diff --git a/src/dht/gnunet-service-dht_nse.c b/src/dht/gnunet-service-dht_nse.c
index 7f411cf71..58f18816a 100644
--- a/src/dht/gnunet-service-dht_nse.c
+++ b/src/dht/gnunet-service-dht_nse.c
@@ -52,11 +52,13 @@ static struct GNUNET_NSE_Handle *nse;
52 * 52 *
53 */ 53 */
54static void 54static void
55update_network_size_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, 55update_network_size_estimate (void *cls,
56 double logestimate, double std_dev) 56 struct GNUNET_TIME_Absolute timestamp,
57 double logestimate,
58 double std_dev)
57{ 59{
58 GNUNET_STATISTICS_update (GDS_stats, 60 GNUNET_STATISTICS_update (GDS_stats,
59 gettext_noop ("# Network size estimates received"), 61 "# Network size estimates received",
60 1, GNUNET_NO); 62 1, GNUNET_NO);
61 /* do not allow estimates < 0.5 */ 63 /* do not allow estimates < 0.5 */
62 log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate); 64 log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate);
@@ -83,20 +85,22 @@ GDS_NSE_init ()
83{ 85{
84 unsigned long long hops; 86 unsigned long long hops;
85 87
86 if ((GNUNET_YES == 88 if ( (GNUNET_YES ==
87 GNUNET_CONFIGURATION_have_value (GDS_cfg, 89 GNUNET_CONFIGURATION_have_value (GDS_cfg,
88 "dht", 90 "dht",
89 "FORCE_NSE")) && 91 "FORCE_NSE")) &&
90 (GNUNET_OK == 92 (GNUNET_OK ==
91 GNUNET_CONFIGURATION_get_value_number (GDS_cfg, 93 GNUNET_CONFIGURATION_get_value_number (GDS_cfg,
92 "dht", 94 "dht",
93 "FORCE_NSE", 95 "FORCE_NSE",
94 &hops))) 96 &hops)) )
95 { 97 {
96 log_of_network_size_estimate = (double) hops; 98 log_of_network_size_estimate = (double) hops;
97 return; 99 return;
98 } 100 }
99 nse = GNUNET_NSE_connect (GDS_cfg, &update_network_size_estimate, NULL); 101 nse = GNUNET_NSE_connect (GDS_cfg,
102 &update_network_size_estimate,
103 NULL);
100} 104}
101 105
102 106
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c
index b05fb76d3..ec36eae75 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V. 3 Copyright (C) 2011, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -31,8 +31,9 @@
31 31
32/** 32/**
33 * Number of requests we track at most (for routing replies). 33 * Number of requests we track at most (for routing replies).
34 * TODO: make configurable!
34 */ 35 */
35#define DHT_MAX_RECENT (1024 * 16) 36#define DHT_MAX_RECENT (1024 * 128)
36 37
37 38
38/** 39/**
@@ -62,11 +63,6 @@ struct RecentRequest
62 struct GNUNET_BLOCK_Group *bg; 63 struct GNUNET_BLOCK_Group *bg;
63 64
64 /** 65 /**
65 * Type of the requested block.
66 */
67 enum GNUNET_BLOCK_Type type;
68
69 /**
70 * extended query (see gnunet_block_lib.h). Allocated at the 66 * extended query (see gnunet_block_lib.h). Allocated at the
71 * end of this struct. 67 * end of this struct.
72 */ 68 */
@@ -78,6 +74,11 @@ struct RecentRequest
78 size_t xquery_size; 74 size_t xquery_size;
79 75
80 /** 76 /**
77 * Type of the requested block.
78 */
79 enum GNUNET_BLOCK_Type type;
80
81 /**
81 * Request options. 82 * Request options.
82 */ 83 */
83 enum GNUNET_DHT_RouteOption options; 84 enum GNUNET_DHT_RouteOption options;
@@ -96,14 +97,14 @@ static struct GNUNET_CONTAINER_MultiHashMap *recent_map;
96 97
97 98
98/** 99/**
99 * Closure for the 'process' function. 100 * Closure for the process() function.
100 */ 101 */
101struct ProcessContext 102struct ProcessContext
102{ 103{
103 /** 104 /**
104 * Path of the original PUT 105 * Block data.
105 */ 106 */
106 const struct GNUNET_PeerIdentity *put_path; 107 const struct GDS_DATACACHE_BlockData *bd;
107 108
108 /** 109 /**
109 * Path of the reply. 110 * Path of the reply.
@@ -111,34 +112,10 @@ struct ProcessContext
111 const struct GNUNET_PeerIdentity *get_path; 112 const struct GNUNET_PeerIdentity *get_path;
112 113
113 /** 114 /**
114 * Payload of the reply.
115 */
116 const void *data;
117
118 /**
119 * Expiration time of the result.
120 */
121 struct GNUNET_TIME_Absolute expiration_time;
122
123 /**
124 * Number of entries in @e put_path.
125 */
126 unsigned int put_path_length;
127
128 /**
129 * Number of entries in @e get_path. 115 * Number of entries in @e get_path.
130 */ 116 */
131 unsigned int get_path_length; 117 unsigned int get_path_length;
132 118
133 /**
134 * Number of bytes in @e data.
135 */
136 size_t data_size;
137
138 /**
139 * Type of the reply.
140 */
141 enum GNUNET_BLOCK_Type type;
142}; 119};
143 120
144 121
@@ -146,132 +123,106 @@ struct ProcessContext
146 * Forward the result to the given peer if it matches the request. 123 * Forward the result to the given peer if it matches the request.
147 * 124 *
148 * @param cls the `struct ProcessContext` with the result 125 * @param cls the `struct ProcessContext` with the result
149 * @param key the query 126 * @param query_hash the hash from the original query
150 * @param value the `struct RecentRequest` with the request 127 * @param value the `struct RecentRequest` with the request
151 * @return #GNUNET_OK (continue to iterate), 128 * @return #GNUNET_OK (continue to iterate)
152 * #GNUNET_SYSERR if the result is malformed or type unsupported
153 */ 129 */
154static int 130static enum GNUNET_GenericReturnValue
155process (void *cls, 131process (void *cls,
156 const struct GNUNET_HashCode *key, 132 const struct GNUNET_HashCode *query_hash,
157 void *value) 133 void *value)
158{ 134{
159 struct ProcessContext *pc = cls; 135 struct ProcessContext *pc = cls;
160 struct RecentRequest *rr = value; 136 struct RecentRequest *rr = value;
161 enum GNUNET_BLOCK_EvaluationResult eval; 137 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
162 unsigned int gpl; 138 unsigned int get_path_length;
163 unsigned int ppl; 139 struct GDS_DATACACHE_BlockData bdx = *pc->bd;
164 struct GNUNET_HashCode hc;
165 const struct GNUNET_HashCode *eval_key;
166
167 if ((rr->type != GNUNET_BLOCK_TYPE_ANY) &&
168 (rr->type != pc->type))
169 return GNUNET_OK; /* type mismatch */
170 140
141 if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) &&
142 (rr->type != pc->bd->type) )
143 return GNUNET_OK; /* type mismatch */
171 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) 144 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
172 { 145 {
173 gpl = pc->get_path_length; 146 get_path_length = pc->get_path_length;
174 ppl = pc->put_path_length;
175 } 147 }
176 else 148 else
177 { 149 {
178 gpl = 0; 150 get_path_length = 0;
179 ppl = 0; 151 bdx.put_path_length = 0;
152 bdx.put_path = NULL;
180 } 153 }
181 if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && 154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
182 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO)) 155 (0 != GNUNET_memcmp (query_hash,
156 &bdx.key)) )
183 { 157 {
184 /* key may not match HELLO, which is OK since 158 GNUNET_STATISTICS_update (GDS_stats,
185 * the search is approximate. Still, the evaluation 159 "# Inexact matches discarded in exact search",
186 * would fail since the match is not exact. So 160 1,
187 * we fake it by changing the key to the actual PID ... */ 161 GNUNET_NO);
188 GNUNET_BLOCK_get_key (GDS_block_context, 162 return GNUNET_OK; /* exact search, but inexact match */
189 GNUNET_BLOCK_TYPE_DHT_HELLO,
190 pc->data,
191 pc->data_size,
192 &hc);
193 eval_key = &hc;
194 }
195 else
196 {
197 eval_key = key;
198 } 163 }
199 eval 164 eval = GNUNET_BLOCK_check_reply (GDS_block_context,
200 = GNUNET_BLOCK_evaluate (GDS_block_context, 165 bdx.type,
201 pc->type, 166 rr->bg,
202 rr->bg, 167 &bdx.key,
203 GNUNET_BLOCK_EO_NONE, 168 rr->xquery,
204 eval_key, 169 rr->xquery_size,
205 rr->xquery, 170 bdx.data,
206 rr->xquery_size, 171 bdx.data_size);
207 pc->data,
208 pc->data_size);
209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
210 "Result for %s of type %d was evaluated as %d\n", 173 "Result for %s of type %d was evaluated as %d\n",
211 GNUNET_h2s (key), 174 GNUNET_h2s (&bdx.key),
212 pc->type, 175 bdx.type,
213 eval); 176 eval);
214 switch (eval) 177 switch (eval)
215 { 178 {
216 case GNUNET_BLOCK_EVALUATION_OK_MORE: 179 case GNUNET_BLOCK_REPLY_OK_MORE:
217 case GNUNET_BLOCK_EVALUATION_OK_LAST: 180 case GNUNET_BLOCK_REPLY_OK_LAST:
218 GNUNET_STATISTICS_update (GDS_stats, 181 case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
219 gettext_noop 182 {
220 ("# Good REPLIES matched against routing table"), 183 struct PeerInfo *pi;
221 1, GNUNET_NO); 184
222 GDS_NEIGHBOURS_handle_reply (&rr->peer, 185 GNUNET_STATISTICS_update (GDS_stats,
223 pc->type, 186 "# Good REPLIES matched against routing table",
224 pc->expiration_time, 187 1,
225 key, 188 GNUNET_NO);
226 ppl, pc->put_path, 189 pi = GDS_NEIGHBOURS_lookup_peer (&rr->peer);
227 gpl, pc->get_path, 190 if (NULL == pi)
228 pc->data, 191 {
229 pc->data_size); 192 /* peer disconnected in the meantime, drop reply */
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
194 "No matching peer for reply for key %s\n",
195 GNUNET_h2s (query_hash));
196 return GNUNET_OK;
197 }
198 GDS_NEIGHBOURS_handle_reply (pi,
199 &bdx,
200 query_hash,
201 get_path_length, pc->get_path);
202 }
230 break; 203 break;
231 204 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
232 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
233 GNUNET_STATISTICS_update (GDS_stats,
234 gettext_noop
235 (
236 "# Duplicate REPLIES matched against routing table"),
237 1, GNUNET_NO);
238 return GNUNET_OK;
239
240 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
241 GNUNET_STATISTICS_update (GDS_stats, 205 GNUNET_STATISTICS_update (GDS_stats,
242 gettext_noop 206 "# Duplicate REPLIES matched against routing table",
243 ( 207 1,
244 "# Invalid REPLIES matched against routing table"), 208 GNUNET_NO);
245 1, GNUNET_NO);
246 return GNUNET_SYSERR;
247
248 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
249 GNUNET_STATISTICS_update (GDS_stats,
250 gettext_noop
251 (
252 "# Irrelevant REPLIES matched against routing table"),
253 1, GNUNET_NO);
254 return GNUNET_OK;
255
256 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
257 GNUNET_break (0);
258 return GNUNET_OK; 209 return GNUNET_OK;
259 210 case GNUNET_BLOCK_REPLY_INVALID:
260 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
261 GNUNET_break (0); 211 GNUNET_break (0);
212 GNUNET_STATISTICS_update (GDS_stats,
213 "# Invalid REPLIES matched against routing table",
214 1,
215 GNUNET_NO);
262 return GNUNET_OK; 216 return GNUNET_OK;
263 217 case GNUNET_BLOCK_REPLY_IRRELEVANT:
264 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
265 GNUNET_STATISTICS_update (GDS_stats, 218 GNUNET_STATISTICS_update (GDS_stats,
266 gettext_noop 219 "# Irrelevant REPLIES matched against routing table",
267 ( 220 1,
268 "# Unsupported REPLIES matched against routing table"), 221 GNUNET_NO);
269 1, GNUNET_NO); 222 return GNUNET_OK;
270 return GNUNET_SYSERR;
271
272 default: 223 default:
273 GNUNET_break (0); 224 GNUNET_break (0);
274 return GNUNET_SYSERR; 225 return GNUNET_OK;
275 } 226 }
276 return GNUNET_OK; 227 return GNUNET_OK;
277} 228}
@@ -281,52 +232,28 @@ process (void *cls,
281 * Handle a reply (route to origin). Only forwards the reply back to 232 * Handle a reply (route to origin). Only forwards the reply back to
282 * other peers waiting for it. Does not do local caching or 233 * other peers waiting for it. Does not do local caching or
283 * forwarding to local clients. Essentially calls 234 * forwarding to local clients. Essentially calls
284 * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching 235 * GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching
285 * request recently. 236 * request recently.
286 * 237 *
287 * @param type type of the block 238 * @param bd block details
288 * @param expiration_time when does the content expire 239 * @param query_hash query used in the inquiry
289 * @param key key for the content
290 * @param put_path_length number of entries in @a put_path
291 * @param put_path peers the original PUT traversed (if tracked)
292 * @param get_path_length number of entries in @a get_path 240 * @param get_path_length number of entries in @a get_path
293 * @param get_path peers this reply has traversed so far (if tracked) 241 * @param get_path peers this reply has traversed so far (if tracked)
294 * @param data payload of the reply
295 * @param data_size number of bytes in data
296 */ 242 */
297void 243void
298GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, 244GDS_ROUTING_process (const struct GDS_DATACACHE_BlockData *bd,
299 struct GNUNET_TIME_Absolute expiration_time, 245 const struct GNUNET_HashCode *query_hash,
300 const struct GNUNET_HashCode *key,
301 unsigned int put_path_length,
302 const struct GNUNET_PeerIdentity *put_path,
303 unsigned int get_path_length, 246 unsigned int get_path_length,
304 const struct GNUNET_PeerIdentity *get_path, 247 const struct GNUNET_PeerIdentity *get_path)
305 const void *data,
306 size_t data_size)
307{ 248{
308 struct ProcessContext pc; 249 struct ProcessContext pc = {
309 250 .bd = bd,
310 pc.type = type; 251 .get_path = get_path,
311 pc.expiration_time = expiration_time; 252 .get_path_length = get_path_length
312 pc.put_path_length = put_path_length; 253 };
313 pc.put_path = put_path; 254
314 pc.get_path_length = get_path_length;
315 pc.get_path = get_path;
316 pc.data = data;
317 pc.data_size = data_size;
318 if (NULL == data)
319 {
320 /* Some apps might have an 'empty' reply as a valid reply; however,
321 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL'
322 reply as request-validation (but we need response-validation).
323 So we set 'data' to a 0-byte non-NULL value just to be sure */
324 GNUNET_break (0 == data_size);
325 pc.data_size = 0;
326 pc.data = ""; /* something not null */
327 }
328 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, 255 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
329 key, 256 query_hash,
330 &process, 257 &process,
331 &pc); 258 &pc);
332} 259}
@@ -338,13 +265,13 @@ GDS_ROUTING_process (enum GNUNET_BLOCK_Type type,
338 * in the heap and hashmap. 265 * in the heap and hashmap.
339 */ 266 */
340static void 267static void
341expire_oldest_entry () 268expire_oldest_entry (void)
342{ 269{
343 struct RecentRequest *recent_req; 270 struct RecentRequest *recent_req;
344 271
345 GNUNET_STATISTICS_update (GDS_stats, 272 GNUNET_STATISTICS_update (GDS_stats,
346 gettext_noop 273 "# Old entries removed from routing table",
347 ("# Entries removed from routing table"), 1, 274 1,
348 GNUNET_NO); 275 GNUNET_NO);
349 recent_req = GNUNET_CONTAINER_heap_peek (recent_heap); 276 recent_req = GNUNET_CONTAINER_heap_peek (recent_heap);
350 GNUNET_assert (recent_req != NULL); 277 GNUNET_assert (recent_req != NULL);
@@ -362,13 +289,13 @@ expire_oldest_entry ()
362 * Try to combine multiple recent requests for the same value 289 * Try to combine multiple recent requests for the same value
363 * (if they come from the same peer). 290 * (if they come from the same peer).
364 * 291 *
365 * @param cls the new 'struct RecentRequest' (to discard upon successful combination) 292 * @param cls the new `struct RecentRequest` (to discard upon successful combination)
366 * @param key the query 293 * @param key the query
367 * @param value the existing 'struct RecentRequest' (to update upon successful combination) 294 * @param value the existing `struct RecentRequest` (to update upon successful combination)
368 * @return #GNUNET_OK (continue to iterate), 295 * @return #GNUNET_OK (continue to iterate),
369 * #GNUNET_SYSERR if the request was successfully combined 296 * #GNUNET_SYSERR if the request was successfully combined
370 */ 297 */
371static int 298static enum GNUNET_GenericReturnValue
372try_combine_recent (void *cls, 299try_combine_recent (void *cls,
373 const struct GNUNET_HashCode *key, 300 const struct GNUNET_HashCode *key,
374 void *value) 301 void *value)
@@ -376,13 +303,13 @@ try_combine_recent (void *cls,
376 struct RecentRequest *in = cls; 303 struct RecentRequest *in = cls;
377 struct RecentRequest *rr = value; 304 struct RecentRequest *rr = value;
378 305
379 if ((0 != GNUNET_memcmp (&in->peer, 306 if ( (0 != GNUNET_memcmp (&in->peer,
380 &rr->peer)) || 307 &rr->peer)) ||
381 (in->type != rr->type) || 308 (in->type != rr->type) ||
382 (in->xquery_size != rr->xquery_size) || 309 (in->xquery_size != rr->xquery_size) ||
383 (0 != memcmp (in->xquery, 310 (0 != memcmp (in->xquery,
384 rr->xquery, 311 rr->xquery,
385 in->xquery_size))) 312 in->xquery_size) ) )
386 return GNUNET_OK; 313 return GNUNET_OK;
387 GNUNET_break (GNUNET_SYSERR != 314 GNUNET_break (GNUNET_SYSERR !=
388 GNUNET_BLOCK_group_merge (in->bg, 315 GNUNET_BLOCK_group_merge (in->bg,
@@ -419,7 +346,7 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
419 while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT) 346 while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT)
420 expire_oldest_entry (); 347 expire_oldest_entry ();
421 GNUNET_STATISTICS_update (GDS_stats, 348 GNUNET_STATISTICS_update (GDS_stats,
422 gettext_noop ("# Entries added to routing table"), 349 "# Entries added to routing table",
423 1, 350 1,
424 GNUNET_NO); 351 GNUNET_NO);
425 recent_req = GNUNET_malloc (sizeof(struct RecentRequest) + xquery_size); 352 recent_req = GNUNET_malloc (sizeof(struct RecentRequest) + xquery_size);
@@ -440,19 +367,21 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
440 recent_req)) 367 recent_req))
441 { 368 {
442 GNUNET_STATISTICS_update (GDS_stats, 369 GNUNET_STATISTICS_update (GDS_stats,
443 gettext_noop 370 "# DHT requests combined",
444 ("# DHT requests combined"), 371 1,
445 1, GNUNET_NO); 372 GNUNET_NO);
446 return; 373 return;
447 } 374 }
448 recent_req->heap_node 375 recent_req->heap_node
449 = GNUNET_CONTAINER_heap_insert (recent_heap, 376 = GNUNET_CONTAINER_heap_insert (
450 recent_req, 377 recent_heap,
451 GNUNET_TIME_absolute_get ().abs_value_us); 378 recent_req,
452 GNUNET_CONTAINER_multihashmap_put (recent_map, 379 GNUNET_TIME_absolute_get ().abs_value_us);
453 key, 380 (void) GNUNET_CONTAINER_multihashmap_put (
454 recent_req, 381 recent_map,
455 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 382 key,
383 recent_req,
384 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
456} 385}
457 386
458 387
@@ -476,10 +405,12 @@ GDS_ROUTING_done ()
476{ 405{
477 while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) 406 while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0)
478 expire_oldest_entry (); 407 expire_oldest_entry ();
479 GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap)); 408 GNUNET_assert (0 ==
409 GNUNET_CONTAINER_heap_get_size (recent_heap));
480 GNUNET_CONTAINER_heap_destroy (recent_heap); 410 GNUNET_CONTAINER_heap_destroy (recent_heap);
481 recent_heap = NULL; 411 recent_heap = NULL;
482 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map)); 412 GNUNET_assert (0 ==
413 GNUNET_CONTAINER_multihashmap_size (recent_map));
483 GNUNET_CONTAINER_multihashmap_destroy (recent_map); 414 GNUNET_CONTAINER_multihashmap_destroy (recent_map);
484 recent_map = NULL; 415 recent_map = NULL;
485} 416}
diff --git a/src/dht/gnunet-service-dht_routing.h b/src/dht/gnunet-service-dht_routing.h
index 7fea01bae..1a1514cc5 100644
--- a/src/dht/gnunet-service-dht_routing.h
+++ b/src/dht/gnunet-service-dht_routing.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V. 3 Copyright (C) 2011, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -35,29 +35,19 @@
35 * Handle a reply (route to origin). Only forwards the reply back to 35 * Handle a reply (route to origin). Only forwards the reply back to
36 * other peers waiting for it. Does not do local caching or 36 * other peers waiting for it. Does not do local caching or
37 * forwarding to local clients. Essentially calls 37 * forwarding to local clients. Essentially calls
38 * #GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching 38 * GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching
39 * request recently. 39 * request recently.
40 * 40 *
41 * @param type type of the block 41 * @param bd block details
42 * @param expiration_time when does the content expire 42 * @param query_hash query used in the inquiry
43 * @param key key for the content
44 * @param put_path_length number of entries in @a put_path
45 * @param put_path peers the original PUT traversed (if tracked)
46 * @param get_path_length number of entries in @a get_path 43 * @param get_path_length number of entries in @a get_path
47 * @param get_path peers this reply has traversed so far (if tracked) 44 * @param get_path peers this reply has traversed so far (if tracked)
48 * @param data payload of the reply
49 * @param data_size number of bytes in @a data
50 */ 45 */
51void 46void
52GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, 47GDS_ROUTING_process (const struct GDS_DATACACHE_BlockData *bd,
53 struct GNUNET_TIME_Absolute expiration_time, 48 const struct GNUNET_HashCode *query_hash,
54 const struct GNUNET_HashCode *key,
55 unsigned int put_path_length,
56 const struct GNUNET_PeerIdentity *put_path,
57 unsigned int get_path_length, 49 unsigned int get_path_length,
58 const struct GNUNET_PeerIdentity *get_path, 50 const struct GNUNET_PeerIdentity *get_path);
59 const void *data,
60 size_t data_size);
61 51
62 52
63/** 53/**
diff --git a/src/dht/plugin_block_dht.c b/src/dht/plugin_block_dht.c
index a9f336240..7c6fb9ed6 100644
--- a/src/dht/plugin_block_dht.c
+++ b/src/dht/plugin_block_dht.c
@@ -159,6 +159,145 @@ block_plugin_dht_evaluate (void *cls,
159 159
160 160
161/** 161/**
162 * Function called to validate a query.
163 *
164 * @param cls closure
165 * @param ctx block context
166 * @param type block type
167 * @param query original query (hash)
168 * @param xquery extrended query data (can be NULL, depending on type)
169 * @param xquery_size number of bytes in @a xquery
170 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
171 */
172static enum GNUNET_GenericReturnValue
173block_plugin_dht_check_query (void *cls,
174 enum GNUNET_BLOCK_Type type,
175 const struct GNUNET_HashCode *query,
176 const void *xquery,
177 size_t xquery_size)
178{
179 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
180 return GNUNET_SYSERR;
181 if (0 != xquery_size)
182 {
183 GNUNET_break_op (0);
184 return GNUNET_NO;
185 }
186 return GNUNET_OK;
187}
188
189
190/**
191 * Function called to validate a block for storage.
192 *
193 * @param cls closure
194 * @param type block type
195 * @param query key for the block (hash), must match exactly
196 * @param block block data to validate
197 * @param block_size number of bytes in @a block
198 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
199 */
200static enum GNUNET_GenericReturnValue
201block_plugin_dht_check_block (void *cls,
202 enum GNUNET_BLOCK_Type type,
203 const struct GNUNET_HashCode *query,
204 const void *block,
205 size_t block_size)
206{
207 const struct GNUNET_HELLO_Message *hello;
208 struct GNUNET_PeerIdentity pid;
209 const struct GNUNET_MessageHeader *msg;
210
211 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
212 return GNUNET_SYSERR;
213 if (block_size < sizeof(struct GNUNET_MessageHeader))
214 {
215 GNUNET_break_op (0);
216 return GNUNET_NO;
217 }
218 msg = block;
219 if (block_size != ntohs (msg->size))
220 {
221 GNUNET_break_op (0);
222 return GNUNET_NO;
223 }
224 hello = block;
225 if (GNUNET_OK !=
226 GNUNET_HELLO_get_id (hello,
227 &pid))
228 {
229 GNUNET_break_op (0);
230 return GNUNET_NO;
231 }
232 return GNUNET_OK;
233}
234
235
236/**
237 * Function called to validate a reply to a request. Note that it is assumed
238 * that the reply has already been matched to the key (and signatures checked)
239 * as it would be done with the GetKeyFunction and the
240 * BlockEvaluationFunction.
241 *
242 * @param cls closure
243 * @param type block type
244 * @param group which block group to use for evaluation
245 * @param query original query (hash)
246 * @param xquery extrended query data (can be NULL, depending on type)
247 * @param xquery_size number of bytes in @a xquery
248 * @param reply_block response to validate
249 * @param reply_block_size number of bytes in @a reply_block
250 * @return characterization of result
251 */
252static enum GNUNET_BLOCK_ReplyEvaluationResult
253block_plugin_dht_check_reply (
254 void *cls,
255 enum GNUNET_BLOCK_Type type,
256 struct GNUNET_BLOCK_Group *group,
257 const struct GNUNET_HashCode *query,
258 const void *xquery,
259 size_t xquery_size,
260 const void *reply_block,
261 size_t reply_block_size)
262{
263 const struct GNUNET_HELLO_Message *hello;
264 struct GNUNET_PeerIdentity pid;
265 const struct GNUNET_MessageHeader *msg;
266 struct GNUNET_HashCode phash;
267
268 if (type != GNUNET_BLOCK_TYPE_DHT_HELLO)
269 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
270 if (reply_block_size < sizeof(struct GNUNET_MessageHeader))
271 {
272 GNUNET_break_op (0);
273 return GNUNET_BLOCK_REPLY_INVALID;
274 }
275 msg = reply_block;
276 if (reply_block_size != ntohs (msg->size))
277 {
278 GNUNET_break_op (0);
279 return GNUNET_BLOCK_REPLY_INVALID;
280 }
281 hello = reply_block;
282 if (GNUNET_OK !=
283 GNUNET_HELLO_get_id (hello,
284 &pid))
285 {
286 GNUNET_break_op (0);
287 return GNUNET_BLOCK_REPLY_INVALID;
288 }
289 GNUNET_CRYPTO_hash (&pid,
290 sizeof(pid),
291 &phash);
292 if (GNUNET_YES ==
293 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
294 &phash))
295 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
296 return GNUNET_BLOCK_REPLY_OK_MORE;
297}
298
299
300/**
162 * Function called to obtain the key for a block. 301 * Function called to obtain the key for a block.
163 * 302 *
164 * @param cls closure 303 * @param cls closure
@@ -169,7 +308,7 @@ block_plugin_dht_evaluate (void *cls,
169 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 308 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
170 * (or if extracting a key from a block of this type does not work) 309 * (or if extracting a key from a block of this type does not work)
171 */ 310 */
172static int 311static enum GNUNET_GenericReturnValue
173block_plugin_dht_get_key (void *cls, 312block_plugin_dht_get_key (void *cls,
174 enum GNUNET_BLOCK_Type type, 313 enum GNUNET_BLOCK_Type type,
175 const void *block, 314 const void *block,
@@ -229,6 +368,9 @@ libgnunet_plugin_block_dht_init (void *cls)
229 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 368 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
230 api->evaluate = &block_plugin_dht_evaluate; 369 api->evaluate = &block_plugin_dht_evaluate;
231 api->get_key = &block_plugin_dht_get_key; 370 api->get_key = &block_plugin_dht_get_key;
371 api->check_query = &block_plugin_dht_check_query;
372 api->check_block = &block_plugin_dht_check_block;
373 api->check_reply = &block_plugin_dht_check_reply;
232 api->create_group = &block_plugin_dht_create_group; 374 api->create_group = &block_plugin_dht_create_group;
233 api->types = types; 375 api->types = types;
234 return api; 376 return api;
diff --git a/src/dns/plugin_block_dns.c b/src/dns/plugin_block_dns.c
index e0beccb52..d3eb7d2b9 100644
--- a/src/dns/plugin_block_dns.c
+++ b/src/dns/plugin_block_dns.c
@@ -177,6 +177,141 @@ block_plugin_dns_evaluate (void *cls,
177 177
178 178
179/** 179/**
180 * Function called to validate a query.
181 *
182 * @param cls closure
183 * @param ctx block context
184 * @param type block type
185 * @param query original query (hash)
186 * @param xquery extrended query data (can be NULL, depending on type)
187 * @param xquery_size number of bytes in @a xquery
188 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
189 */
190static enum GNUNET_GenericReturnValue
191block_plugin_dns_check_query (void *cls,
192 enum GNUNET_BLOCK_Type type,
193 const struct GNUNET_HashCode *query,
194 const void *xquery,
195 size_t xquery_size)
196{
197 switch (type)
198 {
199 case GNUNET_BLOCK_TYPE_DNS:
200 if (0 != xquery_size)
201 return GNUNET_NO;
202 return GNUNET_OK;
203 default:
204 return GNUNET_SYSERR;
205 }
206}
207
208
209/**
210 * Function called to validate a block for storage.
211 *
212 * @param cls closure
213 * @param type block type
214 * @param query key for the block (hash), must match exactly
215 * @param block block data to validate
216 * @param block_size number of bytes in @a block
217 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
218 */
219static enum GNUNET_GenericReturnValue
220block_plugin_dns_check_block (void *cls,
221 enum GNUNET_BLOCK_Type type,
222 const struct GNUNET_HashCode *query,
223 const void *block,
224 size_t block_size)
225{
226 const struct GNUNET_DNS_Advertisement *ad;
227
228 switch (type)
229 {
230 case GNUNET_BLOCK_TYPE_DNS:
231 if (sizeof(struct GNUNET_DNS_Advertisement) != block_size)
232 {
233 GNUNET_break_op (0);
234 return GNUNET_NO;
235 }
236 ad = block;
237
238 if (ntohl (ad->purpose.size) !=
239 sizeof(struct GNUNET_DNS_Advertisement)
240 - sizeof(struct GNUNET_CRYPTO_EddsaSignature))
241 {
242 GNUNET_break_op (0);
243 return GNUNET_NO;
244 }
245 if (GNUNET_TIME_absolute_is_past (
246 GNUNET_TIME_absolute_ntoh (ad->expiration_time)))
247 {
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 "DNS advertisement has expired\n");
250 return GNUNET_NO;
251 }
252 if (GNUNET_OK !=
253 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD,
254 &ad->purpose,
255 &ad->signature,
256 &ad->peer.public_key))
257 {
258 GNUNET_break_op (0);
259 return GNUNET_NO;
260 }
261 return GNUNET_OK;
262 default:
263 return GNUNET_SYSERR;
264 }
265}
266
267
268/**
269 * Function called to validate a reply to a request. Note that it is assumed
270 * that the reply has already been matched to the key (and signatures checked)
271 * as it would be done with the GetKeyFunction and the
272 * BlockEvaluationFunction.
273 *
274 * @param cls closure
275 * @param type block type
276 * @param group which block group to use for evaluation
277 * @param query original query (hash)
278 * @param xquery extrended query data (can be NULL, depending on type)
279 * @param xquery_size number of bytes in @a xquery
280 * @param reply_block response to validate
281 * @param reply_block_size number of bytes in @a reply_block
282 * @return characterization of result
283 */
284static enum GNUNET_BLOCK_ReplyEvaluationResult
285block_plugin_dns_check_reply (
286 void *cls,
287 enum GNUNET_BLOCK_Type type,
288 struct GNUNET_BLOCK_Group *group,
289 const struct GNUNET_HashCode *query,
290 const void *xquery,
291 size_t xquery_size,
292 const void *reply_block,
293 size_t reply_block_size)
294{
295 struct GNUNET_HashCode phash;
296
297 switch (type)
298 {
299 case GNUNET_BLOCK_TYPE_DNS:
300 GNUNET_CRYPTO_hash (reply_block,
301 reply_block_size,
302 &phash);
303 if (GNUNET_YES ==
304 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
305 &phash))
306 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
307 return GNUNET_BLOCK_REPLY_OK_MORE;
308 default:
309 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
310 }
311}
312
313
314/**
180 * Function called to obtain the key for a block. 315 * Function called to obtain the key for a block.
181 * 316 *
182 * @param cls closure 317 * @param cls closure
@@ -187,7 +322,7 @@ block_plugin_dns_evaluate (void *cls,
187 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 322 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
188 * (or if extracting a key from a block of this type does not work) 323 * (or if extracting a key from a block of this type does not work)
189 */ 324 */
190static int 325static enum GNUNET_GenericReturnValue
191block_plugin_dns_get_key (void *cls, 326block_plugin_dns_get_key (void *cls,
192 enum GNUNET_BLOCK_Type type, 327 enum GNUNET_BLOCK_Type type,
193 const void *block, 328 const void *block,
@@ -214,6 +349,9 @@ libgnunet_plugin_block_dns_init (void *cls)
214 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 349 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
215 api->evaluate = &block_plugin_dns_evaluate; 350 api->evaluate = &block_plugin_dns_evaluate;
216 api->get_key = &block_plugin_dns_get_key; 351 api->get_key = &block_plugin_dns_get_key;
352 api->check_query = &block_plugin_dns_check_query;
353 api->check_block = &block_plugin_dns_check_block;
354 api->check_reply = &block_plugin_dns_check_reply;
217 api->create_group = &block_plugin_dns_create_group; 355 api->create_group = &block_plugin_dns_create_group;
218 api->types = types; 356 api->types = types;
219 return api; 357 return api;
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index e90ba4c8b..8c6c39885 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -395,7 +395,7 @@ client_request_destroy (void *cls)
395 */ 395 */
396static void 396static void
397client_response_handler (void *cls, 397client_response_handler (void *cls,
398 enum GNUNET_BLOCK_EvaluationResult eval, 398 enum GNUNET_BLOCK_ReplyEvaluationResult eval,
399 struct GSF_PendingRequest *pr, 399 struct GSF_PendingRequest *pr,
400 uint32_t reply_anonymity_level, 400 uint32_t reply_anonymity_level,
401 struct GNUNET_TIME_Absolute expiration, 401 struct GNUNET_TIME_Absolute expiration,
@@ -447,7 +447,7 @@ client_response_handler (void *cls,
447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
448 "Queued reply to query `%s' for local client\n", 448 "Queued reply to query `%s' for local client\n",
449 GNUNET_h2s (&prd->query)); 449 GNUNET_h2s (&prd->query));
450 if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval) 450 if (GNUNET_BLOCK_REPLY_OK_LAST != eval)
451 { 451 {
452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
453 "Evaluation %d - keeping query alive\n", 453 "Evaluation %d - keeping query alive\n",
@@ -668,9 +668,9 @@ consider_request_for_forwarding (void *cls,
668void 668void
669GSF_consider_forwarding (void *cls, 669GSF_consider_forwarding (void *cls,
670 struct GSF_PendingRequest *pr, 670 struct GSF_PendingRequest *pr,
671 enum GNUNET_BLOCK_EvaluationResult result) 671 enum GNUNET_BLOCK_ReplyEvaluationResult result)
672{ 672{
673 if (GNUNET_BLOCK_EVALUATION_OK_LAST == result) 673 if (GNUNET_BLOCK_REPLY_OK_LAST == result)
674 return; /* we're done... */ 674 return; /* we're done... */
675 if (GNUNET_YES != 675 if (GNUNET_YES !=
676 GSF_pending_request_test_active_ (pr)) 676 GSF_pending_request_test_active_ (pr))
@@ -737,13 +737,13 @@ check_p2p_get (void *cls,
737static void 737static void
738start_p2p_processing (void *cls, 738start_p2p_processing (void *cls,
739 struct GSF_PendingRequest *pr, 739 struct GSF_PendingRequest *pr,
740 enum GNUNET_BLOCK_EvaluationResult result) 740 enum GNUNET_BLOCK_ReplyEvaluationResult result)
741{ 741{
742 struct GSF_LocalClient *lc = cls; 742 struct GSF_LocalClient *lc = cls;
743 struct GSF_PendingRequestData *prd; 743 struct GSF_PendingRequestData *prd;
744 744
745 GNUNET_SERVICE_client_continue (lc->client); 745 GNUNET_SERVICE_client_continue (lc->client);
746 if (GNUNET_BLOCK_EVALUATION_OK_LAST == result) 746 if (GNUNET_BLOCK_REPLY_OK_LAST == result)
747 return; /* we're done, 'pr' was already destroyed... */ 747 return; /* we're done, 'pr' was already destroyed... */
748 prd = GSF_pending_request_get_data_ (pr); 748 prd = GSF_pending_request_get_data_ (pr);
749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/fs/gnunet-service-fs.h b/src/fs/gnunet-service-fs.h
index 9c87115ed..a6b73db09 100644
--- a/src/fs/gnunet-service-fs.h
+++ b/src/fs/gnunet-service-fs.h
@@ -280,7 +280,7 @@ extern unsigned int GSF_datastore_queue_size;
280void 280void
281GSF_consider_forwarding (void *cls, 281GSF_consider_forwarding (void *cls,
282 struct GSF_PendingRequest *pr, 282 struct GSF_PendingRequest *pr,
283 enum GNUNET_BLOCK_EvaluationResult result); 283 enum GNUNET_BLOCK_ReplyEvaluationResult result);
284 284
285 285
286/** 286/**
diff --git a/src/fs/gnunet-service-fs_cp.c b/src/fs/gnunet-service-fs_cp.c
index c174ad611..5476aa2be 100644
--- a/src/fs/gnunet-service-fs_cp.c
+++ b/src/fs/gnunet-service-fs_cp.c
@@ -836,7 +836,7 @@ get_randomized_delay ()
836 */ 836 */
837static void 837static void
838handle_p2p_reply (void *cls, 838handle_p2p_reply (void *cls,
839 enum GNUNET_BLOCK_EvaluationResult eval, 839 enum GNUNET_BLOCK_ReplyEvaluationResult eval,
840 struct GSF_PendingRequest *pr, 840 struct GSF_PendingRequest *pr,
841 uint32_t reply_anonymity_level, 841 uint32_t reply_anonymity_level,
842 struct GNUNET_TIME_Absolute expiration, 842 struct GNUNET_TIME_Absolute expiration,
@@ -862,11 +862,11 @@ handle_p2p_reply (void *cls,
862 return; 862 return;
863 } 863 }
864 GNUNET_break (GNUNET_BLOCK_TYPE_ANY != type); 864 GNUNET_break (GNUNET_BLOCK_TYPE_ANY != type);
865 if ((prd->type != type) && (GNUNET_BLOCK_TYPE_ANY != prd->type)) 865 if ( (prd->type != type) &&
866 (GNUNET_BLOCK_TYPE_ANY != prd->type) )
866 { 867 {
867 GNUNET_STATISTICS_update (GSF_stats, 868 GNUNET_STATISTICS_update (GSF_stats,
868 gettext_noop 869 "# replies dropped due to type mismatch",
869 ("# replies dropped due to type mismatch"),
870 1, GNUNET_NO); 870 1, GNUNET_NO);
871 return; 871 return;
872 } 872 }
@@ -874,22 +874,22 @@ handle_p2p_reply (void *cls,
874 "Transmitting result for query `%s' to peer\n", 874 "Transmitting result for query `%s' to peer\n",
875 GNUNET_h2s (&prd->query)); 875 GNUNET_h2s (&prd->query));
876 GNUNET_STATISTICS_update (GSF_stats, 876 GNUNET_STATISTICS_update (GSF_stats,
877 gettext_noop ("# replies received for other peers"), 877 "# replies received for other peers",
878 1, GNUNET_NO); 878 1,
879 GNUNET_NO);
879 msize = sizeof(struct PutMessage) + data_len; 880 msize = sizeof(struct PutMessage) + data_len;
880 if (msize >= GNUNET_MAX_MESSAGE_SIZE) 881 if (msize >= GNUNET_MAX_MESSAGE_SIZE)
881 { 882 {
882 GNUNET_break (0); 883 GNUNET_break (0);
883 return; 884 return;
884 } 885 }
885 if ((UINT32_MAX != reply_anonymity_level) && (reply_anonymity_level > 1)) 886 if ( (UINT32_MAX != reply_anonymity_level) &&
887 (reply_anonymity_level > 1) )
886 { 888 {
887 if (reply_anonymity_level - 1 > GSF_cover_content_count) 889 if (reply_anonymity_level - 1 > GSF_cover_content_count)
888 { 890 {
889 GNUNET_STATISTICS_update (GSF_stats, 891 GNUNET_STATISTICS_update (GSF_stats,
890 gettext_noop 892 "# replies dropped due to insufficient cover traffic",
891 (
892 "# replies dropped due to insufficient cover traffic"),
893 1, GNUNET_NO); 893 1, GNUNET_NO);
894 return; 894 return;
895 } 895 }
@@ -930,14 +930,12 @@ handle_p2p_reply (void *cls,
930 UINT32_MAX, 930 UINT32_MAX,
931 env); 931 env);
932 } 932 }
933 if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval) 933 if (GNUNET_BLOCK_REPLY_OK_LAST != eval)
934 return; 934 return;
935 if (NULL == peerreq->kill_task) 935 if (NULL == peerreq->kill_task)
936 { 936 {
937 GNUNET_STATISTICS_update (GSF_stats, 937 GNUNET_STATISTICS_update (GSF_stats,
938 gettext_noop 938 "# P2P searches destroyed due to ultimate reply",
939 (
940 "# P2P searches destroyed due to ultimate reply"),
941 1, 939 1,
942 GNUNET_NO); 940 GNUNET_NO);
943 peerreq->kill_task = 941 peerreq->kill_task =
diff --git a/src/fs/gnunet-service-fs_pr.c b/src/fs/gnunet-service-fs_pr.c
index a5db4b6b7..c3fe5ff58 100644
--- a/src/fs/gnunet-service-fs_pr.c
+++ b/src/fs/gnunet-service-fs_pr.c
@@ -135,7 +135,7 @@ struct GSF_PendingRequest
135 /** 135 /**
136 * Last result from the local datastore lookup evaluation. 136 * Last result from the local datastore lookup evaluation.
137 */ 137 */
138 enum GNUNET_BLOCK_EvaluationResult local_result; 138 enum GNUNET_BLOCK_ReplyEvaluationResult local_result;
139 139
140 /** 140 /**
141 * Identity of the peer that we should use for the 'sender' 141 * Identity of the peer that we should use for the 'sender'
@@ -619,7 +619,9 @@ clean_request (void *cls, const struct GNUNET_HashCode *key, void *value)
619 if (NULL != (cont = pr->llc_cont)) 619 if (NULL != (cont = pr->llc_cont))
620 { 620 {
621 pr->llc_cont = NULL; 621 pr->llc_cont = NULL;
622 cont (pr->llc_cont_cls, pr, pr->local_result); 622 cont (pr->llc_cont_cls,
623 pr,
624 pr->local_result);
623 } 625 }
624 GSF_plan_notify_request_done_ (pr); 626 GSF_plan_notify_request_done_ (pr);
625 GNUNET_free (pr->replies_seen); 627 GNUNET_free (pr->replies_seen);
@@ -689,7 +691,9 @@ GSF_pending_request_cancel_ (struct GSF_PendingRequest *pr, int full_cleanup)
689 if (NULL != (cont = pr->llc_cont)) 691 if (NULL != (cont = pr->llc_cont))
690 { 692 {
691 pr->llc_cont = NULL; 693 pr->llc_cont = NULL;
692 cont (pr->llc_cont_cls, pr, pr->local_result); 694 cont (pr->llc_cont_cls,
695 pr,
696 pr->local_result);
693 } 697 }
694 GSF_plan_notify_request_done_ (pr); 698 GSF_plan_notify_request_done_ (pr);
695 if (NULL != pr->qe) 699 if (NULL != pr->qe)
@@ -778,7 +782,7 @@ struct ProcessReplyClosure
778 /** 782 /**
779 * Evaluation result (returned). 783 * Evaluation result (returned).
780 */ 784 */
781 enum GNUNET_BLOCK_EvaluationResult eval; 785 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
782 786
783 /** 787 /**
784 * Did we find a matching request? 788 * Did we find a matching request?
@@ -814,8 +818,10 @@ update_request_performance_data (struct ProcessReplyClosure *prq,
814 * @param value value in the hash map (info about the query) 818 * @param value value in the hash map (info about the query)
815 * @return #GNUNET_YES (we should continue to iterate) 819 * @return #GNUNET_YES (we should continue to iterate)
816 */ 820 */
817static int 821static enum GNUNET_GenericReturnValue
818process_reply (void *cls, const struct GNUNET_HashCode *key, void *value) 822process_reply (void *cls,
823 const struct GNUNET_HashCode *key,
824 void *value)
819{ 825{
820 struct ProcessReplyClosure *prq = cls; 826 struct ProcessReplyClosure *prq = cls;
821 struct GSF_PendingRequest *pr = value; 827 struct GSF_PendingRequest *pr = value;
@@ -832,22 +838,20 @@ process_reply (void *cls, const struct GNUNET_HashCode *key, void *value)
832 gettext_noop ("# replies received and matched"), 838 gettext_noop ("# replies received and matched"),
833 1, 839 1,
834 GNUNET_NO); 840 GNUNET_NO);
835 prq->eval = GNUNET_BLOCK_evaluate (GSF_block_ctx, 841 prq->eval = GNUNET_BLOCK_check_reply (GSF_block_ctx,
836 prq->type, 842 prq->type,
837 pr->bg, 843 pr->bg,
838 prq->eo, 844 key,
839 key, 845 NULL, 0,
840 NULL, 846 prq->data,
841 0, 847 prq->size);
842 prq->data,
843 prq->size);
844 switch (prq->eval) 848 switch (prq->eval)
845 { 849 {
846 case GNUNET_BLOCK_EVALUATION_OK_MORE: 850 case GNUNET_BLOCK_REPLY_OK_MORE:
847 update_request_performance_data (prq, pr); 851 update_request_performance_data (prq, pr);
848 break; 852 break;
849 853
850 case GNUNET_BLOCK_EVALUATION_OK_LAST: 854 case GNUNET_BLOCK_REPLY_OK_LAST:
851 /* short cut: stop processing early, no BF-update, etc. */ 855 /* short cut: stop processing early, no BF-update, etc. */
852 update_request_performance_data (prq, pr); 856 update_request_performance_data (prq, pr);
853 GNUNET_LOAD_update (GSF_rt_entry_lifetime, 857 GNUNET_LOAD_update (GSF_rt_entry_lifetime,
@@ -859,8 +863,7 @@ process_reply (void *cls, const struct GNUNET_HashCode *key, void *value)
859 .pr_head, 863 .pr_head,
860 prq->sender, 864 prq->sender,
861 &last_transmission)) 865 &last_transmission))
862 last_transmission.abs_value_us = 866 last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
863 GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
864 /* pass on to other peers / local clients */ 867 /* pass on to other peers / local clients */
865 pr->rh (pr->rh_cls, 868 pr->rh (pr->rh_cls,
866 prq->eval, 869 prq->eval,
@@ -872,46 +875,38 @@ process_reply (void *cls, const struct GNUNET_HashCode *key, void *value)
872 prq->data, 875 prq->data,
873 prq->size); 876 prq->size);
874 return GNUNET_YES; 877 return GNUNET_YES;
875 878 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
876 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
877#if INSANE_STATISTICS 879#if INSANE_STATISTICS
878 GNUNET_STATISTICS_update (GSF_stats, 880 GNUNET_STATISTICS_update (GSF_stats,
879 gettext_noop ( 881 "# duplicate replies discarded (bloomfilter)",
880 "# duplicate replies discarded (bloomfilter)"),
881 1, 882 1,
882 GNUNET_NO); 883 GNUNET_NO);
883#endif 884#endif
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Duplicate response, discarding.\n"); 885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
886 "Duplicate response, discarding.\n");
885 return GNUNET_YES; /* duplicate */ 887 return GNUNET_YES; /* duplicate */
886 888
887 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: 889 case GNUNET_BLOCK_REPLY_IRRELEVANT:
888 GNUNET_STATISTICS_update (GSF_stats, 890 GNUNET_STATISTICS_update (GSF_stats,
889 gettext_noop ("# irrelevant replies discarded"), 891 "# irrelevant replies discarded",
890 1, 892 1,
891 GNUNET_NO); 893 GNUNET_NO);
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Irrelevant response, ignoring.\n"); 894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
893 return GNUNET_YES; 895 "Irrelevant response, ignoring.\n");
894
895 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
896 return GNUNET_YES; /* wrong namespace */
897
898 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
899 GNUNET_break (0);
900 return GNUNET_YES; 896 return GNUNET_YES;
901 897 case GNUNET_BLOCK_REPLY_INVALID:
902 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
903 GNUNET_break (0);
904 return GNUNET_YES; 898 return GNUNET_YES;
905 899 case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
906 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: 900 GNUNET_break (0); /* bad installation? */
907 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
908 _ ("Unsupported block type %u\n"),
909 prq->type);
910 return GNUNET_NO; 901 return GNUNET_NO;
911 } 902 }
912 /* update bloomfilter */ 903 /* update bloomfilter */
913 GNUNET_CRYPTO_hash (prq->data, prq->size, &chash); 904 GNUNET_CRYPTO_hash (prq->data,
914 GSF_pending_request_update_ (pr, &chash, 1); 905 prq->size,
906 &chash);
907 GSF_pending_request_update_ (pr,
908 &chash,
909 1);
915 if (NULL == prq->sender) 910 if (NULL == prq->sender)
916 { 911 {
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 912 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -936,7 +931,7 @@ process_reply (void *cls, const struct GNUNET_HashCode *key, void *value)
936 .pr_head, 931 .pr_head,
937 prq->sender, 932 prq->sender,
938 &last_transmission)) 933 &last_transmission))
939 last_transmission.abs_value_us = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; 934 last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS;
940 pr->rh (pr->rh_cls, 935 pr->rh (pr->rh_cls,
941 prq->eval, 936 prq->eval,
942 pr, 937 pr,
@@ -1363,12 +1358,12 @@ call_continuation (struct GSF_PendingRequest *pr)
1363 pr->llc_cont = NULL; 1358 pr->llc_cont = NULL;
1364 if (0 != (GSF_PRO_LOCAL_ONLY & pr->public_data.options)) 1359 if (0 != (GSF_PRO_LOCAL_ONLY & pr->public_data.options))
1365 { 1360 {
1366 if (GNUNET_BLOCK_EVALUATION_OK_LAST != pr->local_result) 1361 if (GNUNET_BLOCK_REPLY_OK_LAST != pr->local_result)
1367 { 1362 {
1368 /* Signal that we are done and that there won't be any 1363 /* Signal that we are done and that there won't be any
1369 additional results to allow client to clean up state. */ 1364 additional results to allow client to clean up state. */
1370 pr->rh (pr->rh_cls, 1365 pr->rh (pr->rh_cls,
1371 GNUNET_BLOCK_EVALUATION_OK_LAST, 1366 GNUNET_BLOCK_REPLY_OK_LAST,
1372 pr, 1367 pr,
1373 UINT32_MAX, 1368 UINT32_MAX,
1374 GNUNET_TIME_UNIT_ZERO_ABS, 1369 GNUNET_TIME_UNIT_ZERO_ABS,
@@ -1380,11 +1375,15 @@ call_continuation (struct GSF_PendingRequest *pr)
1380 /* Finally, call our continuation to signal that we are 1375 /* Finally, call our continuation to signal that we are
1381 done with local processing of this request; i.e. to 1376 done with local processing of this request; i.e. to
1382 start reading again from the client. */ 1377 start reading again from the client. */
1383 cont (pr->llc_cont_cls, NULL, GNUNET_BLOCK_EVALUATION_OK_LAST); 1378 cont (pr->llc_cont_cls,
1379 NULL,
1380 GNUNET_BLOCK_REPLY_OK_LAST);
1384 return; 1381 return;
1385 } 1382 }
1386 1383
1387 cont (pr->llc_cont_cls, pr, pr->local_result); 1384 cont (pr->llc_cont_cls,
1385 pr,
1386 pr->local_result);
1388} 1387}
1389 1388
1390 1389
@@ -1635,7 +1634,7 @@ called_from_on_demand:
1635 prq.eo = GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO; 1634 prq.eo = GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO;
1636 process_reply (&prq, key, pr); 1635 process_reply (&prq, key, pr);
1637 pr->local_result = prq.eval; 1636 pr->local_result = prq.eval;
1638 if (GNUNET_BLOCK_EVALUATION_OK_LAST == prq.eval) 1637 if (GNUNET_BLOCK_REPLY_OK_LAST == prq.eval)
1639 { 1638 {
1640 GNUNET_STATISTICS_update ( 1639 GNUNET_STATISTICS_update (
1641 GSF_stats, 1640 GSF_stats,
diff --git a/src/fs/gnunet-service-fs_pr.h b/src/fs/gnunet-service-fs_pr.h
index 58fdd334e..a10fb9b4c 100644
--- a/src/fs/gnunet-service-fs_pr.h
+++ b/src/fs/gnunet-service-fs_pr.h
@@ -184,16 +184,17 @@ struct GSF_PendingRequestData
184 * @param data_len number of bytes in @a data 184 * @param data_len number of bytes in @a data
185 */ 185 */
186typedef void 186typedef void
187(*GSF_PendingRequestReplyHandler) (void *cls, 187(*GSF_PendingRequestReplyHandler) (
188 enum GNUNET_BLOCK_EvaluationResult eval, 188 void *cls,
189 struct GSF_PendingRequest *pr, 189 enum GNUNET_BLOCK_ReplyEvaluationResult eval,
190 uint32_t reply_anonymity_level, 190 struct GSF_PendingRequest *pr,
191 struct GNUNET_TIME_Absolute expiration, 191 uint32_t reply_anonymity_level,
192 struct GNUNET_TIME_Absolute 192 struct GNUNET_TIME_Absolute expiration,
193 last_transmission, 193 struct GNUNET_TIME_Absolute
194 enum GNUNET_BLOCK_Type type, 194 last_transmission,
195 const void *data, 195 enum GNUNET_BLOCK_Type type,
196 size_t data_len); 196 const void *data,
197 size_t data_len);
197 198
198 199
199/** 200/**
@@ -374,9 +375,10 @@ GSF_cadet_lookup_ (struct GSF_PendingRequest *pr);
374 * @param result final datastore lookup result 375 * @param result final datastore lookup result
375 */ 376 */
376typedef void 377typedef void
377(*GSF_LocalLookupContinuation) (void *cls, 378(*GSF_LocalLookupContinuation) (
378 struct GSF_PendingRequest *pr, 379 void *cls,
379 enum GNUNET_BLOCK_EvaluationResult result); 380 struct GSF_PendingRequest *pr,
381 enum GNUNET_BLOCK_ReplyEvaluationResult result);
380 382
381 383
382/** 384/**
diff --git a/src/fs/plugin_block_fs.c b/src/fs/plugin_block_fs.c
index 6a9ab3f41..43380b3b6 100644
--- a/src/fs/plugin_block_fs.c
+++ b/src/fs/plugin_block_fs.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2010, 2013 GNUnet e.V. 3 Copyright (C) 2010, 2013, 2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -225,7 +225,7 @@ block_plugin_fs_evaluate (void *cls,
225 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 225 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
226 * (or if extracting a key from a block of this type does not work) 226 * (or if extracting a key from a block of this type does not work)
227 */ 227 */
228static int 228static enum GNUNET_GenericReturnValue
229block_plugin_fs_get_key (void *cls, 229block_plugin_fs_get_key (void *cls,
230 enum GNUNET_BLOCK_Type type, 230 enum GNUNET_BLOCK_Type type,
231 const void *block, 231 const void *block,
@@ -238,9 +238,10 @@ block_plugin_fs_get_key (void *cls,
238 { 238 {
239 case GNUNET_BLOCK_TYPE_FS_DBLOCK: 239 case GNUNET_BLOCK_TYPE_FS_DBLOCK:
240 case GNUNET_BLOCK_TYPE_FS_IBLOCK: 240 case GNUNET_BLOCK_TYPE_FS_IBLOCK:
241 GNUNET_CRYPTO_hash (block, block_size, key); 241 GNUNET_CRYPTO_hash (block,
242 block_size,
243 key);
242 return GNUNET_OK; 244 return GNUNET_OK;
243
244 case GNUNET_BLOCK_TYPE_FS_UBLOCK: 245 case GNUNET_BLOCK_TYPE_FS_UBLOCK:
245 if (block_size < sizeof(struct UBlock)) 246 if (block_size < sizeof(struct UBlock))
246 { 247 {
@@ -252,7 +253,6 @@ block_plugin_fs_get_key (void *cls,
252 sizeof(ub->verification_key), 253 sizeof(ub->verification_key),
253 key); 254 key);
254 return GNUNET_OK; 255 return GNUNET_OK;
255
256 default: 256 default:
257 GNUNET_break (0); 257 GNUNET_break (0);
258 return GNUNET_SYSERR; 258 return GNUNET_SYSERR;
@@ -261,12 +261,153 @@ block_plugin_fs_get_key (void *cls,
261 261
262 262
263/** 263/**
264 * Function called to validate a query.
265 *
266 * @param cls closure
267 * @param ctx block context
268 * @param type block type
269 * @param query original query (hash)
270 * @param xquery extrended query data (can be NULL, depending on type)
271 * @param xquery_size number of bytes in @a xquery
272 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
273 */
274static enum GNUNET_GenericReturnValue
275block_plugin_fs_check_query (void *cls,
276 enum GNUNET_BLOCK_Type type,
277 const struct GNUNET_HashCode *query,
278 const void *xquery,
279 size_t xquery_size)
280{
281 switch (type)
282 {
283 case GNUNET_BLOCK_TYPE_FS_DBLOCK:
284 case GNUNET_BLOCK_TYPE_FS_IBLOCK:
285 case GNUNET_BLOCK_TYPE_FS_UBLOCK:
286 if (0 != xquery_size)
287 {
288 GNUNET_break_op (0);
289 return GNUNET_NO;
290 }
291 return GNUNET_OK;
292 default:
293 return GNUNET_SYSERR;
294 }
295}
296
297
298/**
299 * Function called to validate a block for storage.
300 *
301 * @param cls closure
302 * @param type block type
303 * @param query key for the block (hash), must match exactly
304 * @param block block data to validate
305 * @param block_size number of bytes in @a block
306 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
307 */
308static enum GNUNET_GenericReturnValue
309block_plugin_fs_check_block (void *cls,
310 enum GNUNET_BLOCK_Type type,
311 const struct GNUNET_HashCode *query,
312 const void *block,
313 size_t block_size)
314{
315 switch (type)
316 {
317 case GNUNET_BLOCK_TYPE_FS_DBLOCK:
318 case GNUNET_BLOCK_TYPE_FS_IBLOCK:
319 return GNUNET_OK;
320 case GNUNET_BLOCK_TYPE_FS_UBLOCK:
321 {
322 const struct UBlock *ub;
323
324 if (block_size < sizeof(struct UBlock))
325 {
326 GNUNET_break_op (0);
327 return GNUNET_NO;
328 }
329 ub = block;
330 if (block_size !=
331 ntohl (ub->purpose.size) +
332 sizeof (struct GNUNET_CRYPTO_EcdsaSignature))
333 {
334 GNUNET_break_op (0);
335 return GNUNET_NO;
336 }
337 if (GNUNET_OK !=
338 GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK,
339 &ub->purpose,
340 &ub->signature,
341 &ub->verification_key))
342 {
343 GNUNET_break_op (0);
344 return GNUNET_NO;
345 }
346 return GNUNET_OK;
347 }
348 default:
349 return GNUNET_SYSERR;
350 }
351}
352
353
354/**
355 * Function called to validate a reply to a request. Note that it is assumed
356 * that the reply has already been matched to the key (and signatures checked)
357 * as it would be done with the GetKeyFunction and the
358 * BlockEvaluationFunction.
359 *
360 * @param cls closure
361 * @param type block type
362 * @param group which block group to use for evaluation
363 * @param query original query (hash)
364 * @param xquery extrended query data (can be NULL, depending on type)
365 * @param xquery_size number of bytes in @a xquery
366 * @param reply_block response to validate
367 * @param reply_block_size number of bytes in @a reply_block
368 * @return characterization of result
369 */
370static enum GNUNET_BLOCK_ReplyEvaluationResult
371block_plugin_fs_check_reply (void *cls,
372 enum GNUNET_BLOCK_Type type,
373 struct GNUNET_BLOCK_Group *group,
374 const struct GNUNET_HashCode *query,
375 const void *xquery,
376 size_t xquery_size,
377 const void *reply_block,
378 size_t reply_block_size)
379{
380 switch (type)
381 {
382 case GNUNET_BLOCK_TYPE_FS_DBLOCK:
383 case GNUNET_BLOCK_TYPE_FS_IBLOCK:
384 return GNUNET_BLOCK_REPLY_OK_LAST;
385 case GNUNET_BLOCK_TYPE_FS_UBLOCK:
386 {
387 struct GNUNET_HashCode chash;
388
389 GNUNET_CRYPTO_hash (reply_block,
390 reply_block_size,
391 &chash);
392 if (GNUNET_YES ==
393 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
394 &chash))
395 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
396 return GNUNET_BLOCK_REPLY_OK_MORE;
397 }
398 default:
399 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
400 }
401}
402
403
404/**
264 * Entry point for the plugin. 405 * Entry point for the plugin.
265 */ 406 */
266void * 407void *
267libgnunet_plugin_block_fs_init (void *cls) 408libgnunet_plugin_block_fs_init (void *cls)
268{ 409{
269 static enum GNUNET_BLOCK_Type types[] = { 410 static const enum GNUNET_BLOCK_Type types[] = {
270 GNUNET_BLOCK_TYPE_FS_DBLOCK, 411 GNUNET_BLOCK_TYPE_FS_DBLOCK,
271 GNUNET_BLOCK_TYPE_FS_IBLOCK, 412 GNUNET_BLOCK_TYPE_FS_IBLOCK,
272 GNUNET_BLOCK_TYPE_FS_UBLOCK, 413 GNUNET_BLOCK_TYPE_FS_UBLOCK,
@@ -278,6 +419,9 @@ libgnunet_plugin_block_fs_init (void *cls)
278 api->evaluate = &block_plugin_fs_evaluate; 419 api->evaluate = &block_plugin_fs_evaluate;
279 api->get_key = &block_plugin_fs_get_key; 420 api->get_key = &block_plugin_fs_get_key;
280 api->create_group = &block_plugin_fs_create_group; 421 api->create_group = &block_plugin_fs_create_group;
422 api->check_query = &block_plugin_fs_check_query;
423 api->check_block = &block_plugin_fs_check_block;
424 api->check_reply = &block_plugin_fs_check_reply;
281 api->types = types; 425 api->types = types;
282 return api; 426 return api;
283} 427}
diff --git a/src/fs/test_plugin_block_fs.c b/src/fs/test_plugin_block_fs.c
index 4f71c5d74..727cc37c2 100644
--- a/src/fs/test_plugin_block_fs.c
+++ b/src/fs/test_plugin_block_fs.c
@@ -34,36 +34,31 @@ test_fs (struct GNUNET_BLOCK_Context *ctx)
34 34
35 memset (block, 1, sizeof(block)); 35 memset (block, 1, sizeof(block));
36 if (GNUNET_OK != 36 if (GNUNET_OK !=
37 GNUNET_BLOCK_get_key (ctx, GNUNET_BLOCK_TYPE_FS_DBLOCK, block, 37 GNUNET_BLOCK_get_key (ctx,
38 sizeof(block), &key)) 38 GNUNET_BLOCK_TYPE_FS_DBLOCK,
39 block,
40 sizeof(block),
41 &key))
39 return 1; 42 return 1;
40 if (GNUNET_BLOCK_EVALUATION_OK_LAST != 43 if (GNUNET_OK !=
41 GNUNET_BLOCK_evaluate (ctx, 44 GNUNET_BLOCK_check_block (ctx,
42 GNUNET_BLOCK_TYPE_FS_DBLOCK, 45 GNUNET_BLOCK_TYPE_FS_DBLOCK,
43 NULL, 46 &key,
44 GNUNET_BLOCK_EO_NONE, 47 block,
45 &key, 48 sizeof(block)))
46 NULL, 0,
47 block, sizeof(block)))
48 return 2; 49 return 2;
49 if (GNUNET_BLOCK_EVALUATION_REQUEST_VALID != 50 if (GNUNET_OK !=
50 GNUNET_BLOCK_evaluate (ctx, 51 GNUNET_BLOCK_check_query (ctx,
51 GNUNET_BLOCK_TYPE_FS_DBLOCK, 52 GNUNET_BLOCK_TYPE_FS_DBLOCK,
52 NULL, 53 &key,
53 GNUNET_BLOCK_EO_NONE, 54 NULL, 0))
54 &key,
55 NULL, 0,
56 NULL, 0))
57 return 4; 55 return 4;
58 GNUNET_log_skip (1, GNUNET_NO); 56 GNUNET_log_skip (1, GNUNET_NO);
59 if (GNUNET_BLOCK_EVALUATION_REQUEST_INVALID != 57 if (GNUNET_BLOCK_EVALUATION_REQUEST_INVALID !=
60 GNUNET_BLOCK_evaluate (ctx, 58 GNUNET_BLOCK_check_query (ctx,
61 GNUNET_BLOCK_TYPE_FS_DBLOCK, 59 GNUNET_BLOCK_TYPE_FS_DBLOCK,
62 NULL, 60 &key,
63 GNUNET_BLOCK_EO_NONE, 61 "bogus", 5))
64 &key,
65 "bogus", 5,
66 NULL, 0))
67 return 8; 62 return 8;
68 GNUNET_log_skip (0, GNUNET_YES); 63 GNUNET_log_skip (0, GNUNET_YES);
69 return 0; 64 return 0;
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 1380cba10..315b4dbf3 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -22,20 +22,6 @@ else
22 LIBIDN2= 22 LIBIDN2=
23endif 23endif
24 24
25EXTRA_DIST = \
26 test_gns_defaults.conf \
27 test_gns_lookup.conf \
28 test_gns_proxy.conf \
29 test_gns_simple_lookup.conf \
30 openssl.cnf \
31 gnunet-gns-proxy-setup-ca.in \
32 zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \
33 zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \
34 zonefiles/test_zonekey \
35 $(check_SCRIPTS) \
36 $(pkgdata_DATA) \
37 test_gnunet_gns.sh.in
38
39USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la 25USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la
40 26
41if USE_COVERAGE 27if USE_COVERAGE
@@ -50,6 +36,8 @@ plugindir = $(libdir)/gnunet
50 36
51pkgcfg_DATA = \ 37pkgcfg_DATA = \
52 gns.conf 38 gns.conf
39dist_pkgcfg_DATA = \
40 tlds.conf
53 41
54lib_LTLIBRARIES = \ 42lib_LTLIBRARIES = \
55 libgnunetgns.la 43 libgnunetgns.la
@@ -294,6 +282,19 @@ endif
294check_SCRIPTS += \ 282check_SCRIPTS += \
295 test_plugin_rest_gns.sh 283 test_plugin_rest_gns.sh
296 284
285EXTRA_DIST = \
286 test_gns_defaults.conf \
287 test_gns_lookup.conf \
288 test_gns_proxy.conf \
289 test_gns_simple_lookup.conf \
290 openssl.cnf \
291 gnunet-gns-proxy-setup-ca.in \
292 zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \
293 zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \
294 zonefiles/test_zonekey \
295 $(check_SCRIPTS) \
296 $(pkgdata_DATA) \
297 test_gnunet_gns.sh.in
297 298
298if ENABLE_TEST_RUN 299if ENABLE_TEST_RUN
299if HAVE_SQLITE 300if HAVE_SQLITE
diff --git a/src/gns/gns.conf.in b/src/gns/gns.conf.in
index a458f69a2..13741bee9 100644
--- a/src/gns/gns.conf.in
+++ b/src/gns/gns.conf.in
@@ -24,9 +24,6 @@ INTERCEPT_DNS = NO
24 24
25# PREFIX = valgrind --leak-check=full --track-origins=yes 25# PREFIX = valgrind --leak-check=full --track-origins=yes
26 26
27# Zones
28.pin = 000G001MF6DVMZZ4Y8XRZQDXM1PB3D3VGEK29ZHXBA57EPSNW1QBPKT8J0
29
30[gns-proxy] 27[gns-proxy]
31BINARY = gnunet-gns-proxy 28BINARY = gnunet-gns-proxy
32START_ON_DEMAND = NO 29START_ON_DEMAND = NO
diff --git a/src/gns/gnunet-gns-proxy-setup-ca.in b/src/gns/gnunet-gns-proxy-setup-ca.in
index 9a298f24a..b3ebfd11d 100644
--- a/src/gns/gnunet-gns-proxy-setup-ca.in
+++ b/src/gns/gnunet-gns-proxy-setup-ca.in
@@ -48,33 +48,45 @@
48 48
49dir=$(dirname "$0") 49dir=$(dirname "$0")
50 50
51if test -e @PKGDATADIRECTORY@/progname.sh 51progname=${0##*/}
52then
53 . @PKGDATADIRECTORY@/progname.sh
54else
55 . $dir/../../contrib/build-common/sh/lib.sh/progname.sh
56fi
57 52
58if test -e @PKGDATADIRECTORY@/existence.sh 53existence() {
59then 54 command -v "$1" >/dev/null 2>&1
60 . @PKGDATADIRECTORY@/existence.sh 55}
61else 56
62 . $dir/../../contrib/build-common/sh/lib.sh/existence.sh 57statusmsg()
63fi 58{
59 ${runcmd} echo "${tab}$@" | tee -a "${results}"
60}
61
62infomsg()
63{
64 if [ x$verbosity = x1 ]; then
65 statusmsg "INFO:${tab}$@"
66 fi
67}
64 68
65if test -e @PKGDATADIRECTORY@/msg.sh 69warningmsg()
66then 70{
67 . @PKGDATADIRECTORY@/msg.sh 71 statusmsg "WARNING:${tab}$@"
68else 72}
69 . $dir/../../contrib/build-common/sh/lib.sh/msg.sh
70fi
71 73
72if test -e @PKGDATADIRECTORY@/version_gnunet.sh 74errormsg()
73then 75{
74 . @PKGDATADIRECTORY@/version_gnunet.sh 76 statusmsg "ERROR:${tab}$@"
75else 77}
76 . $dir/../../contrib/build-common/sh/lib.sh/version_gnunet.sh 78
77fi 79linemsg()
80{
81 statusmsg "========================================="
82}
83
84
85print_version()
86{
87 GNUNET_ARM_VERSION=`gnunet-arm -v | awk '{print $2 " " $3}'`
88 echo ${progname} $GNUNET_ARM_VERSION
89}
78 90
79# Whitespace normalization without depending on shell features: 91# Whitespace normalization without depending on shell features:
80tab=' ' 92tab=' '
diff --git a/src/gns/plugin_block_gns.c b/src/gns/plugin_block_gns.c
index 9b58c9034..407754a8c 100644
--- a/src/gns/plugin_block_gns.c
+++ b/src/gns/plugin_block_gns.c
@@ -185,7 +185,7 @@ block_plugin_gns_evaluate (void *cls,
185 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 185 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
186 * (or if extracting a key from a block of this type does not work) 186 * (or if extracting a key from a block of this type does not work)
187 */ 187 */
188static int 188static enum GNUNET_GenericReturnValue
189block_plugin_gns_get_key (void *cls, 189block_plugin_gns_get_key (void *cls,
190 enum GNUNET_BLOCK_Type type, 190 enum GNUNET_BLOCK_Type type,
191 const void *reply_block, 191 const void *reply_block,
@@ -208,13 +208,139 @@ block_plugin_gns_get_key (void *cls,
208} 208}
209 209
210 210
211
212/**
213 * Function called to validate a query.
214 *
215 * @param cls closure
216 * @param ctx block context
217 * @param type block type
218 * @param query original query (hash)
219 * @param xquery extrended query data (can be NULL, depending on type)
220 * @param xquery_size number of bytes in @a xquery
221 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
222 */
223static enum GNUNET_GenericReturnValue
224block_plugin_gns_check_query (void *cls,
225 enum GNUNET_BLOCK_Type type,
226 const struct GNUNET_HashCode *query,
227 const void *xquery,
228 size_t xquery_size)
229{
230 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
231 return GNUNET_SYSERR;
232 if (0 != xquery_size)
233 {
234 GNUNET_break_op (0);
235 return GNUNET_NO;
236 }
237 return GNUNET_OK;
238}
239
240
241/**
242 * Function called to validate a block for storage.
243 *
244 * @param cls closure
245 * @param type block type
246 * @param query key for the block (hash), must match exactly
247 * @param block block data to validate
248 * @param block_size number of bytes in @a block
249 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
250 */
251static enum GNUNET_GenericReturnValue
252block_plugin_gns_check_block (void *cls,
253 enum GNUNET_BLOCK_Type type,
254 const struct GNUNET_HashCode *query,
255 const void *block,
256 size_t block_size)
257{
258 const struct GNUNET_GNSRECORD_Block *gblock;
259
260 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
261 return GNUNET_SYSERR;
262 if (block_size < sizeof(struct GNUNET_GNSRECORD_Block))
263 {
264 GNUNET_break_op (0);
265 return GNUNET_NO;
266 }
267 gblock = block;
268 if (GNUNET_GNSRECORD_block_get_size (gblock) > block_size)
269 {
270 GNUNET_break_op (0);
271 return GNUNET_NO;
272 }
273 if (GNUNET_OK !=
274 GNUNET_GNSRECORD_block_verify (gblock))
275 {
276 GNUNET_break_op (0);
277 return GNUNET_NO;
278 }
279 return GNUNET_OK;
280}
281
282
283/**
284 * Function called to validate a reply to a request. Note that it is assumed
285 * that the reply has already been matched to the key (and signatures checked)
286 * as it would be done with the GetKeyFunction and the
287 * BlockEvaluationFunction.
288 *
289 * @param cls closure
290 * @param type block type
291 * @param group which block group to use for evaluation
292 * @param query original query (hash)
293 * @param xquery extrended query data (can be NULL, depending on type)
294 * @param xquery_size number of bytes in @a xquery
295 * @param reply_block response to validate
296 * @param reply_block_size number of bytes in @a reply_block
297 * @return characterization of result
298 */
299static enum GNUNET_BLOCK_ReplyEvaluationResult
300block_plugin_gns_check_reply (void *cls,
301 enum GNUNET_BLOCK_Type type,
302 struct GNUNET_BLOCK_Group *group,
303 const struct GNUNET_HashCode *query,
304 const void *xquery,
305 size_t xquery_size,
306 const void *reply_block,
307 size_t reply_block_size)
308{
309 const struct GNUNET_GNSRECORD_Block *block;
310 struct GNUNET_HashCode chash;
311
312 if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
313 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
314 /* this is a reply */
315 if (reply_block_size < sizeof(struct GNUNET_GNSRECORD_Block))
316 {
317 GNUNET_break_op (0);
318 return GNUNET_BLOCK_REPLY_INVALID;
319 }
320 block = reply_block;
321 if (GNUNET_GNSRECORD_block_get_size (block) > reply_block_size)
322 {
323 GNUNET_break_op (0);
324 return GNUNET_BLOCK_REPLY_INVALID;
325 }
326 GNUNET_CRYPTO_hash (reply_block,
327 reply_block_size,
328 &chash);
329 if (GNUNET_YES ==
330 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
331 &chash))
332 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
333 return GNUNET_BLOCK_REPLY_OK_MORE;
334}
335
336
211/** 337/**
212 * Entry point for the plugin. 338 * Entry point for the plugin.
213 */ 339 */
214void * 340void *
215libgnunet_plugin_block_gns_init (void *cls) 341libgnunet_plugin_block_gns_init (void *cls)
216{ 342{
217 static enum GNUNET_BLOCK_Type types[] = { 343 static const enum GNUNET_BLOCK_Type types[] = {
218 GNUNET_BLOCK_TYPE_GNS_NAMERECORD, 344 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
219 GNUNET_BLOCK_TYPE_ANY /* end of list */ 345 GNUNET_BLOCK_TYPE_ANY /* end of list */
220 }; 346 };
@@ -224,6 +350,9 @@ libgnunet_plugin_block_gns_init (void *cls)
224 api->evaluate = &block_plugin_gns_evaluate; 350 api->evaluate = &block_plugin_gns_evaluate;
225 api->get_key = &block_plugin_gns_get_key; 351 api->get_key = &block_plugin_gns_get_key;
226 api->create_group = &block_plugin_gns_create_group; 352 api->create_group = &block_plugin_gns_create_group;
353 api->check_query = &block_plugin_gns_check_query;
354 api->check_block = &block_plugin_gns_check_block;
355 api->check_reply = &block_plugin_gns_check_reply;
227 api->types = types; 356 api->types = types;
228 return api; 357 return api;
229} 358}
diff --git a/src/gns/test_gnunet_gns.sh.in b/src/gns/test_gnunet_gns.sh.in
index 8a96ff034..d0c07b4e4 100755
--- a/src/gns/test_gnunet_gns.sh.in
+++ b/src/gns/test_gnunet_gns.sh.in
@@ -8,12 +8,9 @@
8# but this works for now. 8# but this works for now.
9dir=$(dirname "$0") 9dir=$(dirname "$0")
10 10
11if test -e @PKGDATADIRECTORY@/existence.sh 11existence() {
12then 12 command -v "$1" >/dev/null 2>&1
13 . @PKGDATADIRECTORY@/existence.sh 13}
14else
15 . $dir/../../contrib/build-common/sh/lib.sh/existence.sh
16fi
17 14
18LOCATION=`existence gnunet-config` 15LOCATION=`existence gnunet-config`
19if test -z $LOCATION; then 16if test -z $LOCATION; then
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 59ace6c41..e535c208a 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -71,9 +71,12 @@ check_PROGRAMS = \
71 test_identity \ 71 test_identity \
72 test_identity_defaults 72 test_identity_defaults
73 73
74check_SCRIPTS = \
75 test_identity_messages.sh
76
74if ENABLE_TEST_RUN 77if ENABLE_TEST_RUN
75AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 78AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
76TESTS = $(check_PROGRAMS) 79TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
77endif 80endif
78 81
79 82
diff --git a/src/identity/gnunet-identity.c b/src/identity/gnunet-identity.c
index d8dc936d3..97dc2ce7e 100644
--- a/src/identity/gnunet-identity.c
+++ b/src/identity/gnunet-identity.c
@@ -71,6 +71,16 @@ static int quiet;
71static int type_eddsa; 71static int type_eddsa;
72 72
73/** 73/**
74 * -W option
75 */
76static char *write_msg;
77
78/**
79 * -R option
80 */
81static char *read_msg;
82
83/**
74 * -C option 84 * -C option
75 */ 85 */
76static char *create_ego; 86static char *create_ego;
@@ -86,6 +96,11 @@ static char *delete_ego;
86static char *privkey_ego; 96static char *privkey_ego;
87 97
88/** 98/**
99 * -k option
100 */
101static char *pubkey_msg;
102
103/**
89 * -s option. 104 * -s option.
90 */ 105 */
91static char *set_ego; 106static char *set_ego;
@@ -164,6 +179,8 @@ test_finished (void)
164 (NULL == delete_op) && 179 (NULL == delete_op) &&
165 (NULL == set_op) && 180 (NULL == set_op) &&
166 (NULL == set_subsystem) && 181 (NULL == set_subsystem) &&
182 (NULL == write_msg) &&
183 (NULL == read_msg) &&
167 (! list) && 184 (! list) &&
168 (! monitor)) 185 (! monitor))
169 { 186 {
@@ -260,6 +277,135 @@ set_done (void *cls, const char *emsg)
260 277
261 278
262/** 279/**
280 * Encrypt a message given with -W, encrypted using public key of
281 * an identity given with -k.
282 */
283static void
284write_encrypted_message (void)
285{
286 struct GNUNET_IDENTITY_PublicKey recipient;
287 if (GNUNET_IDENTITY_public_key_from_string (pubkey_msg, &recipient) !=
288 GNUNET_SYSERR)
289 {
290 struct GNUNET_CRYPTO_EcdhePublicKey message_key;
291 size_t msg_len = strlen (write_msg);
292 ssize_t res = GNUNET_IDENTITY_encrypt (write_msg,
293 msg_len,
294 &recipient,
295 &message_key,
296 write_msg);
297 if (-1 != res)
298 {
299 char *keystr;
300 char *serialized_msg;
301 keystr = GNUNET_STRINGS_data_to_string_alloc (&message_key,
302 sizeof(struct
303 GNUNET_CRYPTO_EcdhePublicKey));
304 serialized_msg = GNUNET_STRINGS_data_to_string_alloc (write_msg,
305 msg_len);
306 fprintf (stdout,
307 "%s.%s\n",
308 keystr, serialized_msg);
309 GNUNET_free (keystr);
310 GNUNET_free (serialized_msg);
311 }
312 else
313 {
314 fprintf (stderr, "Error during encryption.\n");
315 global_ret = 1;
316 }
317 }
318 else
319 {
320 fprintf (stderr, "Invalid recipient public key.\n");
321 global_ret = 1;
322 }
323}
324
325
326/**
327 * Decrypt a message given with -R, encrypted using public key of @c ego
328 * and ephemeral key given with -k.
329 *
330 * @param ego ego whose private key is used for decryption
331 */
332static void
333read_encrypted_message (struct GNUNET_IDENTITY_Ego *ego)
334{
335 // message contains ECDHE key and ciphertext divided by ".", so split up first
336 char delim[2] = ".";
337 char *key_msg = strtok (read_msg, delim);
338 char *cipher;
339 if (NULL == key_msg)
340 {
341 fprintf (stderr, "Invalid message format.\n");
342 global_ret = 1;
343 return;
344 }
345 cipher = strtok (NULL, delim);
346 if (NULL == cipher)
347 {
348 fprintf (stderr, "Invalid message format, text missing.\n");
349 global_ret = 1;
350 return;
351 }
352
353 if (NULL != strtok (NULL, delim))
354 {
355 fprintf (stderr,
356 "Invalid message format, expecting only key and cipher components.\n");
357 global_ret = 1;
358 return;
359 }
360
361 struct GNUNET_CRYPTO_EcdhePublicKey message_key;
362 if (GNUNET_OK == GNUNET_STRINGS_string_to_data (key_msg, strlen (
363 key_msg),
364 &message_key,
365 sizeof(message_key)))
366 {
367 char *deserialized_msg;
368 size_t msg_len;
369 if (GNUNET_OK == GNUNET_STRINGS_string_to_data_alloc (cipher, strlen (
370 cipher),
371 (void **) &
372 deserialized_msg,
373 &msg_len))
374 {
375 ssize_t res = GNUNET_IDENTITY_decrypt (deserialized_msg,
376 msg_len,
377 GNUNET_IDENTITY_ego_get_private_key (
378 ego),
379 &message_key,
380 deserialized_msg);
381 if (-1 != res)
382 {
383 fprintf (stdout,
384 "%s\n",
385 deserialized_msg);
386 }
387 else
388 {
389 fprintf (stderr, "Failed to decrypt message.\n");
390 global_ret = 1;
391 }
392 GNUNET_free (deserialized_msg);
393 }
394 else
395 {
396 fprintf (stderr, "Invalid message format.\n");
397 global_ret = 1;
398 }
399 }
400 else
401 {
402 fprintf (stderr, "Invalid message ephemeral key.\n");
403 global_ret = 1;
404 }
405}
406
407
408/**
263 * If listing is enabled, prints information about the egos. 409 * If listing is enabled, prints information about the egos.
264 * 410 *
265 * This function is initially called for all egos and then again 411 * This function is initially called for all egos and then again
@@ -330,13 +476,25 @@ print_ego (void *cls,
330 GNUNET_free (set_ego); 476 GNUNET_free (set_ego);
331 set_ego = NULL; 477 set_ego = NULL;
332 } 478 }
479 if ( (NULL == ego) &&
480 (NULL != set_ego) &&
481 (NULL != read_msg) )
482 {
483 fprintf (stderr,
484 "Ego `%s' is not known, cannot decrypt message.\n",
485 set_ego);
486 GNUNET_free (read_msg);
487 read_msg = NULL;
488 GNUNET_free (set_ego);
489 set_ego = NULL;
490 }
333 if ((NULL == ego) && (! monitor)) 491 if ((NULL == ego) && (! monitor))
334 { 492 {
335 list = 0; 493 list = 0;
336 test_finished (); 494 test_finished ();
337 return; 495 return;
338 } 496 }
339 if (! (list | monitor)) 497 if (! (list | monitor) && (NULL == read_msg))
340 return; 498 return;
341 if ( (NULL == ego) || 499 if ( (NULL == ego) ||
342 (NULL == identifier) ) 500 (NULL == identifier) )
@@ -349,7 +507,14 @@ print_ego (void *cls,
349 s = GNUNET_IDENTITY_public_key_to_string (&pk); 507 s = GNUNET_IDENTITY_public_key_to_string (&pk);
350 privs = GNUNET_IDENTITY_private_key_to_string ( 508 privs = GNUNET_IDENTITY_private_key_to_string (
351 GNUNET_IDENTITY_ego_get_private_key (ego)); 509 GNUNET_IDENTITY_ego_get_private_key (ego));
352 if ((monitor) || (NULL != identifier)) 510 if ((NULL != read_msg) && (NULL != set_ego))
511 {
512 // due to the check above, set_ego and the identifier are equal
513 read_encrypted_message (ego);
514 GNUNET_free (read_msg);
515 read_msg = NULL;
516 }
517 else if ((monitor) || (NULL != identifier))
353 { 518 {
354 if (quiet) 519 if (quiet)
355 { 520 {
@@ -397,6 +562,19 @@ run (void *cls,
397 fprintf (stderr, "Option -s requires option -e to be specified as well.\n"); 562 fprintf (stderr, "Option -s requires option -e to be specified as well.\n");
398 return; 563 return;
399 } 564 }
565
566 if ((NULL != read_msg) && (NULL == set_ego))
567 {
568 fprintf (stderr,
569 "Option -R requires options -e to be specified as well.\n");
570 return;
571 }
572
573 if ((NULL != write_msg) && (NULL == pubkey_msg))
574 {
575 fprintf (stderr, "Option -W requires option -k to be specified as well.\n");
576 return;
577 }
400 sh = GNUNET_IDENTITY_connect (cfg, 578 sh = GNUNET_IDENTITY_connect (cfg,
401 (monitor | list) || 579 (monitor | list) ||
402 (NULL != set_ego) || 580 (NULL != set_ego) ||
@@ -404,6 +582,13 @@ run (void *cls,
404 ? &print_ego 582 ? &print_ego
405 : NULL, 583 : NULL,
406 NULL); 584 NULL);
585 if (NULL != write_msg)
586 {
587 write_encrypted_message ();
588 GNUNET_free (write_msg);
589 write_msg = NULL;
590 }
591 // read message is handled in ego callback (print_ego)
407 if (NULL != delete_ego) 592 if (NULL != delete_ego)
408 delete_op = 593 delete_op =
409 GNUNET_IDENTITY_delete (sh, 594 GNUNET_IDENTITY_delete (sh,
@@ -471,6 +656,18 @@ main (int argc, char *const *argv)
471 gettext_noop ( 656 gettext_noop (
472 "set the private key for the identity to PRIVATE_KEY (use together with -C)"), 657 "set the private key for the identity to PRIVATE_KEY (use together with -C)"),
473 &privkey_ego), 658 &privkey_ego),
659 GNUNET_GETOPT_option_string ('R',
660 "read",
661 "MESSAGE",
662 gettext_noop (
663 "Read and decrypt message encrypted for the given ego (use together with -e EGO)"),
664 &read_msg),
665 GNUNET_GETOPT_option_string ('W',
666 "write",
667 "MESSAGE",
668 gettext_noop (
669 "Encrypt and write message for recipient identity PULBIC_KEY, (use together with -k RECIPIENT_PUBLIC_KEY)"),
670 &write_msg),
474 GNUNET_GETOPT_option_flag ('X', 671 GNUNET_GETOPT_option_flag ('X',
475 "eddsa", 672 "eddsa",
476 gettext_noop ( 673 gettext_noop (
@@ -489,8 +686,14 @@ main (int argc, char *const *argv)
489 "ego", 686 "ego",
490 "NAME", 687 "NAME",
491 gettext_noop ( 688 gettext_noop (
492 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s) or restrict results to NAME (use together with -d)"), 689 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s), restrict results to NAME (use together with -d) or read and decrypt a message for NAME (use together with -R)"),
493 &set_ego), 690 &set_ego),
691 GNUNET_GETOPT_option_string ('k',
692 "key",
693 "PUBLIC_KEY",
694 gettext_noop (
695 "The public key of the recipient (with -W)"),
696 &pubkey_msg),
494 GNUNET_GETOPT_option_flag ('m', 697 GNUNET_GETOPT_option_flag ('m',
495 "monitor", 698 "monitor",
496 gettext_noop ("run in monitor mode egos"), 699 gettext_noop ("run in monitor mode egos"),
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
index 08a975e65..01f36b840 100644
--- a/src/identity/identity_api.c
+++ b/src/identity/identity_api.c
@@ -979,10 +979,8 @@ GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key)
979 { 979 {
980 case GNUNET_IDENTITY_TYPE_ECDSA: 980 case GNUNET_IDENTITY_TYPE_ECDSA:
981 return sizeof (key->type) + sizeof (key->ecdsa_key); 981 return sizeof (key->type) + sizeof (key->ecdsa_key);
982 break;
983 case GNUNET_IDENTITY_TYPE_EDDSA: 982 case GNUNET_IDENTITY_TYPE_EDDSA:
984 return sizeof (key->type) + sizeof (key->eddsa_key); 983 return sizeof (key->type) + sizeof (key->eddsa_key);
985 break;
986 default: 984 default:
987 GNUNET_break (0); 985 GNUNET_break (0);
988 } 986 }
@@ -992,19 +990,22 @@ GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key)
992 990
993ssize_t 991ssize_t
994GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key, 992GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key,
995 const void*buffer, 993 const void *buffer,
996 size_t len) 994 size_t len)
997{ 995{
998 if (len < sizeof (key->type)) 996 if (len < sizeof (key->type))
999 return -1; 997 return -1;
1000 GNUNET_memcpy (&(key->type), buffer, sizeof (key->type)); 998 GNUNET_memcpy (&key->type,
1001 const ssize_t length = GNUNET_IDENTITY_key_get_length (key); 999 buffer,
1000 sizeof (key->type));
1001 ssize_t length = GNUNET_IDENTITY_key_get_length (key);
1002 if (len < length) 1002 if (len < length)
1003 return -1; 1003 return -1;
1004 if (length < 0) 1004 if (length < 0)
1005 return -2; 1005 return -2;
1006 GNUNET_memcpy (&(key->ecdsa_key), buffer + sizeof (key->type), length 1006 GNUNET_memcpy (&key->ecdsa_key,
1007 - sizeof (key->type)); 1007 buffer + sizeof (key->type),
1008 length - sizeof (key->type));
1008 return length; 1009 return length;
1009} 1010}
1010 1011
diff --git a/src/identity/test_identity.conf b/src/identity/test_identity.conf
index 9c433da77..14b915732 100644
--- a/src/identity/test_identity.conf
+++ b/src/identity/test_identity.conf
@@ -1,3 +1,6 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-identity-service/
3
1[arm] 4[arm]
2PORT = 12000 5PORT = 12000
3UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock 6UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
diff --git a/src/identity/test_identity_messages.sh b/src/identity/test_identity_messages.sh
new file mode 100755
index 000000000..250c6a6f1
--- /dev/null
+++ b/src/identity/test_identity_messages.sh
@@ -0,0 +1,34 @@
1#!/bin/bash
2trap "gnunet-arm -e -c test_identity.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_identity.conf -s PATHS -o GNUNET_HOME -f`
17
18which timeout >/dev/null 2>&1 && DO_TIMEOUT="timeout 30"
19
20TEST_MSG="This is a test message. 123"
21gnunet-arm -s -c test_identity.conf
22gnunet-identity -C recipientego -c test_identity.conf
23RECIPIENT_KEY=$(gnunet-identity -d -e recipientego -q -c test_identity.conf)
24MSG_ENC=$(gnunet-identity -W "$TEST_MSG" -k $RECIPIENT_KEY -c test_identity.conf)
25MSG_DEC=$(gnunet-identity -R "$MSG_ENC" -e recipientego -c test_identity.conf)
26
27if test "$TEST_MSG" != "$MSG_DEC"
28then
29 echo "Failed - $TEST_MSG != $MSG_DEC"
30 exit 1
31fi
32
33gnunet-identity -D recipientego -c test_identity.conf
34gnunet-arm -e -c test_identity.conf
diff --git a/src/include/.gitignore b/src/include/.gitignore
new file mode 100644
index 000000000..6c12255e5
--- /dev/null
+++ b/src/include/.gitignore
@@ -0,0 +1,2 @@
1gnu_name_system_record_types.h
2gnunet_signatures.h
diff --git a/src/include/gnu_name_system_record_types.h b/src/include/gnu_name_system_record_types.h
deleted file mode 100644
index 22b2c472e..000000000
--- a/src/include/gnu_name_system_record_types.h
+++ /dev/null
@@ -1,148 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012-2021 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#ifndef GNU_NAME_SYSTEM_RECORD_TYPES_H
21#define GNU_NAME_SYSTEM_RECORD_TYPES_H
22
23/**
24 * WARNING:
25 * This header is generated!
26 * In order to add GNS record types, you must register
27 * them in GANA, and then use the header generation script
28 * to create an update of this file. You may then replace this
29 * file with the update.
30 */
31
32#ifdef __cplusplus
33extern "C" {
34#if 0 /* keep Emacsens' auto-indent happy */
35}
36#endif
37#endif
38
39
40/**
41 * GNS zone transfer
42 */
43#define GNUNET_GNSRECORD_TYPE_PKEY 65536
44
45/**
46 * GNS nick names
47 */
48#define GNUNET_GNSRECORD_TYPE_NICK 65537
49
50/**
51 * legacy hostnames
52 */
53#define GNUNET_GNSRECORD_TYPE_LEHO 65538
54
55/**
56 * VPN resolution
57 */
58#define GNUNET_GNSRECORD_TYPE_VPN 65539
59
60/**
61 * Delegation to DNS
62 */
63#define GNUNET_GNSRECORD_TYPE_GNS2DNS 65540
64
65/**
66 * Boxed records (see TLSA/SRV handling in GNS)
67 */
68#define GNUNET_GNSRECORD_TYPE_BOX 65541
69
70/**
71 * social place for SecuShare
72 */
73#define GNUNET_GNSRECORD_TYPE_PLACE 65542
74
75/**
76 * Endpoint for conversation
77 */
78#define GNUNET_GNSRECORD_TYPE_PHONE 65543
79
80/**
81 * identity attribute
82 */
83#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE 65544
84
85/**
86 * local ticket reference
87 */
88#define GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET 65545
89
90/**
91 * For ABD policies
92 */
93#define GNUNET_GNSRECORD_TYPE_DELEGATE 65548
94
95/**
96 * For ABD reverse lookups
97 */
98#define GNUNET_GNSRECORD_TYPE_ATTRIBUTE 65549
99
100/**
101 * for reclaim records
102 */
103#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF 65550
104
105/**
106 * For reclaim OIDC client names.
107 */
108#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT 65552
109
110/**
111 * Used reclaimID OIDC client redirect URIs.
112 */
113#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT 65553
114
115/**
116 * Record type for an attribute attestation (e.g. JWT).
117 */
118#define GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL 65554
119
120/**
121 * Record type for a presentation of a credential.
122 */
123#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
124
125/**
126 * Record type for EDKEY zone delegations.
127 */
128#define GNUNET_GNSRECORD_TYPE_EDKEY 65556
129
130/**
131 * Encoding for Robust Immutable Storage (ERIS) binary read capability
132 */
133#define GNUNET_GNSRECORD_TYPE_ERIS_READ_CAPABILITY 65557
134
135/**
136 * Record type to share an entry of a messenger room
137 */
138#define GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY 65558
139
140
141#if 0 /* keep Emacsens' auto-indent happy */
142{
143#endif
144#ifdef __cplusplus
145}
146#endif
147
148#endif
diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h
index 73b51252e..5640209a6 100644
--- a/src/include/gnunet_block_lib.h
+++ b/src/include/gnunet_block_lib.h
@@ -43,6 +43,8 @@ extern "C"
43 43
44/** 44/**
45 * Blocks in the datastore and the datacache must have a unique type. 45 * Blocks in the datastore and the datacache must have a unique type.
46 *
47 * TODO: move to GANA!
46 */ 48 */
47enum GNUNET_BLOCK_Type 49enum GNUNET_BLOCK_Type
48{ 50{
@@ -155,6 +157,7 @@ enum GNUNET_BLOCK_Type
155 157
156/** 158/**
157 * Flags that can be set to control the evaluation. 159 * Flags that can be set to control the evaluation.
160 * @deprecated
158 */ 161 */
159enum GNUNET_BLOCK_EvaluationOptions 162enum GNUNET_BLOCK_EvaluationOptions
160{ 163{
@@ -173,6 +176,7 @@ enum GNUNET_BLOCK_EvaluationOptions
173 176
174/** 177/**
175 * Possible ways for how a block may relate to a query. 178 * Possible ways for how a block may relate to a query.
179 * @deprecated
176 */ 180 */
177enum GNUNET_BLOCK_EvaluationResult 181enum GNUNET_BLOCK_EvaluationResult
178{ 182{
@@ -221,6 +225,44 @@ enum GNUNET_BLOCK_EvaluationResult
221 225
222 226
223/** 227/**
228 * Possible ways for how a block may relate to a query.
229 */
230enum GNUNET_BLOCK_ReplyEvaluationResult
231{
232 /**
233 * Valid result, but suppressed because it is a duplicate.
234 */
235 GNUNET_BLOCK_REPLY_OK_DUPLICATE = 0,
236
237 /**
238 * Valid result, and there may be more.
239 */
240 GNUNET_BLOCK_REPLY_OK_MORE = 1,
241
242 /**
243 * Last possible valid result.
244 */
245 GNUNET_BLOCK_REPLY_OK_LAST = 2,
246
247 /**
248 * Specified block type not supported by any plugin.
249 */
250 GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED = -1,
251
252 /**
253 * Block does not match query (invalid result)
254 */
255 GNUNET_BLOCK_REPLY_INVALID = -2,
256
257 /**
258 * Block does not match xquery (valid result, not relevant for the request)
259 */
260 GNUNET_BLOCK_REPLY_IRRELEVANT = -3,
261
262};
263
264
265/**
224 * Handle to an initialized block library. 266 * Handle to an initialized block library.
225 */ 267 */
226struct GNUNET_BLOCK_Context; 268struct GNUNET_BLOCK_Context;
@@ -297,7 +339,7 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
297 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not 339 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
298 * supported, #GNUNET_SYSERR on error 340 * supported, #GNUNET_SYSERR on error
299 */ 341 */
300int 342enum GNUNET_GenericReturnValue
301GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg, 343GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
302 uint32_t *nonce, 344 uint32_t *nonce,
303 void **raw_data, 345 void **raw_data,
@@ -330,6 +372,7 @@ GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg);
330 * @param reply_block response to validate 372 * @param reply_block response to validate
331 * @param reply_block_size number of bytes in @a reply_block 373 * @param reply_block_size number of bytes in @a reply_block
332 * @return characterization of result 374 * @return characterization of result
375 * @deprecated
333 */ 376 */
334enum GNUNET_BLOCK_EvaluationResult 377enum GNUNET_BLOCK_EvaluationResult
335GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx, 378GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
@@ -344,6 +387,70 @@ GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
344 387
345 388
346/** 389/**
390 * Function called to validate a reply.
391 * Also checks the query key against the block contents
392 * as it would be done with the #GNUNET_BLOCK_get_key() function.
393 *
394 * @param ctx block contxt
395 * @param type block type
396 * @param group block group to use for evaluation
397 * @param query original query (hash)
398 * @param xquery extrended query data (can be NULL, depending on type)
399 * @param xquery_size number of bytes in @a xquery
400 * @param reply_block response to validate
401 * @param reply_block_size number of bytes in @a reply_block
402 * @return characterization of result
403 */
404enum GNUNET_BLOCK_ReplyEvaluationResult
405GNUNET_BLOCK_check_reply (struct GNUNET_BLOCK_Context *ctx,
406 enum GNUNET_BLOCK_Type type,
407 struct GNUNET_BLOCK_Group *group,
408 const struct GNUNET_HashCode *query,
409 const void *xquery,
410 size_t xquery_size,
411 const void *reply_block,
412 size_t reply_block_size);
413
414
415/**
416 * Function called to validate a request.
417 *
418 * @param ctx block contxt
419 * @param type block type
420 * @param query original query (hash)
421 * @param xquery extrended query data (can be NULL, depending on type)
422 * @param xquery_size number of bytes in @a xquery
423 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not,
424 * #GNUNET_SYSERR if @a type is not supported
425 */
426enum GNUNET_GenericReturnValue
427GNUNET_BLOCK_check_query (struct GNUNET_BLOCK_Context *ctx,
428 enum GNUNET_BLOCK_Type type,
429 const struct GNUNET_HashCode *query,
430 const void *xquery,
431 size_t xquery_size);
432
433
434/**
435 * Function called to validate a block.
436 *
437 * @param ctx block contxt
438 * @param type block type
439 * @param query query key (hash)
440 * @param block payload to put
441 * @param block_size number of bytes in @a block
442 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not,
443 * #GNUNET_SYSERR if @a type is not supported
444 */
445enum GNUNET_GenericReturnValue
446GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
447 enum GNUNET_BLOCK_Type type,
448 const struct GNUNET_HashCode *query,
449 const void *block,
450 size_t block_size);
451
452
453/**
347 * Function called to obtain the key for a block. 454 * Function called to obtain the key for a block.
348 * 455 *
349 * @param ctx block context 456 * @param ctx block context
@@ -356,7 +463,7 @@ GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
356 * #GNUNET_SYSERR if type not supported 463 * #GNUNET_SYSERR if type not supported
357 * (or if extracting a key from a block of this type does not work) 464 * (or if extracting a key from a block of this type does not work)
358 */ 465 */
359int 466enum GNUNET_GenericReturnValue
360GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx, 467GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
361 enum GNUNET_BLOCK_Type type, 468 enum GNUNET_BLOCK_Type type,
362 const void *block, 469 const void *block,
@@ -375,7 +482,7 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
375 * @param seen_results_count number of entries in @a seen_results 482 * @param seen_results_count number of entries in @a seen_results
376 * @return #GNUNET_SYSERR if not supported, #GNUNET_OK on success 483 * @return #GNUNET_SYSERR if not supported, #GNUNET_OK on success
377 */ 484 */
378int 485enum GNUNET_GenericReturnValue
379GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg, 486GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg,
380 const struct GNUNET_HashCode *seen_results, 487 const struct GNUNET_HashCode *seen_results,
381 unsigned int seen_results_count); 488 unsigned int seen_results_count);
@@ -393,7 +500,7 @@ GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg,
393 * #GNUNET_NO if merge failed due to different nonce 500 * #GNUNET_NO if merge failed due to different nonce
394 * #GNUNET_SYSERR if merging is not supported 501 * #GNUNET_SYSERR if merging is not supported
395 */ 502 */
396int 503enum GNUNET_GenericReturnValue
397GNUNET_BLOCK_group_merge (struct GNUNET_BLOCK_Group *bg1, 504GNUNET_BLOCK_group_merge (struct GNUNET_BLOCK_Group *bg1,
398 struct GNUNET_BLOCK_Group *bg2); 505 struct GNUNET_BLOCK_Group *bg2);
399 506
diff --git a/src/include/gnunet_block_plugin.h b/src/include/gnunet_block_plugin.h
index ee237ac03..2c9a3839d 100644
--- a/src/include/gnunet_block_plugin.h
+++ b/src/include/gnunet_block_plugin.h
@@ -48,9 +48,9 @@
48 * @param seen_results_count number of entries in @a seen_results 48 * @param seen_results_count number of entries in @a seen_results
49 */ 49 */
50typedef void 50typedef void
51(*GNUNET_BLOCK_GroupMarkSeenFunction)(struct GNUNET_BLOCK_Group *bg, 51(*GNUNET_BLOCK_GroupMarkSeenFunction)(
52 const struct 52 struct GNUNET_BLOCK_Group *bg,
53 GNUNET_HashCode *seen_results, 53 const struct GNUNET_HashCode *seen_results,
54 unsigned int seen_results_count); 54 unsigned int seen_results_count);
55 55
56 56
@@ -63,7 +63,7 @@ typedef void
63 * @return #GNUNET_OK on success, #GNUNET_NO if the nonces were different and thus 63 * @return #GNUNET_OK on success, #GNUNET_NO if the nonces were different and thus
64 * we failed. 64 * we failed.
65 */ 65 */
66typedef int 66typedef enum GNUNET_GenericReturnValue
67(*GNUNET_BLOCK_GroupMergeFunction)(struct GNUNET_BLOCK_Group *bg1, 67(*GNUNET_BLOCK_GroupMergeFunction)(struct GNUNET_BLOCK_Group *bg1,
68 const struct GNUNET_BLOCK_Group *bg2); 68 const struct GNUNET_BLOCK_Group *bg2);
69 69
@@ -78,7 +78,7 @@ typedef int
78 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not 78 * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
79 * supported, #GNUNET_SYSERR on error 79 * supported, #GNUNET_SYSERR on error
80 */ 80 */
81typedef int 81typedef enum GNUNET_GenericReturnValue
82(*GNUNET_BLOCK_GroupSerializeFunction)(struct GNUNET_BLOCK_Group *bg, 82(*GNUNET_BLOCK_GroupSerializeFunction)(struct GNUNET_BLOCK_Group *bg,
83 uint32_t *nonce, 83 uint32_t *nonce,
84 void **raw_data, 84 void **raw_data,
@@ -180,6 +180,7 @@ typedef struct GNUNET_BLOCK_Group *
180 * @param reply_block response to validate 180 * @param reply_block response to validate
181 * @param reply_block_size number of bytes in @a reply_block 181 * @param reply_block_size number of bytes in @a reply_block
182 * @return characterization of result 182 * @return characterization of result
183 * @deprecated
183 */ 184 */
184typedef enum GNUNET_BLOCK_EvaluationResult 185typedef enum GNUNET_BLOCK_EvaluationResult
185(*GNUNET_BLOCK_EvaluationFunction)(void *cls, 186(*GNUNET_BLOCK_EvaluationFunction)(void *cls,
@@ -195,19 +196,83 @@ typedef enum GNUNET_BLOCK_EvaluationResult
195 196
196 197
197/** 198/**
199 * Function called to validate a query.
200 *
201 * @param cls closure
202 * @param ctx block context
203 * @param type block type
204 * @param query original query (hash)
205 * @param xquery extrended query data (can be NULL, depending on type)
206 * @param xquery_size number of bytes in @a xquery
207 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
208 */
209typedef enum GNUNET_GenericReturnValue
210(*GNUNET_BLOCK_QueryEvaluationFunction)(void *cls,
211 enum GNUNET_BLOCK_Type type,
212 const struct GNUNET_HashCode *query,
213 const void *xquery,
214 size_t xquery_size);
215
216
217/**
218 * Function called to validate a block for storage.
219 *
220 * @param cls closure
221 * @param type block type
222 * @param query key for the block (hash), must match exactly
223 * @param block block data to validate
224 * @param block_size number of bytes in @a block
225 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
226 */
227typedef enum GNUNET_GenericReturnValue
228(*GNUNET_BLOCK_BlockEvaluationFunction)(void *cls,
229 enum GNUNET_BLOCK_Type type,
230 const struct GNUNET_HashCode *query,
231 const void *block,
232 size_t block_size);
233
234
235/**
236 * Function called to validate a reply to a request. Note that it is assumed
237 * that the reply has already been matched to the key (and signatures checked)
238 * as it would be done with the GetKeyFunction and the
239 * BlockEvaluationFunction.
240 *
241 * @param cls closure
242 * @param type block type
243 * @param group which block group to use for evaluation
244 * @param query original query (hash)
245 * @param xquery extrended query data (can be NULL, depending on type)
246 * @param xquery_size number of bytes in @a xquery
247 * @param reply_block response to validate
248 * @param reply_block_size number of bytes in @a reply_block
249 * @return characterization of result
250 */
251typedef enum GNUNET_BLOCK_ReplyEvaluationResult
252(*GNUNET_BLOCK_ReplyEvaluationFunction)(void *cls,
253 enum GNUNET_BLOCK_Type type,
254 struct GNUNET_BLOCK_Group *group,
255 const struct GNUNET_HashCode *query,
256 const void *xquery,
257 size_t xquery_size,
258 const void *reply_block,
259 size_t reply_block_size);
260
261
262/**
198 * Function called to obtain the key for a block. 263 * Function called to obtain the key for a block.
199 * 264 *
200 * @param cls closure 265 * @param cls closure
201 * @param type block type 266 * @param type block type
202 * @param block block to get the key for 267 * @param block block to get the key for
203 * @param block_size number of bytes in @a block 268 * @param block_size number of bytes in @a block
204 * @param key set to the key (query) for the given block 269 * @param[out] key set to the key (query) for the given block
205 * @return #GNUNET_YES on success, 270 * @return #GNUNET_YES on success,
206 * #GNUNET_NO if the block is malformed 271 * #GNUNET_NO if the block is malformed
207 * #GNUNET_SYSERR if type not supported 272 * #GNUNET_SYSERR if type not supported
208 * (or if extracting a key from a block of this type does not work) 273 * (or if extracting a key from a block of this type does not work)
209 */ 274 */
210typedef int 275typedef enum GNUNET_GenericReturnValue
211(*GNUNET_BLOCK_GetKeyFunction) (void *cls, 276(*GNUNET_BLOCK_GetKeyFunction) (void *cls,
212 enum GNUNET_BLOCK_Type type, 277 enum GNUNET_BLOCK_Type type,
213 const void *block, 278 const void *block,
@@ -234,6 +299,8 @@ struct GNUNET_BLOCK_PluginFunctions
234 /** 299 /**
235 * Main function of a block plugin. Allows us to check if a 300 * Main function of a block plugin. Allows us to check if a
236 * block matches a query. 301 * block matches a query.
302 *
303 * @param deprecated
237 */ 304 */
238 GNUNET_BLOCK_EvaluationFunction evaluate; 305 GNUNET_BLOCK_EvaluationFunction evaluate;
239 306
@@ -247,6 +314,22 @@ struct GNUNET_BLOCK_PluginFunctions
247 * context (i.e. to detect duplicates). 314 * context (i.e. to detect duplicates).
248 */ 315 */
249 GNUNET_BLOCK_GroupCreateFunction create_group; 316 GNUNET_BLOCK_GroupCreateFunction create_group;
317
318 /**
319 * Check that a query is well-formed.
320 */
321 GNUNET_BLOCK_QueryEvaluationFunction check_query;
322
323 /**
324 * Check that a block is well-formed.
325 */
326 GNUNET_BLOCK_BlockEvaluationFunction check_block;
327
328 /**
329 * Check that a reply block matches a query.
330 */
331 GNUNET_BLOCK_ReplyEvaluationFunction check_reply;
332
250}; 333};
251 334
252#endif 335#endif
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 9166f822b..1ab135d80 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 <stdbool.h>
53#include <sodium.h> 54#include <sodium.h>
54 55
55/** 56/**
@@ -1037,61 +1038,38 @@ GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a,
1037 1038
1038 1039
1039/** 1040/**
1040 * @ingroup hash 1041 * Count the number of leading 0 bits in @a h.
1041 * Convert a hashcode into a key.
1042 * 1042 *
1043 * @param hc hash code that serves to generate the key 1043 * @param h a hash
1044 * @param skey set to a valid session key 1044 * @return number of leading 0 bits in @a h
1045 * @param iv set to a valid initialization vector
1046 */ 1045 */
1047void 1046unsigned int
1048GNUNET_CRYPTO_hash_to_aes_key ( 1047GNUNET_CRYPTO_hash_count_leading_zeros (const struct GNUNET_HashCode *h);
1049 const struct GNUNET_HashCode *hc,
1050 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
1051 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv);
1052 1048
1053 1049
1054/** 1050/**
1055 * @ingroup hash 1051 * Count the number of tailing 0 bits in @a h.
1056 * Obtain a bit from a hashcode.
1057 * 1052 *
1058 * @param code the `struct GNUNET_HashCode` to index bit-wise 1053 * @param h a hash
1059 * @param bit index into the hashcode, [0...159] where 0 is the leftmost bit 1054 * @return number of tailing 0 bits in @a h
1060 * (bytes in code interpreted big endian)
1061 * @return Bit \a bit from hashcode \a code, -1 for invalid index
1062 */
1063int
1064GNUNET_CRYPTO_hash_get_bit_ltr (const struct GNUNET_HashCode *code,
1065 unsigned int bit);
1066
1067
1068/**
1069 * Obtain a bit from a hashcode.
1070 * @param code the GNUNET_CRYPTO_hash to index bit-wise
1071 * @param bit index into the hashcode, [0...511] where 0 is the rightmost bit
1072 * (bytes in code interpreted little endian)
1073 * @return Bit \a bit from hashcode \a code, -1 for invalid index
1074 */ 1055 */
1075int 1056unsigned int
1076GNUNET_CRYPTO_hash_get_bit_rtl (const struct GNUNET_HashCode *code, 1057GNUNET_CRYPTO_hash_count_tailing_zeros (const struct GNUNET_HashCode *h);
1077 unsigned int bit);
1078 1058
1079 1059
1080/** 1060/**
1081 * @ingroup hash 1061 * @ingroup hash
1082 * Determine how many low order bits match in two 1062 * Convert a hashcode into a key.
1083 * `struct GNUNET_HashCodes`. e.g. - 010011 and 011111 share
1084 * the first two lowest order bits, and therefore the
1085 * return value is two (NOT XOR distance, nor how many
1086 * bits match absolutely!).
1087 * 1063 *
1088 * @param first the first hashcode 1064 * @param hc hash code that serves to generate the key
1089 * @param second the hashcode to compare first to 1065 * @param skey set to a valid session key
1090 * @return the number of bits that match 1066 * @param iv set to a valid initialization vector
1091 */ 1067 */
1092unsigned int 1068void
1093GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode *first, 1069GNUNET_CRYPTO_hash_to_aes_key (
1094 const struct GNUNET_HashCode *second); 1070 const struct GNUNET_HashCode *hc,
1071 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
1072 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv);
1095 1073
1096 1074
1097/** 1075/**
@@ -2606,7 +2584,6 @@ void
2606GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv, 2584GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
2607 struct GNUNET_CRYPTO_CsRPublic *r_pub); 2585 struct GNUNET_CRYPTO_CsRPublic *r_pub);
2608 2586
2609
2610/** 2587/**
2611 * Derives new random blinding factors. 2588 * Derives new random blinding factors.
2612 * In original papers blinding factors are generated randomly 2589 * In original papers blinding factors are generated randomly
@@ -2614,13 +2591,12 @@ GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
2614 * To ensure unpredictability a new nonce has to be used. 2591 * To ensure unpredictability a new nonce has to be used.
2615 * Uses HKDF internally 2592 * Uses HKDF internally
2616 * 2593 *
2617 * @param secret is secret to derive blinding factors 2594 * @param blind_seed is the blinding seed to derive blinding factors
2618 * @param secret_len secret length
2619 * @param[out] bs array containing the two derived blinding secrets 2595 * @param[out] bs array containing the two derived blinding secrets
2620 */ 2596 */
2621void 2597void
2622GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret, 2598GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct
2623 size_t secret_len, 2599 GNUNET_CRYPTO_CsNonce *blind_seed,
2624 struct GNUNET_CRYPTO_CsBlindingSecret 2600 struct GNUNET_CRYPTO_CsBlindingSecret
2625 bs[2]); 2601 bs[2]);
2626 2602
diff --git a/src/include/gnunet_datacache_lib.h b/src/include/gnunet_datacache_lib.h
index 40885803b..519c36bb4 100644
--- a/src/include/gnunet_datacache_lib.h
+++ b/src/include/gnunet_datacache_lib.h
@@ -146,20 +146,6 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
146 146
147 147
148/** 148/**
149 * Obtain a random element from the datacache.
150 *
151 * @param h handle to the datacache
152 * @param iter maybe NULL (to just count)
153 * @param iter_cls closure for @a iter
154 * @return the number of results found (zero or 1)
155 */
156unsigned int
157GNUNET_DATACACHE_get_random (struct GNUNET_DATACACHE_Handle *h,
158 GNUNET_DATACACHE_Iterator iter,
159 void *iter_cls);
160
161
162/**
163 * Iterate over the results that are "close" to a particular key in 149 * Iterate over the results that are "close" to a particular key in
164 * the datacache. "close" is defined as numerically larger than @a 150 * the datacache. "close" is defined as numerically larger than @a
165 * key (when interpreted as a circular address space), with small 151 * key (when interpreted as a circular address space), with small
diff --git a/src/include/gnunet_datacache_plugin.h b/src/include/gnunet_datacache_plugin.h
index d7fa8fde0..5d5cac12c 100644
--- a/src/include/gnunet_datacache_plugin.h
+++ b/src/include/gnunet_datacache_plugin.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2006, 2009, 2015 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2015, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -115,15 +115,17 @@ struct GNUNET_DATACACHE_PluginFunctions
115 * @param path_info a path through the network 115 * @param path_info a path through the network
116 * @return 0 if duplicate, -1 on error, number of bytes used otherwise 116 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
117 */ 117 */
118 ssize_t (*put) (void *cls, 118 ssize_t
119 const struct GNUNET_HashCode *key, 119 (*put) (void *cls,
120 uint32_t xor_distance, 120 const struct GNUNET_HashCode *key,
121 size_t size, 121 uint32_t xor_distance,
122 const char *data, 122 size_t size,
123 enum GNUNET_BLOCK_Type type, 123 const char *data,
124 struct GNUNET_TIME_Absolute discard_time, 124 enum GNUNET_BLOCK_Type type,
125 unsigned int path_info_len, 125 struct GNUNET_TIME_Absolute discard_time,
126 const struct GNUNET_PeerIdentity *path_info); 126 unsigned int path_info_len,
127 const struct GNUNET_PeerIdentity *path_info);
128
127 129
128 /** 130 /**
129 * Iterate over the results for a particular key 131 * Iterate over the results for a particular key
@@ -136,11 +138,13 @@ struct GNUNET_DATACACHE_PluginFunctions
136 * @param iter_cls closure for @a iter 138 * @param iter_cls closure for @a iter
137 * @return the number of results found 139 * @return the number of results found
138 */ 140 */
139 unsigned int (*get) (void *cls, 141 unsigned int
140 const struct GNUNET_HashCode *key, 142 (*get) (void *cls,
141 enum GNUNET_BLOCK_Type type, 143 const struct GNUNET_HashCode *key,
142 GNUNET_DATACACHE_Iterator iter, 144 enum GNUNET_BLOCK_Type type,
143 void *iter_cls); 145 GNUNET_DATACACHE_Iterator iter,
146 void *iter_cls);
147
144 148
145 /** 149 /**
146 * Delete the entry with the lowest expiration value 150 * Delete the entry with the lowest expiration value
@@ -149,19 +153,8 @@ struct GNUNET_DATACACHE_PluginFunctions
149 * @param cls closure (internal context for the plugin) 153 * @param cls closure (internal context for the plugin)
150 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 154 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
151 */ 155 */
152 int (*del) (void *cls); 156 enum GNUNET_GenericReturnValue
153 157 (*del)(void *cls);
154 /**
155 * Return a random value from the datastore.
156 *
157 * @param cls closure (internal context for the plugin)
158 * @param iter maybe NULL (to just count)
159 * @param iter_cls closure for @a iter
160 * @return the number of results found (zero or one)
161 */
162 unsigned int (*get_random) (void *cls,
163 GNUNET_DATACACHE_Iterator iter,
164 void *iter_cls);
165 158
166 159
167 /** 160 /**
@@ -177,11 +170,12 @@ struct GNUNET_DATACACHE_PluginFunctions
177 * @param iter_cls closure for @a iter 170 * @param iter_cls closure for @a iter
178 * @return the number of results found 171 * @return the number of results found
179 */ 172 */
180 unsigned int (*get_closest) (void *cls, 173 unsigned int
181 const struct GNUNET_HashCode *key, 174 (*get_closest) (void *cls,
182 unsigned int num_results, 175 const struct GNUNET_HashCode *key,
183 GNUNET_DATACACHE_Iterator iter, 176 unsigned int num_results,
184 void *iter_cls); 177 GNUNET_DATACACHE_Iterator iter,
178 void *iter_cls);
185}; 179};
186 180
187 181
diff --git a/src/include/gnunet_dht_service.h b/src/include/gnunet_dht_service.h
index d4a4ed7d2..160beffdd 100644
--- a/src/include/gnunet_dht_service.h
+++ b/src/include/gnunet_dht_service.h
@@ -56,6 +56,12 @@ extern "C"
56 56
57 57
58/** 58/**
59 * Maximum allowed replication level for all requests.
60 */
61#define GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL 16
62
63
64/**
59 * Connection to the DHT service. 65 * Connection to the DHT service.
60 */ 66 */
61struct GNUNET_DHT_Handle; 67struct GNUNET_DHT_Handle;
diff --git a/src/include/gnunet_getopt_lib.h b/src/include/gnunet_getopt_lib.h
index 731be4159..259d648dd 100644
--- a/src/include/gnunet_getopt_lib.h
+++ b/src/include/gnunet_getopt_lib.h
@@ -378,6 +378,24 @@ GNUNET_GETOPT_option_absolute_time (char shortName,
378 378
379 379
380/** 380/**
381 * Allow user to specify a `struct GNUNET_TIME_Timestamp`
382 * (using human-readable "fancy" time).
383 *
384 * @param shortName short name of the option
385 * @param name long name of the option
386 * @param argumentHelp help text for the option argument
387 * @param description long help text for the option
388 * @param[out] val set to the time specified at the command line
389 */
390struct GNUNET_GETOPT_CommandLineOption
391GNUNET_GETOPT_option_timestamp (char shortName,
392 const char *name,
393 const char *argumentHelp,
394 const char *description,
395 struct GNUNET_TIME_Timestamp *val);
396
397
398/**
381 * Increment @a val each time the option flag is given by one. 399 * Increment @a val each time the option flag is given by one.
382 * 400 *
383 * @param shortName short name of the option 401 * @param shortName short name of the option
diff --git a/src/include/gnunet_identity_service.h b/src/include/gnunet_identity_service.h
index c123983e2..e40a741bf 100644
--- a/src/include/gnunet_identity_service.h
+++ b/src/include/gnunet_identity_service.h
@@ -82,6 +82,8 @@ struct GNUNET_IDENTITY_Handle;
82 */ 82 */
83struct GNUNET_IDENTITY_Ego; 83struct GNUNET_IDENTITY_Ego;
84 84
85// FIXME: these types are NOT packed,
86// NOT 64-bit aligned, but used in messages!!??
85 87
86/** 88/**
87 * A private key for an identity as per LSD0001. 89 * A private key for an identity as per LSD0001.
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h
index 5ef4592e5..7d101196c 100644
--- a/src/include/gnunet_json_lib.h
+++ b/src/include/gnunet_json_lib.h
@@ -304,25 +304,25 @@ GNUNET_JSON_spec_boolean (const char *name,
304/* ************ GNUnet-specific parser specifications ******************* */ 304/* ************ GNUnet-specific parser specifications ******************* */
305 305
306/** 306/**
307 * Absolute time. 307 * Timestamp.
308 * 308 *
309 * @param name name of the JSON field 309 * @param name name of the JSON field
310 * @param[out] at where to store the absolute time found under @a name 310 * @param[out] at where to store the absolute time found under @a name
311 */ 311 */
312struct GNUNET_JSON_Specification 312struct GNUNET_JSON_Specification
313GNUNET_JSON_spec_absolute_time (const char *name, 313GNUNET_JSON_spec_timestamp (const char *name,
314 struct GNUNET_TIME_Absolute *at); 314 struct GNUNET_TIME_Timestamp *t);
315 315
316 316
317/** 317/**
318 * Absolute time in network byte order. 318 * Timestamp in network byte order.
319 * 319 *
320 * @param name name of the JSON field 320 * @param name name of the JSON field
321 * @param[out] at where to store the absolute time found under @a name 321 * @param[out] tn where to store the absolute time found under @a name
322 */ 322 */
323struct GNUNET_JSON_Specification 323struct GNUNET_JSON_Specification
324GNUNET_JSON_spec_absolute_time_nbo (const char *name, 324GNUNET_JSON_spec_timestamp_nbo (const char *name,
325 struct GNUNET_TIME_AbsoluteNBO *at); 325 struct GNUNET_TIME_TimestampNBO *tn);
326 326
327 327
328/** 328/**
@@ -385,23 +385,23 @@ GNUNET_JSON_from_data (const void *data, size_t size);
385 385
386 386
387/** 387/**
388 * Convert absolute timestamp to a json string. 388 * Convert timestamp to a json string.
389 * 389 *
390 * @param stamp the time stamp 390 * @param stamp the time stamp
391 * @return a json string with the timestamp in @a stamp 391 * @return a json string with the timestamp in @a stamp
392 */ 392 */
393json_t * 393json_t *
394GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp); 394GNUNET_JSON_from_timestamp (struct GNUNET_TIME_Timestamp stamp);
395 395
396 396
397/** 397/**
398 * Convert absolute timestamp to a json string. 398 * Convert timestamp to a json string.
399 * 399 *
400 * @param stamp the time stamp 400 * @param stamp the time stamp
401 * @return a json string with the timestamp in @a stamp 401 * @return a json string with the timestamp in @a stamp
402 */ 402 */
403json_t * 403json_t *
404GNUNET_JSON_from_time_abs_nbo (struct GNUNET_TIME_AbsoluteNBO stamp); 404GNUNET_JSON_from_timestamp_nbo (struct GNUNET_TIME_TimestampNBO stamp);
405 405
406 406
407/** 407/**
@@ -747,30 +747,30 @@ GNUNET_JSON_pack_data_varsize (const char *name,
747 747
748/** 748/**
749 * Generate packer instruction for a JSON field of type 749 * Generate packer instruction for a JSON field of type
750 * absolute time. 750 * timestamp.
751 * 751 *
752 * @param name name of the field to add to the object 752 * @param name name of the field to add to the object
753 * @param at absolute time to pack, a value of 0 is only 753 * @param at timestamp pack, a value of 0 is only
754 * allowed with #GNUNET_JSON_pack_allow_null()! 754 * allowed with #GNUNET_JSON_pack_allow_null()!
755 * @return json pack specification 755 * @return json pack specification
756 */ 756 */
757struct GNUNET_JSON_PackSpec 757struct GNUNET_JSON_PackSpec
758GNUNET_JSON_pack_time_abs (const char *name, 758GNUNET_JSON_pack_timestamp (const char *name,
759 struct GNUNET_TIME_Absolute at); 759 struct GNUNET_TIME_Timestamp at);
760 760
761 761
762/** 762/**
763 * Generate packer instruction for a JSON field of type 763 * Generate packer instruction for a JSON field of type
764 * absolute time in network byte order. 764 * timestamp in network byte order.
765 * 765 *
766 * @param name name of the field to add to the object 766 * @param name name of the field to add to the object
767 * @param at absolute time to pack, a value of 0 is only 767 * @param at timestamp to pack, a value of 0 is only
768 * allowed with #GNUNET_JSON_pack_allow_null()! 768 * allowed with #GNUNET_JSON_pack_allow_null()!
769 * @return json pack specification 769 * @return json pack specification
770 */ 770 */
771struct GNUNET_JSON_PackSpec 771struct GNUNET_JSON_PackSpec
772GNUNET_JSON_pack_time_abs_nbo (const char *name, 772GNUNET_JSON_pack_timestamp_nbo (const char *name,
773 struct GNUNET_TIME_AbsoluteNBO at); 773 struct GNUNET_TIME_TimestampNBO at);
774 774
775 775
776/** 776/**
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h
index 05d373f88..f7bf59212 100644
--- a/src/include/gnunet_pq_lib.h
+++ b/src/include/gnunet_pq_lib.h
@@ -96,7 +96,11 @@ struct GNUNET_PQ_QueryParam
96 */ 96 */
97#define GNUNET_PQ_query_param_end \ 97#define GNUNET_PQ_query_param_end \
98 { \ 98 { \
99 NULL, NULL, NULL, 0, 0 \ 99 .conv = NULL, \
100 .conv_cls = NULL, \
101 .data = NULL, \
102 .size = 0, \
103 .num_params = 0 \
100 } 104 }
101 105
102 106
@@ -200,6 +204,17 @@ GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x);
200 204
201 205
202/** 206/**
207 * Generate query parameter for a timestamp.
208 * The database must store a 64-bit integer.
209 *
210 * @param x pointer to the query parameter to pass
211 * @return query parameter to use
212 */
213struct GNUNET_PQ_QueryParam
214GNUNET_PQ_query_param_timestamp (const struct GNUNET_TIME_Timestamp *x);
215
216
217/**
203 * Generate query parameter for an absolute time value. 218 * Generate query parameter for an absolute time value.
204 * The database must store a 64-bit integer. 219 * The database must store a 64-bit integer.
205 * 220 *
@@ -212,6 +227,18 @@ GNUNET_PQ_query_param_absolute_time_nbo (
212 227
213 228
214/** 229/**
230 * Generate query parameter for a timestamp in NBO.
231 * The database must store a 64-bit integer.
232 *
233 * @param x pointer to the query parameter to pass
234 * @return query parameter to use
235 */
236struct GNUNET_PQ_QueryParam
237GNUNET_PQ_query_param_timestamp_nbo (
238 const struct GNUNET_TIME_TimestampNBO *t);
239
240
241/**
215 * Generate query parameter for an uint16_t in host byte order. 242 * Generate query parameter for an uint16_t in host byte order.
216 * 243 *
217 * @param x pointer to the query parameter to pass 244 * @param x pointer to the query parameter to pass
@@ -472,6 +499,18 @@ GNUNET_PQ_result_spec_absolute_time (const char *name,
472 499
473 500
474/** 501/**
502 * Timestamp expected.
503 *
504 * @param name name of the field in the table
505 * @param[out] t where to store the result
506 * @return array entry for the result specification to use
507 */
508struct GNUNET_PQ_ResultSpec
509GNUNET_PQ_result_spec_timestamp (const char *name,
510 struct GNUNET_TIME_Timestamp *t);
511
512
513/**
475 * Relative time expected. 514 * Relative time expected.
476 * 515 *
477 * @param name name of the field in the table 516 * @param name name of the field in the table
@@ -496,6 +535,18 @@ GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
496 535
497 536
498/** 537/**
538 * Timestamp expected.
539 *
540 * @param name name of the field in the table
541 * @param[out] tn where to store the result
542 * @return array entry for the result specification to use
543 */
544struct GNUNET_PQ_ResultSpec
545GNUNET_PQ_result_spec_timestamp_nbo (const char *name,
546 struct GNUNET_TIME_TimestampNBO *tn);
547
548
549/**
499 * uint16_t expected. 550 * uint16_t expected.
500 * 551 *
501 * @param name name of the field in the table 552 * @param name name of the field in the table
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
deleted file mode 100644
index 7c0c1d104..000000000
--- a/src/include/gnunet_signatures.h
+++ /dev/null
@@ -1,266 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 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 * @author Christian Grothoff
23 *
24 * @file
25 * Constants for network signatures
26 *
27 * @defgroup signatures Network signature definitions
28 * @{
29 */
30
31#ifndef GNUNET_SIGNATURES_H
32#define GNUNET_SIGNATURES_H
33
34#ifdef __cplusplus
35extern "C"
36{
37#if 0 /* keep Emacsens' auto-indent happy */
38}
39#endif
40#endif
41
42/**
43 * Test signature, not valid for anything other than writing
44 * a test. (Note that the signature verification code will
45 * accept this value).
46 */
47#define GNUNET_SIGNATURE_PURPOSE_TEST 0
48
49/**
50 * Signature for confirming that this peer uses a particular address.
51 */
52#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN 1
53
54/**
55 * Signature for confirming that this peer intends to disconnect.
56 */
57#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DISCONNECT 2
58
59/**
60 * Signature for confirming a key revocation.
61 */
62#define GNUNET_SIGNATURE_PURPOSE_REVOCATION 3
63
64/**
65 * Signature for a namespace/pseudonym advertisement (by
66 * the namespace owner).
67 */
68#define GNUNET_SIGNATURE_PURPOSE_NAMESPACE_ADVERTISEMENT 4
69
70/**
71 * Signature by which a peer affirms that it is
72 * providing a certain bit of content (used
73 * in LOCation URIs).
74 */
75#define GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT 5
76
77/**
78 * Obsolete, legacy value.
79 */
80#define GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK 6
81
82/**
83 * Obsolete, legacy value.
84 */
85#define GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK 7
86
87/**
88 * Obsolete, legacy value.
89 */
90#define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK 8
91
92/**
93 * Obsolete, legacy value.
94 */
95#define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG 9
96
97/**
98 *
99 */
100#define GNUNET_SIGNATURE_PURPOSE_RESOLVER_RESPONSE 10
101
102/**
103 * Signature of an GNUNET_DNS_Advertisement
104 */
105#define GNUNET_SIGNATURE_PURPOSE_DNS_RECORD 11
106
107/**
108 * Signature of a chat message.
109 */
110#define GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE 12
111
112/**
113 * Signature of confirmation receipt for a chat message.
114 */
115#define GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT 13
116
117/**
118 * Signature of a network size estimate message.
119 */
120#define GNUNET_SIGNATURE_PURPOSE_NSE_SEND 14
121
122/**
123 * Signature of a gnunet naming system record block
124 */
125#define GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN 15
126
127/**
128 * Purpose is to set a session key.
129 */
130#define GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY 16
131
132/**
133 * UBlock Signature, done using DSS, not ECC
134 */
135#define GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK 17
136
137/**
138 * Accept state in regex DFA. Peer affirms that
139 * it offers the matching service.
140 */
141#define GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT 18
142
143/**
144 * Signature of a multicast message sent by the origin.
145 */
146#define GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE 19
147
148/**
149 * Signature of a conversation ring.
150 */
151#define GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING 20
152
153/**
154 * Signature for the first round of distributed key generation.
155 */
156#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 21
157
158/**
159 * Signature for the second round of distributed key generation.
160 */
161#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2 22
162
163/**
164 * Signature for cooperatice decryption.
165 */
166#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION 23
167
168/**
169 * Signature of a multicast request sent by a member.
170 */
171#define GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST 24
172
173/**
174 * Signature for a sensor anomaly report message.
175 */
176#define GNUNET_SIGNATURE_PURPOSE_SENSOR_ANOMALY_REPORT 25
177
178/**
179 * Signature for a GNUid Token
180 */
181#define GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN 26
182
183/**
184 * Signature for a GNUid Ticket
185 */
186#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN 27
187
188/**
189 * Signature for a GNUnet credential
190 */
191#define GNUNET_SIGNATURE_PURPOSE_DELEGATE 28
192
193/**
194 * Signature by a peer affirming that this is one of its
195 * addresses (for the given time period).
196 */
197#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS 29
198
199/**
200 * Signature by a peer affirming that the given ephemeral
201 * key is currently in use by that peer's transport service.
202 */
203#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL 30
204
205/**
206 * Signature used by TCP communicator handshake,
207 */
208#define GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE 31
209
210/**
211 * Signature used by TCP communicator rekey.
212 */
213#define GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY 32
214
215/**
216 * Signature used by UDP communicator handshake
217 */
218#define GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE 33
219
220/**
221 * Signature used by UDP broadcasts.
222 */
223#define GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST 34
224
225/**
226 * Signature by a peer affirming that it received a
227 * challenge (and stating how long it expects the
228 * address on which the challenge was received to
229 * remain valid).
230 */
231#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE 35
232
233/**
234 * Signature by a peer affirming that it is on a DV path.
235 */
236#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_HOP 36
237
238/**
239 * Signature by a peer affirming that it originated the
240 * DV path.
241 */
242#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR 37
243
244/**
245 * Signature by a peer that like to create a connection.
246 */
247#define GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR 38
248
249/**
250 * Signature by a peer sending back the nonce received at initial handshake.
251 */
252#define GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK 39
253
254#if 0 /* keep Emacsens' auto-indent happy */
255{
256#endif
257#ifdef __cplusplus
258}
259#endif
260
261/* ifndef GNUNET_SIGNATURES_H */
262#endif
263
264/** @} */ /* end of group */
265
266/* end of gnunet_signatures.h */
diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h
index 21ce5b393..e89ded07e 100644
--- a/src/include/gnunet_sq_lib.h
+++ b/src/include/gnunet_sq_lib.h
@@ -40,7 +40,7 @@
40 * so immediately suitable for passing to `sqlite3_bind`-functions. 40 * so immediately suitable for passing to `sqlite3_bind`-functions.
41 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success 41 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
42 */ 42 */
43typedef int 43typedef enum GNUNET_GenericReturnValue
44(*GNUNET_SQ_QueryConverter)(void *cls, 44(*GNUNET_SQ_QueryConverter)(void *cls,
45 const void *data, 45 const void *data,
46 size_t data_len, 46 size_t data_len,
@@ -156,8 +156,8 @@ GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x);
156 * @param x pointer to the query parameter to pass 156 * @param x pointer to the query parameter to pass
157 */ 157 */
158struct GNUNET_SQ_QueryParam 158struct GNUNET_SQ_QueryParam
159GNUNET_SQ_query_param_absolute_time_nbo (const struct 159GNUNET_SQ_query_param_absolute_time_nbo (
160 GNUNET_TIME_AbsoluteNBO *x); 160 const struct GNUNET_TIME_AbsoluteNBO *x);
161 161
162 162
163/** 163/**
@@ -222,7 +222,7 @@ GNUNET_SQ_reset (sqlite3 *dbh,
222 * #GNUNET_YES if all results could be extracted 222 * #GNUNET_YES if all results could be extracted
223 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) 223 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
224 */ 224 */
225typedef int 225typedef enum GNUNET_GenericReturnValue
226(*GNUNET_SQ_ResultConverter)(void *cls, 226(*GNUNET_SQ_ResultConverter)(void *cls,
227 sqlite3_stmt *result, 227 sqlite3_stmt *result,
228 unsigned int column, 228 unsigned int column,
@@ -436,7 +436,7 @@ GNUNET_SQ_result_spec_uint64 (uint64_t *u64);
436 * #GNUNET_OK if all results could be extracted 436 * #GNUNET_OK if all results could be extracted
437 * #GNUNET_SYSERR if a result was invalid (non-existing field) 437 * #GNUNET_SYSERR if a result was invalid (non-existing field)
438 */ 438 */
439int 439enum GNUNET_GenericReturnValue
440GNUNET_SQ_extract_result (sqlite3_stmt *result, 440GNUNET_SQ_extract_result (sqlite3_stmt *result,
441 struct GNUNET_SQ_ResultSpec *rs); 441 struct GNUNET_SQ_ResultSpec *rs);
442 442
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 977c2ead7..2e0c720ee 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -76,7 +76,7 @@ GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
76 * @param rtime set to the relative time 76 * @param rtime set to the relative time
77 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 77 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
78 */ 78 */
79int 79enum GNUNET_GenericReturnValue
80GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, 80GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
81 struct GNUNET_TIME_Relative *rtime); 81 struct GNUNET_TIME_Relative *rtime);
82 82
@@ -91,12 +91,27 @@ GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
91 * @param atime set to the absolute time 91 * @param atime set to the absolute time
92 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 92 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
93 */ 93 */
94int 94enum GNUNET_GenericReturnValue
95GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time, 95GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
96 struct GNUNET_TIME_Absolute *atime); 96 struct GNUNET_TIME_Absolute *atime);
97 97
98 98
99/** 99/**
100 * @ingroup time
101 * Convert a given fancy human-readable time to our internal
102 * representation. The human-readable time is expected to be
103 * in local time, whereas the returned value will be in UTC.
104 *
105 * @param fancy_time human readable string (e.g. %Y-%m-%d %H:%M:%S)
106 * @param atime set to the absolute time
107 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
108 */
109enum GNUNET_GenericReturnValue
110GNUNET_STRINGS_fancy_time_to_timestamp (const char *fancy_time,
111 struct GNUNET_TIME_Timestamp *atime);
112
113
114/**
100 * Convert a given filesize into a fancy human-readable format. 115 * Convert a given filesize into a fancy human-readable format.
101 * 116 *
102 * @param size number of bytes 117 * @param size number of bytes
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h
index 26b442066..b14439462 100644
--- a/src/include/gnunet_time_lib.h
+++ b/src/include/gnunet_time_lib.h
@@ -54,6 +54,17 @@ struct GNUNET_TIME_Absolute
54}; 54};
55 55
56/** 56/**
57 * Rounded time for timestamps used by GNUnet, in seconds.
58 */
59struct GNUNET_TIME_Timestamp
60{
61 /**
62 * The actual value. Must be round number in seconds.
63 */
64 struct GNUNET_TIME_Absolute abs_time;
65};
66
67/**
57 * Time for relative time used by GNUnet, in microseconds. 68 * Time for relative time used by GNUnet, in microseconds.
58 * Always positive, so we can only refer to future time. 69 * Always positive, so we can only refer to future time.
59 */ 70 */
@@ -89,17 +100,34 @@ struct GNUNET_TIME_AbsoluteNBO
89 */ 100 */
90 uint64_t abs_value_us__ GNUNET_PACKED; 101 uint64_t abs_value_us__ GNUNET_PACKED;
91}; 102};
103
104/**
105 * Time for timestamps used by GNUnet, in seconds and in network byte order.
106 */
107struct GNUNET_TIME_TimestampNBO
108{
109 /**
110 * The actual value. Must be round number in seconds.
111 */
112 struct GNUNET_TIME_AbsoluteNBO abs_time_nbo;
113};
114
92GNUNET_NETWORK_STRUCT_END 115GNUNET_NETWORK_STRUCT_END
93 116
94/** 117/**
95 * Relative time zero. 118 * Relative time zero.
96 */ 119 */
97#define GNUNET_TIME_UNIT_ZERO GNUNET_TIME_relative_get_zero_ () 120#define GNUNET_TIME_UNIT_ZERO ((struct GNUNET_TIME_Relative){0})
98 121
99/** 122/**
100 * Absolute time zero. 123 * Absolute time zero.
101 */ 124 */
102#define GNUNET_TIME_UNIT_ZERO_ABS GNUNET_TIME_absolute_get_zero_ () 125#define GNUNET_TIME_UNIT_ZERO_ABS ((struct GNUNET_TIME_Absolute){0})
126
127/**
128 * Timestamp of zero.
129 */
130#define GNUNET_TIME_UNIT_ZERO_TS ((struct GNUNET_TIME_Timestamp){{0}})
103 131
104/** 132/**
105 * One microsecond, our basic time unit. 133 * One microsecond, our basic time unit.
@@ -154,13 +182,22 @@ GNUNET_NETWORK_STRUCT_END
154 * Constant used to specify "forever". This constant 182 * Constant used to specify "forever". This constant
155 * will be treated specially in all time operations. 183 * will be treated specially in all time operations.
156 */ 184 */
157#define GNUNET_TIME_UNIT_FOREVER_REL GNUNET_TIME_relative_get_forever_ () 185#define GNUNET_TIME_UNIT_FOREVER_REL \
186 ((struct GNUNET_TIME_Relative){UINT64_MAX})
158 187
159/** 188/**
160 * Constant used to specify "forever". This constant 189 * Constant used to specify "forever". This constant
161 * will be treated specially in all time operations. 190 * will be treated specially in all time operations.
162 */ 191 */
163#define GNUNET_TIME_UNIT_FOREVER_ABS GNUNET_TIME_absolute_get_forever_ () 192#define GNUNET_TIME_UNIT_FOREVER_ABS \
193 ((struct GNUNET_TIME_Absolute){UINT64_MAX})
194
195/**
196 * Constant used to specify "forever". This constant
197 * will be treated specially in all time operations.
198 */
199#define GNUNET_TIME_UNIT_FOREVER_TS \
200 ((struct GNUNET_TIME_Timestamp){{UINT64_MAX}})
164 201
165 202
166/** 203/**
@@ -183,6 +220,47 @@ GNUNET_NETWORK_STRUCT_END
183 220
184 221
185/** 222/**
223 * Convert @a ts to human-readable timestamp.
224 * Note that the returned value will be overwritten if this function
225 * is called again.
226 *
227 * @param ts the timestamp to convert
228 * @return statically allocated string, will change on the next call
229 */
230const char *
231GNUNET_TIME_timestamp2s (struct GNUNET_TIME_Timestamp ts);
232
233
234/**
235 * @ingroup time
236 * Like `asctime`, except for GNUnet time. Converts a GNUnet internal
237 * absolute time (which is in UTC) to a string in local time.
238 * Note that the returned value will be overwritten if this function
239 * is called again.
240 *
241 * @param t the absolute time to convert
242 * @return timestamp in human-readable form in local time
243 */
244const char *
245GNUNET_TIME_absolute2s (struct GNUNET_TIME_Absolute ts);
246
247
248/**
249 * @ingroup time
250 * Give relative time in human-readable fancy format.
251 * This is one of the very few calls in the entire API that is
252 * NOT reentrant!
253 *
254 * @param delta time in milli seconds
255 * @param do_round are we allowed to round a bit?
256 * @return string in human-readable form
257 */
258const char *
259GNUNET_TIME_relative2s (struct GNUNET_TIME_Relative delta,
260 bool do_round);
261
262
263/**
186 * Randomized exponential back-off, starting at 1 ms 264 * Randomized exponential back-off, starting at 1 ms
187 * and going up by a factor of 2+r, where 0 <= r <= 0.5, up 265 * and going up by a factor of 2+r, where 0 <= r <= 0.5, up
188 * to a maximum of the given threshold. 266 * to a maximum of the given threshold.
@@ -192,8 +270,8 @@ GNUNET_NETWORK_STRUCT_END
192 * @return the next backoff time 270 * @return the next backoff time
193 */ 271 */
194struct GNUNET_TIME_Relative 272struct GNUNET_TIME_Relative
195GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt, struct 273GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
196 GNUNET_TIME_Relative threshold); 274 struct GNUNET_TIME_Relative threshold);
197 275
198 276
199/** 277/**
@@ -290,27 +368,69 @@ GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel);
290 368
291 369
292/** 370/**
293 * Round a time value so that it is suitable for transmission 371 * Convert relative time to a timestamp in the
294 * via JSON encodings. 372 * future.
373 *
374 * @param rel relative time to convert
375 * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow)
376 */
377struct GNUNET_TIME_Timestamp
378GNUNET_TIME_relative_to_timestamp (struct GNUNET_TIME_Relative rel);
379
380
381/**
382 * Round an absolute time to a timestamp.
295 * 383 *
296 * @param at time to round 384 * @param at time to round
297 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if 385 * @return the result
298 * it was just now rounded
299 */ 386 */
300int 387struct GNUNET_TIME_Timestamp
301GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at); 388GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at);
302 389
303 390
304/** 391/**
305 * Round a time value so that it is suitable for transmission 392 * Get timestamp representing the current time.
306 * via JSON encodings.
307 * 393 *
308 * @param rt time to round 394 * @return current time, rounded down to seconds
309 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
310 * it was just now rounded
311 */ 395 */
312int 396struct GNUNET_TIME_Timestamp
313GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt); 397GNUNET_TIME_timestamp_get (void);
398
399
400/**
401 * Compare two absolute times.
402 *
403 * @param t1 first time
404 * @param op compare operator
405 * @param t2 second time
406 * @return true if @a t1 @a op @a t2
407 */
408#define GNUNET_TIME_absolute_cmp(t1,op,t2) \
409 ((void) (1 op 2), (t1).abs_value_us op (t2).abs_value_us)
410
411
412/**
413 * Compare two timestamps
414 *
415 * @param t1 first timestamp
416 * @param op compare operator
417 * @param t2 second timestamp
418 * @return true if @a t1 @a op @a t2
419 */
420#define GNUNET_TIME_timestamp_cmp(t1,op,t2) \
421 GNUNET_TIME_absolute_cmp ((t1).abs_time,op,(t2).abs_time)
422
423
424/**
425 * Compare two relative times.
426 *
427 * @param t1 first time
428 * @param op compare operator
429 * @param t2 second time
430 * @return true if @a t1 @a op @a t2
431 */
432#define GNUNET_TIME_relative_cmp(t1,op,t2) \
433 ((void) (1 op 2), (t1).rel_value_us op (t2).rel_value_us)
314 434
315 435
316/** 436/**
@@ -362,6 +482,30 @@ GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
362 482
363 483
364/** 484/**
485 * Return the maximum of two timestamps.
486 *
487 * @param t1 first timestamp
488 * @param t2 other timestamp
489 * @return timestamp that is smaller
490 */
491struct GNUNET_TIME_Timestamp
492GNUNET_TIME_timestamp_max (struct GNUNET_TIME_Timestamp t1,
493 struct GNUNET_TIME_Timestamp t2);
494
495
496/**
497 * Return the minimum of two timestamps.
498 *
499 * @param t1 first timestamp
500 * @param t2 other timestamp
501 * @return timestamp that is smaller
502 */
503struct GNUNET_TIME_Timestamp
504GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1,
505 struct GNUNET_TIME_Timestamp t2);
506
507
508/**
365 * Given a timestamp in the future, how much time 509 * Given a timestamp in the future, how much time
366 * remains until then? 510 * remains until then?
367 * 511 *
@@ -530,6 +674,16 @@ GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a);
530 674
531 675
532/** 676/**
677 * Convert timestamp to network byte order.
678 *
679 * @param t time to convert
680 * @return converted time value
681 */
682struct GNUNET_TIME_TimestampNBO
683GNUNET_TIME_timestamp_hton (struct GNUNET_TIME_Timestamp t);
684
685
686/**
533 * Convert milliseconds after the UNIX epoch to absolute time. 687 * Convert milliseconds after the UNIX epoch to absolute time.
534 * 688 *
535 * @param ms_after_epoch millisecond timestamp to convert 689 * @param ms_after_epoch millisecond timestamp to convert
@@ -558,6 +712,15 @@ GNUNET_TIME_absolute_is_past (struct GNUNET_TIME_Absolute abs);
558 712
559 713
560/** 714/**
715 * Test if @a abs is truly zero.
716 *
717 * @return true if it is.
718 */
719bool
720GNUNET_TIME_absolute_is_zero (struct GNUNET_TIME_Absolute abs);
721
722
723/**
561 * Test if @a abs is truly in the future (excluding now). 724 * Test if @a abs is truly in the future (excluding now).
562 * 725 *
563 * @return true if it is. 726 * @return true if it is.
@@ -595,6 +758,15 @@ GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch);
595 758
596 759
597/** 760/**
761 * Convert seconds after the UNIX epoch to timestamp.
762 *
763 * @param s_after_epoch seconds after epoch to convert
764 * @return converted time value
765 */struct GNUNET_TIME_Timestamp
766GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch);
767
768
769/**
598 * Convert absolute time from network byte order. 770 * Convert absolute time from network byte order.
599 * 771 *
600 * @param a time to convert 772 * @param a time to convert
@@ -605,6 +777,16 @@ GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a);
605 777
606 778
607/** 779/**
780 * Convert timestamp from network byte order.
781 *
782 * @param tn time to convert
783 * @return converted time value
784 */
785struct GNUNET_TIME_Timestamp
786GNUNET_TIME_timestamp_ntoh (struct GNUNET_TIME_TimestampNBO tn);
787
788
789/**
608 * Set the timestamp offset for this instance. 790 * Set the timestamp offset for this instance.
609 * 791 *
610 * @param offset the offset to skew the locale time by 792 * @param offset the offset to skew the locale time by
diff --git a/src/json/json_generator.c b/src/json/json_generator.c
index 0c513ca9d..5421b9527 100644
--- a/src/json/json_generator.c
+++ b/src/json/json_generator.c
@@ -27,14 +27,6 @@
27#include "gnunet_json_lib.h" 27#include "gnunet_json_lib.h"
28 28
29 29
30/**
31 * Convert binary data to a JSON string
32 * with the base32crockford encoding.
33 *
34 * @param data binary data
35 * @param size size of @a data in bytes
36 * @return json string that encodes @a data
37 */
38json_t * 30json_t *
39GNUNET_JSON_from_data (const void *data, 31GNUNET_JSON_from_data (const void *data,
40 size_t size) 32 size_t size)
@@ -57,30 +49,30 @@ GNUNET_JSON_from_data (const void *data,
57} 49}
58 50
59 51
60/**
61 * Convert absolute timestamp to a json string.
62 *
63 * @param stamp the time stamp
64 * @return a json string with the timestamp in @a stamp
65 */
66json_t * 52json_t *
67GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp) 53GNUNET_JSON_from_timestamp (struct GNUNET_TIME_Timestamp stamp)
68{ 54{
69 json_t *j; 55 json_t *j;
70 56
71 GNUNET_assert (GNUNET_OK ==
72 GNUNET_TIME_round_abs (&stamp));
73
74 j = json_object (); 57 j = json_object ();
75 if (NULL == j) 58 if (NULL == j)
76 { 59 {
77 GNUNET_break (0); 60 GNUNET_break (0);
78 return NULL; 61 return NULL;
79 } 62 }
80 if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 63 if (GNUNET_TIME_absolute_is_never (stamp.abs_time))
81 { 64 {
82 if (0 != 65 if (0 !=
83 json_object_set_new (j, 66 json_object_set_new (j,
67 "t_s",
68 json_string ("never")))
69 {
70 GNUNET_break (0);
71 json_decref (j);
72 return NULL;
73 }
74 if (0 !=
75 json_object_set_new (j,
84 "t_ms", 76 "t_ms",
85 json_string ("never"))) 77 json_string ("never")))
86 { 78 {
@@ -90,11 +82,29 @@ GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp)
90 } 82 }
91 return j; 83 return j;
92 } 84 }
85 GNUNET_assert (
86 0 ==
87 (stamp.abs_time.abs_value_us
88 % GNUNET_TIME_UNIT_SECONDS.rel_value_us));
93 if (0 != 89 if (0 !=
94 json_object_set_new (j, 90 json_object_set_new (
95 "t_ms", 91 j,
96 json_integer ((json_int_t) (stamp.abs_value_us 92 "t_s",
97 / 1000LL)))) 93 json_integer (
94 (json_int_t) (stamp.abs_time.abs_value_us
95 / GNUNET_TIME_UNIT_SECONDS.rel_value_us))))
96 {
97 GNUNET_break (0);
98 json_decref (j);
99 return NULL;
100 }
101 if (0 !=
102 json_object_set_new (
103 j,
104 "t_ms",
105 json_integer (
106 (json_int_t) (stamp.abs_time.abs_value_us
107 / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us))))
98 { 108 {
99 GNUNET_break (0); 109 GNUNET_break (0);
100 json_decref (j); 110 json_decref (j);
@@ -104,43 +114,37 @@ GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp)
104} 114}
105 115
106 116
107/**
108 * Convert absolute timestamp to a json string.
109 *
110 * @param stamp the time stamp
111 * @return a json string with the timestamp in @a stamp
112 */
113json_t * 117json_t *
114GNUNET_JSON_from_time_abs_nbo (struct GNUNET_TIME_AbsoluteNBO stamp) 118GNUNET_JSON_from_timestamp_nbo (struct GNUNET_TIME_TimestampNBO stamp)
115{ 119{
116 return GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (stamp)); 120 return GNUNET_JSON_from_timestamp (GNUNET_TIME_timestamp_ntoh (stamp));
117} 121}
118 122
119 123
120/**
121 * Convert relative timestamp to a json string.
122 *
123 * @param stamp the time stamp
124 * @return a json string with the timestamp in @a stamp
125 */
126json_t * 124json_t *
127GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp) 125GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
128{ 126{
129 json_t *j; 127 json_t *j;
130 128
131 GNUNET_assert (GNUNET_OK ==
132 GNUNET_TIME_round_rel (&stamp));
133
134 j = json_object (); 129 j = json_object ();
135 if (NULL == j) 130 if (NULL == j)
136 { 131 {
137 GNUNET_break (0); 132 GNUNET_break (0);
138 return NULL; 133 return NULL;
139 } 134 }
140 if (stamp.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) 135 if (GNUNET_TIME_relative_is_forever (stamp))
141 { 136 {
142 if (0 != 137 if (0 !=
143 json_object_set_new (j, 138 json_object_set_new (j,
139 "d_us",
140 json_string ("forever")))
141 {
142 GNUNET_break (0);
143 json_decref (j);
144 return NULL;
145 }
146 if (0 !=
147 json_object_set_new (j,
144 "d_ms", 148 "d_ms",
145 json_string ("forever"))) 149 json_string ("forever")))
146 { 150 {
@@ -150,11 +154,27 @@ GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
150 } 154 }
151 return j; 155 return j;
152 } 156 }
157 if (stamp.rel_value_us >= (1LLU << 53))
158 {
159 /* value is larger than allowed */
160 GNUNET_break (0);
161 return NULL;
162 }
153 if (0 != 163 if (0 !=
154 json_object_set_new (j, 164 json_object_set_new (
155 "d_ms", 165 j,
156 json_integer ((json_int_t) (stamp.rel_value_us 166 "d_us",
157 / 1000LL)))) 167 json_integer ((json_int_t) stamp.rel_value_us)))
168 {
169 GNUNET_break (0);
170 json_decref (j);
171 return NULL;
172 }
173 if (0 !=
174 json_object_set_new (
175 j,
176 "d_ms",
177 json_integer (((json_int_t) stamp.rel_value_us)/1000LL)))
158 { 178 {
159 GNUNET_break (0); 179 GNUNET_break (0);
160 json_decref (j); 180 json_decref (j);
@@ -164,12 +184,6 @@ GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
164} 184}
165 185
166 186
167/**
168 * Convert RSA public key to JSON.
169 *
170 * @param pk public key to convert
171 * @return corresponding JSON encoding
172 */
173json_t * 187json_t *
174GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk) 188GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk)
175{ 189{
@@ -186,12 +200,6 @@ GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk)
186} 200}
187 201
188 202
189/**
190 * Convert RSA signature to JSON.
191 *
192 * @param sig signature to convert
193 * @return corresponding JSON encoding
194 */
195json_t * 203json_t *
196GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig) 204GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig)
197{ 205{
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 3a11f205c..c0513c529 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -49,7 +49,7 @@ GNUNET_JSON_spec_end ()
49 * @param[out] spec where to write the data 49 * @param[out] spec where to write the data
50 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 50 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
51 */ 51 */
52static int 52static enum GNUNET_GenericReturnValue
53parse_fixed_data (void *cls, 53parse_fixed_data (void *cls,
54 json_t *root, 54 json_t *root,
55 struct GNUNET_JSON_Specification *spec) 55 struct GNUNET_JSON_Specification *spec)
@@ -579,19 +579,20 @@ GNUNET_JSON_spec_int64 (const char *name,
579/* ************ GNUnet-specific parser specifications ******************* */ 579/* ************ GNUnet-specific parser specifications ******************* */
580 580
581/** 581/**
582 * Parse given JSON object to absolute time. 582 * Parse given JSON object to a timestamp.
583 * 583 *
584 * @param cls closure, NULL 584 * @param cls closure, NULL
585 * @param root the json object representing data 585 * @param root the json object representing data
586 * @param[out] spec where to write the data 586 * @param[out] spec where to write the data
587 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 587 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
588 */ 588 */
589static int 589static enum GNUNET_GenericReturnValue
590parse_abs_time (void *cls, 590parse_timestamp (void *cls,
591 json_t *root, 591 json_t *root,
592 struct GNUNET_JSON_Specification *spec) 592 struct GNUNET_JSON_Specification *spec)
593{ 593{
594 struct GNUNET_TIME_Absolute *abs = spec->ptr; 594 struct GNUNET_TIME_Timestamp *ts = spec->ptr;
595 json_t *json_t_s;
595 json_t *json_t_ms; 596 json_t *json_t_ms;
596 unsigned long long int tval; 597 unsigned long long int tval;
597 598
@@ -600,13 +601,49 @@ parse_abs_time (void *cls,
600 GNUNET_break_op (0); 601 GNUNET_break_op (0);
601 return GNUNET_SYSERR; 602 return GNUNET_SYSERR;
602 } 603 }
603 json_t_ms = json_object_get (root, "t_ms"); 604 json_t_s = json_object_get (root,
605 "t_s");
606 if (json_is_integer (json_t_s))
607 {
608 tval = json_integer_value (json_t_s);
609 /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
610 ts->abs_time.abs_value_us
611 = tval * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
612 if (ts->abs_time.abs_value_us
613 / GNUNET_TIME_UNIT_SECONDS.rel_value_us
614 != tval)
615 {
616 /* Integer overflow */
617 GNUNET_break_op (0);
618 return GNUNET_SYSERR;
619 }
620 return GNUNET_OK;
621 }
622 if (json_is_string (json_t_s))
623 {
624 const char *val;
625
626 val = json_string_value (json_t_s);
627 if ((0 == strcasecmp (val,
628 "never")))
629 {
630 ts->abs_time = GNUNET_TIME_UNIT_FOREVER_ABS;
631 return GNUNET_OK;
632 }
633 GNUNET_break_op (0);
634 return GNUNET_SYSERR;
635 }
636 json_t_ms = json_object_get (root,
637 "t_ms");
604 if (json_is_integer (json_t_ms)) 638 if (json_is_integer (json_t_ms))
605 { 639 {
606 tval = json_integer_value (json_t_ms); 640 tval = json_integer_value (json_t_ms);
607 /* Time is in milliseconds in JSON, but in microseconds in GNUNET_TIME_Absolute */ 641 GNUNET_break_op (0 == tval % 1000);
608 abs->abs_value_us = tval * GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; 642 tval -= tval % 1000;
609 if ((abs->abs_value_us) 643 /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
644 ts->abs_time.abs_value_us
645 = tval * GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
646 if (ts->abs_time.abs_value_us
610 / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us 647 / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us
611 != tval) 648 != tval)
612 { 649 {
@@ -621,9 +658,10 @@ parse_abs_time (void *cls,
621 const char *val; 658 const char *val;
622 659
623 val = json_string_value (json_t_ms); 660 val = json_string_value (json_t_ms);
624 if ((0 == strcasecmp (val, "never"))) 661 if ((0 == strcasecmp (val,
662 "never")))
625 { 663 {
626 *abs = GNUNET_TIME_UNIT_FOREVER_ABS; 664 ts->abs_time = GNUNET_TIME_UNIT_FOREVER_ABS;
627 return GNUNET_OK; 665 return GNUNET_OK;
628 } 666 }
629 GNUNET_break_op (0); 667 GNUNET_break_op (0);
@@ -635,17 +673,14 @@ parse_abs_time (void *cls,
635 673
636 674
637struct GNUNET_JSON_Specification 675struct GNUNET_JSON_Specification
638GNUNET_JSON_spec_absolute_time (const char *name, 676GNUNET_JSON_spec_timestamp (const char *name,
639 struct GNUNET_TIME_Absolute *at) 677 struct GNUNET_TIME_Timestamp *t)
640{ 678{
641 struct GNUNET_JSON_Specification ret = { 679 struct GNUNET_JSON_Specification ret = {
642 .parser = &parse_abs_time, 680 .parser = &parse_timestamp,
643 .cleaner = NULL,
644 .cls = NULL,
645 .field = name, 681 .field = name,
646 .ptr = at, 682 .ptr = t,
647 .ptr_size = sizeof(struct GNUNET_TIME_Absolute), 683 .ptr_size = sizeof(struct GNUNET_TIME_Timestamp)
648 .size_ptr = NULL
649 }; 684 };
650 685
651 return ret; 686 return ret;
@@ -660,40 +695,37 @@ GNUNET_JSON_spec_absolute_time (const char *name,
660 * @param[out] spec where to write the data 695 * @param[out] spec where to write the data
661 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 696 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
662 */ 697 */
663static int 698static enum GNUNET_GenericReturnValue
664parse_abs_time_nbo (void *cls, 699parse_timestamp_nbo (void *cls,
665 json_t *root, 700 json_t *root,
666 struct GNUNET_JSON_Specification *spec) 701 struct GNUNET_JSON_Specification *spec)
667{ 702{
668 struct GNUNET_TIME_AbsoluteNBO *abs = spec->ptr; 703 struct GNUNET_TIME_TimestampNBO *ts = spec->ptr;
669 struct GNUNET_TIME_Absolute a; 704 struct GNUNET_TIME_Timestamp a;
670 struct GNUNET_JSON_Specification ispec; 705 struct GNUNET_JSON_Specification ispec;
671 706
672 ispec = *spec; 707 ispec = *spec;
673 ispec.parser = &parse_abs_time; 708 ispec.parser = &parse_timestamp;
674 ispec.ptr = &a; 709 ispec.ptr = &a;
675 if (GNUNET_OK != 710 if (GNUNET_OK !=
676 parse_abs_time (NULL, 711 parse_timestamp (NULL,
677 root, 712 root,
678 &ispec)) 713 &ispec))
679 return GNUNET_SYSERR; 714 return GNUNET_SYSERR;
680 *abs = GNUNET_TIME_absolute_hton (a); 715 *ts = GNUNET_TIME_timestamp_hton (a);
681 return GNUNET_OK; 716 return GNUNET_OK;
682} 717}
683 718
684 719
685struct GNUNET_JSON_Specification 720struct GNUNET_JSON_Specification
686GNUNET_JSON_spec_absolute_time_nbo (const char *name, 721GNUNET_JSON_spec_timestamp_nbo (const char *name,
687 struct GNUNET_TIME_AbsoluteNBO *at) 722 struct GNUNET_TIME_TimestampNBO *at)
688{ 723{
689 struct GNUNET_JSON_Specification ret = { 724 struct GNUNET_JSON_Specification ret = {
690 .parser = &parse_abs_time_nbo, 725 .parser = &parse_timestamp_nbo,
691 .cleaner = NULL,
692 .cls = NULL,
693 .field = name, 726 .field = name,
694 .ptr = at, 727 .ptr = at,
695 .ptr_size = sizeof(struct GNUNET_TIME_AbsoluteNBO), 728 .ptr_size = sizeof(struct GNUNET_TIME_TimestampNBO)
696 .size_ptr = NULL
697 }; 729 };
698 730
699 return ret; 731 return ret;
@@ -708,12 +740,13 @@ GNUNET_JSON_spec_absolute_time_nbo (const char *name,
708 * @param[out] spec where to write the data 740 * @param[out] spec where to write the data
709 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 741 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
710 */ 742 */
711static int 743static enum GNUNET_GenericReturnValue
712parse_rel_time (void *cls, 744parse_rel_time (void *cls,
713 json_t *root, 745 json_t *root,
714 struct GNUNET_JSON_Specification *spec) 746 struct GNUNET_JSON_Specification *spec)
715{ 747{
716 struct GNUNET_TIME_Relative *rel = spec->ptr; 748 struct GNUNET_TIME_Relative *rel = spec->ptr;
749 json_t *json_d_us;
717 json_t *json_d_ms; 750 json_t *json_d_ms;
718 unsigned long long int tval; 751 unsigned long long int tval;
719 752
@@ -722,25 +755,52 @@ parse_rel_time (void *cls,
722 GNUNET_break_op (0); 755 GNUNET_break_op (0);
723 return GNUNET_SYSERR; 756 return GNUNET_SYSERR;
724 } 757 }
725 json_d_ms = json_object_get (root, "d_ms"); 758 json_d_us = json_object_get (root,
726 if (json_is_integer (json_d_ms)) 759 "d_us");
760 if (json_is_integer (json_d_us))
727 { 761 {
728 tval = json_integer_value (json_d_ms); 762 tval = json_integer_value (json_d_us);
729 /* Time is in milliseconds in JSON, but in microseconds in GNUNET_TIME_Absolute */ 763 if (tval >= (1LLU << 53))
730 rel->rel_value_us = tval * 1000LL;
731 if ((rel->rel_value_us) / 1000LL != tval)
732 { 764 {
733 /* Integer overflow */ 765 /* value is larger than allowed */
734 GNUNET_break_op (0); 766 GNUNET_break_op (0);
735 return GNUNET_SYSERR; 767 return GNUNET_SYSERR;
736 } 768 }
769 rel->rel_value_us = tval;
770 return GNUNET_OK;
771 }
772 if (json_is_string (json_d_us))
773 {
774 const char *val;
775
776 val = json_string_value (json_d_us);
777 if ((0 == strcasecmp (val,
778 "forever")))
779 {
780 *rel = GNUNET_TIME_UNIT_FOREVER_REL;
781 return GNUNET_OK;
782 }
783 GNUNET_break_op (0);
784 return GNUNET_SYSERR;
785 }
786
787 json_d_ms = json_object_get (root,
788 "d_ms");
789 if (json_is_integer (json_d_ms))
790 {
791 tval = json_integer_value (json_d_ms);
792 *rel = GNUNET_TIME_relative_multiply (
793 GNUNET_TIME_UNIT_MILLISECONDS,
794 tval);
737 return GNUNET_OK; 795 return GNUNET_OK;
738 } 796 }
739 if (json_is_string (json_d_ms)) 797 if (json_is_string (json_d_ms))
740 { 798 {
741 const char *val; 799 const char *val;
800
742 val = json_string_value (json_d_ms); 801 val = json_string_value (json_d_ms);
743 if ((0 == strcasecmp (val, "forever"))) 802 if ((0 == strcasecmp (val,
803 "forever")))
744 { 804 {
745 *rel = GNUNET_TIME_UNIT_FOREVER_REL; 805 *rel = GNUNET_TIME_UNIT_FOREVER_REL;
746 return GNUNET_OK; 806 return GNUNET_OK;
@@ -759,12 +819,9 @@ GNUNET_JSON_spec_relative_time (const char *name,
759{ 819{
760 struct GNUNET_JSON_Specification ret = { 820 struct GNUNET_JSON_Specification ret = {
761 .parser = &parse_rel_time, 821 .parser = &parse_rel_time,
762 .cleaner = NULL,
763 .cls = NULL,
764 .field = name, 822 .field = name,
765 .ptr = rt, 823 .ptr = rt,
766 .ptr_size = sizeof(struct GNUNET_TIME_Relative), 824 .ptr_size = sizeof(struct GNUNET_TIME_Relative)
767 .size_ptr = NULL
768 }; 825 };
769 826
770 return ret; 827 return ret;
@@ -779,7 +836,7 @@ GNUNET_JSON_spec_relative_time (const char *name,
779 * @param[out] spec where to write the data 836 * @param[out] spec where to write the data
780 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 837 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
781 */ 838 */
782static int 839static enum GNUNET_GenericReturnValue
783parse_rsa_public_key (void *cls, 840parse_rsa_public_key (void *cls,
784 json_t *root, 841 json_t *root,
785 struct GNUNET_JSON_Specification *spec) 842 struct GNUNET_JSON_Specification *spec)
@@ -864,7 +921,7 @@ GNUNET_JSON_spec_rsa_public_key (const char *name,
864 * @param[out] spec where to write the data 921 * @param[out] spec where to write the data
865 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 922 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
866 */ 923 */
867static int 924static enum GNUNET_GenericReturnValue
868parse_rsa_signature (void *cls, 925parse_rsa_signature (void *cls,
869 json_t *root, 926 json_t *root,
870 struct GNUNET_JSON_Specification *spec) 927 struct GNUNET_JSON_Specification *spec)
@@ -952,7 +1009,7 @@ GNUNET_JSON_spec_rsa_signature (const char *name,
952 * @param[out] spec where to write the data 1009 * @param[out] spec where to write the data
953 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1010 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
954 */ 1011 */
955static int 1012static enum GNUNET_GenericReturnValue
956parse_boolean (void *cls, 1013parse_boolean (void *cls,
957 json_t *root, 1014 json_t *root,
958 struct GNUNET_JSON_Specification *spec) 1015 struct GNUNET_JSON_Specification *spec)
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index 92f8b4535..296f56104 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -245,16 +245,16 @@ GNUNET_JSON_pack_data_varsize (const char *name,
245 245
246 246
247struct GNUNET_JSON_PackSpec 247struct GNUNET_JSON_PackSpec
248GNUNET_JSON_pack_time_abs (const char *name, 248GNUNET_JSON_pack_timestamp (const char *name,
249 struct GNUNET_TIME_Absolute at) 249 struct GNUNET_TIME_Timestamp t)
250{ 250{
251 struct GNUNET_JSON_PackSpec ps = { 251 struct GNUNET_JSON_PackSpec ps = {
252 .field_name = name 252 .field_name = name
253 }; 253 };
254 254
255 if (0 != at.abs_value_us) 255 if (! GNUNET_TIME_absolute_is_zero (t.abs_time))
256 { 256 {
257 ps.object = GNUNET_JSON_from_time_abs (at); 257 ps.object = GNUNET_JSON_from_timestamp (t);
258 GNUNET_assert (NULL != ps.object); 258 GNUNET_assert (NULL != ps.object);
259 } 259 }
260 else 260 else
@@ -266,11 +266,11 @@ GNUNET_JSON_pack_time_abs (const char *name,
266 266
267 267
268struct GNUNET_JSON_PackSpec 268struct GNUNET_JSON_PackSpec
269GNUNET_JSON_pack_time_abs_nbo (const char *name, 269GNUNET_JSON_pack_timestamp_nbo (const char *name,
270 struct GNUNET_TIME_AbsoluteNBO at) 270 struct GNUNET_TIME_TimestampNBO at)
271{ 271{
272 return GNUNET_JSON_pack_time_abs (name, 272 return GNUNET_JSON_pack_timestamp (name,
273 GNUNET_TIME_absolute_ntoh (at)); 273 GNUNET_TIME_timestamp_ntoh (at));
274} 274}
275 275
276 276
diff --git a/src/json/test_json.c b/src/json/test_json.c
index 4485a37a4..d6c372cf3 100644
--- a/src/json/test_json.c
+++ b/src/json/test_json.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2015, 2016 GNUnet e.V. 3 (C) 2015, 2016, 2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -34,33 +34,44 @@
34 * @return 0 on success 34 * @return 0 on success
35 */ 35 */
36static int 36static int
37test_abs_time () 37test_timestamp (void)
38{ 38{
39 json_t *j; 39 json_t *j;
40 struct GNUNET_TIME_Absolute a1; 40 struct GNUNET_TIME_Absolute a1;
41 struct GNUNET_TIME_Absolute a2; 41 struct GNUNET_TIME_Timestamp t1;
42 struct GNUNET_JSON_Specification s1[] = { GNUNET_JSON_spec_absolute_time ( 42 struct GNUNET_TIME_Timestamp t2;
43 NULL, 43 struct GNUNET_JSON_Specification s1[] = {
44 &a2), 44 GNUNET_JSON_spec_timestamp (NULL,
45 GNUNET_JSON_spec_end () }; 45 &t2),
46 struct GNUNET_JSON_Specification s2[] = { GNUNET_JSON_spec_absolute_time ( 46 GNUNET_JSON_spec_end ()
47 NULL, 47 };
48 &a2), 48 struct GNUNET_JSON_Specification s2[] = {
49 GNUNET_JSON_spec_end () }; 49 GNUNET_JSON_spec_timestamp (NULL,
50 &t2),
51 GNUNET_JSON_spec_end ()
52 };
50 53
51 a1 = GNUNET_TIME_absolute_get (); 54 a1 = GNUNET_TIME_absolute_get ();
52 GNUNET_TIME_round_abs (&a1); 55 t1 = GNUNET_TIME_absolute_to_timestamp (a1);
53 j = GNUNET_JSON_from_time_abs (a1); 56 j = GNUNET_JSON_from_timestamp (t1);
54 GNUNET_assert (NULL != j); 57 GNUNET_assert (NULL != j);
55 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, s1, NULL, NULL)); 58 GNUNET_assert (GNUNET_OK ==
56 GNUNET_assert (a1.abs_value_us == a2.abs_value_us); 59 GNUNET_JSON_parse (j,
60 s1,
61 NULL,
62 NULL));
63 GNUNET_assert (GNUNET_TIME_timestamp_cmp (t1, ==, t2));
57 json_decref (j); 64 json_decref (j);
58 65
59 a1 = GNUNET_TIME_UNIT_FOREVER_ABS; 66 a1 = GNUNET_TIME_UNIT_FOREVER_ABS;
60 j = GNUNET_JSON_from_time_abs (a1); 67 j = GNUNET_JSON_from_timestamp (t1);
61 GNUNET_assert (NULL != j); 68 GNUNET_assert (NULL != j);
62 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, s2, NULL, NULL)); 69 GNUNET_assert (GNUNET_OK ==
63 GNUNET_assert (a1.abs_value_us == a2.abs_value_us); 70 GNUNET_JSON_parse (j,
71 s2,
72 NULL,
73 NULL));
74 GNUNET_assert (GNUNET_TIME_timestamp_cmp (t1, ==, t2));
64 json_decref (j); 75 json_decref (j);
65 return 0; 76 return 0;
66} 77}
@@ -72,19 +83,21 @@ test_abs_time ()
72 * @return 0 on success 83 * @return 0 on success
73 */ 84 */
74static int 85static int
75test_rel_time () 86test_rel_time (void)
76{ 87{
77 json_t *j; 88 json_t *j;
78 struct GNUNET_TIME_Relative r1; 89 struct GNUNET_TIME_Relative r1;
79 struct GNUNET_TIME_Relative r2; 90 struct GNUNET_TIME_Relative r2;
80 struct GNUNET_JSON_Specification s1[] = { GNUNET_JSON_spec_relative_time ( 91 struct GNUNET_JSON_Specification s1[] = {
81 NULL, 92 GNUNET_JSON_spec_relative_time (NULL,
82 &r2), 93 &r2),
83 GNUNET_JSON_spec_end () }; 94 GNUNET_JSON_spec_end ()
84 struct GNUNET_JSON_Specification s2[] = { GNUNET_JSON_spec_relative_time ( 95 };
85 NULL, 96 struct GNUNET_JSON_Specification s2[] = {
86 &r2), 97 GNUNET_JSON_spec_relative_time (NULL,
87 GNUNET_JSON_spec_end () }; 98 &r2),
99 GNUNET_JSON_spec_end ()
100 };
88 101
89 r1 = GNUNET_TIME_UNIT_SECONDS; 102 r1 = GNUNET_TIME_UNIT_SECONDS;
90 j = GNUNET_JSON_from_time_rel (r1); 103 j = GNUNET_JSON_from_time_rel (r1);
@@ -211,7 +224,7 @@ int
211main (int argc, const char *const argv[]) 224main (int argc, const char *const argv[])
212{ 225{
213 GNUNET_log_setup ("test-json", "WARNING", NULL); 226 GNUNET_log_setup ("test-json", "WARNING", NULL);
214 if (0 != test_abs_time ()) 227 if (0 != test_timestamp ())
215 return 1; 228 return 1;
216 if (0 != test_rel_time ()) 229 if (0 != test_rel_time ())
217 return 1; 230 return 1;
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
index a37b1b10b..6b3ffe638 100644
--- a/src/messenger/messenger_api.c
+++ b/src/messenger/messenger_api.c
@@ -253,7 +253,7 @@ handle_recv_message (void *cls,
253 store, context, sender 253 store, context, sender
254 ); 254 );
255 255
256 handle_room_message (room, contact, &message, hash); 256 contact = handle_room_message (room, contact, &message, hash);
257 257
258 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message(room, hash); 258 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message(room, hash);
259 259
diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c
index 7ec9db156..5b13e50ff 100644
--- a/src/namestore/gnunet-namestore-fcfsd.c
+++ b/src/namestore/gnunet-namestore-fcfsd.c
@@ -789,7 +789,11 @@ create_response (void *cls,
789 "message", _ ("unable to process submitted data"), 789 "message", _ ("unable to process submitted data"),
790 NULL); 790 NULL);
791 rd->body_length = strlen (rd->body); 791 rd->body_length = strlen (rd->body);
792#ifdef MHD_HTTP_CONTENT_TOO_LARGE
793 rd->code = MHD_HTTP_CONTENT_TOO_LARGE;
794#else
792 rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE; 795 rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE;
796#endif
793 return MHD_YES; 797 return MHD_YES;
794 case GNUNET_JSON_PR_JSON_INVALID: 798 case GNUNET_JSON_PR_JSON_INVALID:
795 rd->body = make_json ("error", "true", 799 rd->body = make_json ("error", "true",
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c
index 972b3a79d..56014752d 100644
--- a/src/nse/gnunet-service-nse.c
+++ b/src/nse/gnunet-service-nse.c
@@ -505,12 +505,18 @@ get_matching_bits (struct GNUNET_TIME_Absolute timestamp,
505{ 505{
506 struct GNUNET_HashCode timestamp_hash; 506 struct GNUNET_HashCode timestamp_hash;
507 struct GNUNET_HashCode pid_hash; 507 struct GNUNET_HashCode pid_hash;
508 struct GNUNET_HashCode xor;
508 509
509 GNUNET_CRYPTO_hash (&timestamp.abs_value_us, 510 GNUNET_CRYPTO_hash (&timestamp.abs_value_us,
510 sizeof(timestamp.abs_value_us), 511 sizeof(timestamp.abs_value_us),
511 &timestamp_hash); 512 &timestamp_hash);
512 GNUNET_CRYPTO_hash (id, sizeof(struct GNUNET_PeerIdentity), &pid_hash); 513 GNUNET_CRYPTO_hash (id,
513 return GNUNET_CRYPTO_hash_matching_bits (&timestamp_hash, &pid_hash); 514 sizeof(struct GNUNET_PeerIdentity),
515 &pid_hash);
516 GNUNET_CRYPTO_hash_xor (&pid_hash,
517 &timestamp_hash,
518 &xor);
519 return GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
514} 520}
515 521
516 522
@@ -774,24 +780,6 @@ update_flood_message (void *cls)
774 780
775 781
776/** 782/**
777 * Count the leading zeroes in hash.
778 *
779 * @param hash to count leading zeros in
780 * @return the number of leading zero bits.
781 */
782static unsigned int
783count_leading_zeroes (const struct GNUNET_HashCode *hash)
784{
785 unsigned int hash_count;
786
787 hash_count = 0;
788 while (0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count))
789 hash_count++;
790 return hash_count;
791}
792
793
794/**
795 * Check whether the given public key and integer are a valid proof of 783 * Check whether the given public key and integer are a valid proof of
796 * work. 784 * work.
797 * 785 *
@@ -799,7 +787,7 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash)
799 * @param val the integer 787 * @param val the integer
800 * @return #GNUNET_YES if valid, #GNUNET_NO if not 788 * @return #GNUNET_YES if valid, #GNUNET_NO if not
801 */ 789 */
802static int 790static enum GNUNET_GenericReturnValue
803check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, 791check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
804 uint64_t val) 792 uint64_t val)
805{ 793{
@@ -815,8 +803,10 @@ check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
815 buf, 803 buf,
816 sizeof(buf), 804 sizeof(buf),
817 &result); 805 &result);
818 return (count_leading_zeroes (&result) >= nse_work_required) ? GNUNET_YES 806 return (GNUNET_CRYPTO_hash_count_leading_zeros (&result) >=
819 : GNUNET_NO; 807 nse_work_required)
808 ? GNUNET_YES
809 : GNUNET_NO;
820} 810}
821 811
822 812
@@ -877,7 +867,8 @@ find_proof (void *cls)
877 buf, 867 buf,
878 sizeof(buf), 868 sizeof(buf),
879 &result); 869 &result);
880 if (nse_work_required <= count_leading_zeroes (&result)) 870 if (nse_work_required <=
871 GNUNET_CRYPTO_hash_count_leading_zeros (&result))
881 { 872 {
882 my_proof = counter; 873 my_proof = counter;
883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c
index a63d5f14e..5fea994ef 100644
--- a/src/pq/pq_connect.c
+++ b/src/pq/pq_connect.c
@@ -122,6 +122,7 @@ GNUNET_PQ_connect2 (const char *config_str,
122 GNUNET_PQ_reconnect (db); 122 GNUNET_PQ_reconnect (db);
123 if (NULL == db->conn) 123 if (NULL == db->conn)
124 { 124 {
125 GNUNET_CONTAINER_multishortmap_destroy (db->channel_map);
125 GNUNET_free (db->load_path); 126 GNUNET_free (db->load_path);
126 GNUNET_free (db->config_str); 127 GNUNET_free (db->config_str);
127 GNUNET_free (db); 128 GNUNET_free (db);
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index 78c324512..ce8ce8f87 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -70,7 +70,8 @@ struct GNUNET_PQ_QueryParam
70GNUNET_PQ_query_param_null (void) 70GNUNET_PQ_query_param_null (void)
71{ 71{
72 struct GNUNET_PQ_QueryParam res = { 72 struct GNUNET_PQ_QueryParam res = {
73 &qconv_null, NULL, NULL, 0, 1 73 .conv = &qconv_null,
74 .num_params = 1
74 }; 75 };
75 76
76 return res; 77 return res;
@@ -192,7 +193,10 @@ struct GNUNET_PQ_QueryParam
192GNUNET_PQ_query_param_uint16 (const uint16_t *x) 193GNUNET_PQ_query_param_uint16 (const uint16_t *x)
193{ 194{
194 struct GNUNET_PQ_QueryParam res = { 195 struct GNUNET_PQ_QueryParam res = {
195 &qconv_uint16, NULL, x, sizeof(*x), 1 196 .conv = &qconv_uint16,
197 .data = x,
198 .size = sizeof(*x),
199 .num_params = 1
196 }; 200 };
197 201
198 return res; 202 return res;
@@ -246,7 +250,10 @@ struct GNUNET_PQ_QueryParam
246GNUNET_PQ_query_param_uint32 (const uint32_t *x) 250GNUNET_PQ_query_param_uint32 (const uint32_t *x)
247{ 251{
248 struct GNUNET_PQ_QueryParam res = { 252 struct GNUNET_PQ_QueryParam res = {
249 &qconv_uint32, NULL, x, sizeof(*x), 1 253 .conv = &qconv_uint32,
254 .data = x,
255 .size = sizeof(*x),
256 .num_params = 1
250 }; 257 };
251 258
252 return res; 259 return res;
@@ -300,7 +307,10 @@ struct GNUNET_PQ_QueryParam
300GNUNET_PQ_query_param_uint64 (const uint64_t *x) 307GNUNET_PQ_query_param_uint64 (const uint64_t *x)
301{ 308{
302 struct GNUNET_PQ_QueryParam res = { 309 struct GNUNET_PQ_QueryParam res = {
303 &qconv_uint64, NULL, x, sizeof(*x), 1 310 .conv = &qconv_uint64,
311 .data = x,
312 .size = sizeof(*x),
313 .num_params = 1
304 }; 314 };
305 315
306 return res; 316 return res;
@@ -350,11 +360,13 @@ qconv_rsa_public_key (void *cls,
350 360
351 361
352struct GNUNET_PQ_QueryParam 362struct GNUNET_PQ_QueryParam
353GNUNET_PQ_query_param_rsa_public_key (const struct 363GNUNET_PQ_query_param_rsa_public_key (
354 GNUNET_CRYPTO_RsaPublicKey *x) 364 const struct GNUNET_CRYPTO_RsaPublicKey *x)
355{ 365{
356 struct GNUNET_PQ_QueryParam res = { 366 struct GNUNET_PQ_QueryParam res = {
357 &qconv_rsa_public_key, NULL, (x), 0, 1 367 .conv = &qconv_rsa_public_key,
368 .data = x,
369 .num_params = 1
358 }; 370 };
359 371
360 return res; 372 return res;
@@ -407,7 +419,9 @@ struct GNUNET_PQ_QueryParam
407GNUNET_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x) 419GNUNET_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x)
408{ 420{
409 struct GNUNET_PQ_QueryParam res = { 421 struct GNUNET_PQ_QueryParam res = {
410 &qconv_rsa_signature, NULL, (x), 0, 1 422 .conv = &qconv_rsa_signature,
423 .data = x,
424 .num_params = 1
411 }; 425 };
412 426
413 return res; 427 return res;
@@ -463,7 +477,10 @@ struct GNUNET_PQ_QueryParam
463GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x) 477GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x)
464{ 478{
465 struct GNUNET_PQ_QueryParam res = { 479 struct GNUNET_PQ_QueryParam res = {
466 &qconv_rel_time, NULL, x, sizeof(*x), 1 480 .conv = &qconv_rel_time,
481 .data = x,
482 .size = sizeof(*x),
483 .num_params = 1
467 }; 484 };
468 485
469 return res; 486 return res;
@@ -519,7 +536,10 @@ struct GNUNET_PQ_QueryParam
519GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) 536GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
520{ 537{
521 struct GNUNET_PQ_QueryParam res = { 538 struct GNUNET_PQ_QueryParam res = {
522 &qconv_abs_time, NULL, x, sizeof(*x), 1 539 .conv = &qconv_abs_time,
540 .data = x,
541 .size = sizeof(*x),
542 .num_params = 1
523 }; 543 };
524 544
525 return res; 545 return res;
@@ -534,4 +554,19 @@ GNUNET_PQ_query_param_absolute_time_nbo (
534} 554}
535 555
536 556
557struct GNUNET_PQ_QueryParam
558GNUNET_PQ_query_param_timestamp (const struct GNUNET_TIME_Timestamp *x)
559{
560 return GNUNET_PQ_query_param_absolute_time (&x->abs_time);
561}
562
563
564struct GNUNET_PQ_QueryParam
565GNUNET_PQ_query_param_timestamp_nbo (
566 const struct GNUNET_TIME_TimestampNBO *x)
567{
568 return GNUNET_PQ_query_param_absolute_time_nbo (&x->abs_time_nbo);
569}
570
571
537/* end of pq_query_helper.c */ 572/* end of pq_query_helper.c */
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index 4057772ec..2c11f5202 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -757,6 +757,148 @@ GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
757 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) 757 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
758 */ 758 */
759static enum GNUNET_GenericReturnValue 759static enum GNUNET_GenericReturnValue
760extract_timestamp (void *cls,
761 PGresult *result,
762 int row,
763 const char *fname,
764 size_t *dst_size,
765 void *dst)
766{
767 struct GNUNET_TIME_Timestamp *udst = dst;
768 struct GNUNET_TIME_Absolute abs;
769 const int64_t *res;
770 int fnum;
771
772 (void) cls;
773 fnum = PQfnumber (result,
774 fname);
775 if (fnum < 0)
776 {
777 GNUNET_break (0);
778 return GNUNET_SYSERR;
779 }
780 if (PQgetisnull (result,
781 row,
782 fnum))
783 return GNUNET_NO;
784 GNUNET_assert (NULL != dst);
785 if (sizeof(struct GNUNET_TIME_Absolute) != *dst_size)
786 {
787 GNUNET_break (0);
788 return GNUNET_SYSERR;
789 }
790 if (sizeof(int64_t) !=
791 PQgetlength (result,
792 row,
793 fnum))
794 {
795 GNUNET_break (0);
796 return GNUNET_SYSERR;
797 }
798 res = (int64_t *) PQgetvalue (result,
799 row,
800 fnum);
801 if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
802 {
803 abs = GNUNET_TIME_UNIT_FOREVER_ABS;
804 }
805 else
806 {
807 abs.abs_value_us = GNUNET_ntohll ((uint64_t) *res);
808 if (0 != abs.abs_value_us % GNUNET_TIME_UNIT_SECONDS.rel_value_us)
809 {
810 /* timestamps must be multiple of seconds! */
811 GNUNET_break (0);
812 return GNUNET_SYSERR;
813 }
814 }
815 udst->abs_time = abs;
816 return GNUNET_OK;
817}
818
819
820struct GNUNET_PQ_ResultSpec
821GNUNET_PQ_result_spec_timestamp (const char *name,
822 struct GNUNET_TIME_Timestamp *at)
823{
824 struct GNUNET_PQ_ResultSpec res = {
825 .conv = &extract_timestamp,
826 .dst = (void *) at,
827 .dst_size = sizeof(*at),
828 .fname = name
829 };
830
831 return res;
832}
833
834
835/**
836 * Extract data from a Postgres database @a result at row @a row.
837 *
838 * @param cls closure
839 * @param result where to extract data from
840 * @param int row to extract data from
841 * @param fname name (or prefix) of the fields to extract from
842 * @param[in,out] dst_size where to store size of result, may be NULL
843 * @param[out] dst where to store the result
844 * @return
845 * #GNUNET_YES if all results could be extracted
846 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
847 */
848static enum GNUNET_GenericReturnValue
849extract_timestamp_nbo (void *cls,
850 PGresult *result,
851 int row,
852 const char *fname,
853 size_t *dst_size,
854 void *dst)
855{
856 struct GNUNET_TIME_TimestampNBO *udst = dst;
857 struct GNUNET_TIME_Timestamp t;
858 enum GNUNET_GenericReturnValue r;
859
860 r = extract_timestamp (NULL,
861 result,
862 row,
863 fname,
864 dst_size,
865 &t);
866 if (GNUNET_OK != r)
867 return r;
868 *udst = GNUNET_TIME_timestamp_hton (t);
869 return r;
870}
871
872
873struct GNUNET_PQ_ResultSpec
874GNUNET_PQ_result_spec_timestamp_nbo (const char *name,
875 struct GNUNET_TIME_TimestampNBO *at)
876{
877 struct GNUNET_PQ_ResultSpec res = {
878 .conv = &extract_timestamp_nbo,
879 .dst = (void *) at,
880 .dst_size = sizeof(*at),
881 .fname = name
882 };
883
884 return res;
885}
886
887
888/**
889 * Extract data from a Postgres database @a result at row @a row.
890 *
891 * @param cls closure
892 * @param result where to extract data from
893 * @param int row to extract data from
894 * @param fname name (or prefix) of the fields to extract from
895 * @param[in,out] dst_size where to store size of result, may be NULL
896 * @param[out] dst where to store the result
897 * @return
898 * #GNUNET_YES if all results could be extracted
899 * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
900 */
901static enum GNUNET_GenericReturnValue
760extract_uint16 (void *cls, 902extract_uint16 (void *cls,
761 PGresult *result, 903 PGresult *result,
762 int row, 904 int row,
diff --git a/src/regex/plugin_block_regex.c b/src/regex/plugin_block_regex.c
index ad897493f..0953830ab 100644
--- a/src/regex/plugin_block_regex.c
+++ b/src/regex/plugin_block_regex.c
@@ -329,6 +329,222 @@ block_plugin_regex_evaluate (void *cls,
329 329
330 330
331/** 331/**
332 * Function called to validate a query.
333 *
334 * @param cls closure
335 * @param ctx block context
336 * @param type block type
337 * @param query original query (hash)
338 * @param xquery extrended query data (can be NULL, depending on type)
339 * @param xquery_size number of bytes in @a xquery
340 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
341 */
342static enum GNUNET_GenericReturnValue
343block_plugin_regex_check_query (void *cls,
344 enum GNUNET_BLOCK_Type type,
345 const struct GNUNET_HashCode *query,
346 const void *xquery,
347 size_t xquery_size)
348{
349 switch (type)
350 {
351 case GNUNET_BLOCK_TYPE_REGEX:
352 if (0 != xquery_size)
353 {
354 const char *s;
355
356 s = (const char *) xquery;
357 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
358 {
359 GNUNET_break_op (0);
360 return GNUNET_NO;
361 }
362 }
363 return GNUNET_OK;
364 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
365 if (0 != xquery_size)
366 {
367 GNUNET_break_op (0);
368 return GNUNET_NO;
369 }
370 return GNUNET_OK;
371 default:
372 GNUNET_break (0);
373 return GNUNET_SYSERR;
374 }
375}
376
377
378/**
379 * Function called to validate a block for storage.
380 *
381 * @param cls closure
382 * @param type block type
383 * @param query key for the block (hash), must match exactly
384 * @param block block data to validate
385 * @param block_size number of bytes in @a block
386 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
387 */
388static enum GNUNET_GenericReturnValue
389block_plugin_regex_check_block (void *cls,
390 enum GNUNET_BLOCK_Type type,
391 const struct GNUNET_HashCode *query,
392 const void *block,
393 size_t block_size)
394{
395 switch (type)
396 {
397 case GNUNET_BLOCK_TYPE_REGEX:
398 if (GNUNET_SYSERR ==
399 REGEX_BLOCK_check (block,
400 block_size,
401 query,
402 NULL))
403 return GNUNET_NO;
404 return GNUNET_OK;
405 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
406 {
407 const struct RegexAcceptBlock *rba;
408
409 if (sizeof(struct RegexAcceptBlock) != block_size)
410 {
411 GNUNET_break_op (0);
412 return GNUNET_NO;
413 }
414 rba = block;
415 if (ntohl (rba->purpose.size) !=
416 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
417 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
418 + sizeof(struct GNUNET_HashCode))
419 {
420 GNUNET_break_op (0);
421 return GNUNET_NO;
422 }
423 if (GNUNET_TIME_absolute_is_past (GNUNET_TIME_absolute_ntoh (
424 rba->expiration_time)))
425 {
426 return GNUNET_NO;
427 }
428 if (GNUNET_OK !=
429 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT,
430 &rba->purpose,
431 &rba->signature,
432 &rba->peer.public_key))
433 {
434 GNUNET_break_op (0);
435 return GNUNET_NO;
436 }
437 return GNUNET_OK;
438 }
439 default:
440 GNUNET_break (0);
441 return GNUNET_SYSERR;
442 }
443}
444
445
446/**
447 * Function called to validate a reply to a request. Note that it is assumed
448 * that the reply has already been matched to the key (and signatures checked)
449 * as it would be done with the GetKeyFunction and the
450 * BlockEvaluationFunction.
451 *
452 * @param cls closure
453 * @param type block type
454 * @param group which block group to use for evaluation
455 * @param query original query (hash)
456 * @param xquery extrended query data (can be NULL, depending on type)
457 * @param xquery_size number of bytes in @a xquery
458 * @param reply_block response to validate
459 * @param reply_block_size number of bytes in @a reply_block
460 * @return characterization of result
461 */
462static enum GNUNET_BLOCK_ReplyEvaluationResult
463block_plugin_regex_check_reply (
464 void *cls,
465 enum GNUNET_BLOCK_Type type,
466 struct GNUNET_BLOCK_Group *group,
467 const struct GNUNET_HashCode *query,
468 const void *xquery,
469 size_t xquery_size,
470 const void *reply_block,
471 size_t reply_block_size)
472{
473 struct GNUNET_HashCode chash;
474
475 switch (type)
476 {
477 case GNUNET_BLOCK_TYPE_REGEX:
478 if (0 != xquery_size)
479 {
480 const char *s;
481
482 s = (const char *) xquery;
483 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
484 {
485 /* Technically, the query is invalid ... */
486 GNUNET_break (0);
487 return GNUNET_BLOCK_REPLY_INVALID;
488 }
489 }
490 switch (REGEX_BLOCK_check (reply_block,
491 reply_block_size,
492 query,
493 xquery))
494 {
495 case GNUNET_SYSERR:
496 GNUNET_break_op (0);
497 return GNUNET_BLOCK_REPLY_INVALID;
498 case GNUNET_NO:
499 /* xquery mismatch, can happen */
500 return GNUNET_BLOCK_REPLY_IRRELEVANT;
501 default:
502 break;
503 }
504 GNUNET_CRYPTO_hash (reply_block,
505 reply_block_size,
506 &chash);
507 if (GNUNET_YES ==
508 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
509 &chash))
510 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
511 return GNUNET_BLOCK_REPLY_OK_MORE;
512 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
513 {
514 const struct RegexAcceptBlock *rba;
515
516 if (sizeof(struct RegexAcceptBlock) != reply_block_size)
517 {
518 GNUNET_break_op (0);
519 return GNUNET_BLOCK_REPLY_INVALID;
520 }
521 rba = reply_block;
522 if (ntohl (rba->purpose.size) !=
523 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
524 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
525 + sizeof(struct GNUNET_HashCode))
526 {
527 GNUNET_break_op (0);
528 return GNUNET_BLOCK_REPLY_INVALID;
529 }
530 GNUNET_CRYPTO_hash (reply_block,
531 reply_block_size,
532 &chash);
533 if (GNUNET_YES ==
534 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
535 &chash))
536 return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
537 return GNUNET_BLOCK_REPLY_OK_MORE;
538 }
539 default:
540 GNUNET_break (0);
541 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
542 }
543 return GNUNET_BLOCK_REPLY_OK_MORE;
544}
545
546
547/**
332 * Function called to obtain the key for a block. 548 * Function called to obtain the key for a block.
333 * 549 *
334 * @param cls closure 550 * @param cls closure
@@ -339,7 +555,7 @@ block_plugin_regex_evaluate (void *cls,
339 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 555 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
340 * (or if extracting a key from a block of this type does not work) 556 * (or if extracting a key from a block of this type does not work)
341 */ 557 */
342static int 558static enum GNUNET_GenericReturnValue
343block_plugin_regex_get_key (void *cls, 559block_plugin_regex_get_key (void *cls,
344 enum GNUNET_BLOCK_Type type, 560 enum GNUNET_BLOCK_Type type,
345 const void *block, 561 const void *block,
@@ -350,14 +566,14 @@ block_plugin_regex_get_key (void *cls,
350 { 566 {
351 case GNUNET_BLOCK_TYPE_REGEX: 567 case GNUNET_BLOCK_TYPE_REGEX:
352 if (GNUNET_OK != 568 if (GNUNET_OK !=
353 REGEX_BLOCK_get_key (block, block_size, 569 REGEX_BLOCK_get_key (block,
570 block_size,
354 key)) 571 key))
355 { 572 {
356 GNUNET_break_op (0); 573 GNUNET_break_op (0);
357 return GNUNET_NO; 574 return GNUNET_NO;
358 } 575 }
359 return GNUNET_OK; 576 return GNUNET_OK;
360
361 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: 577 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
362 if (sizeof(struct RegexAcceptBlock) != block_size) 578 if (sizeof(struct RegexAcceptBlock) != block_size)
363 { 579 {
@@ -366,7 +582,6 @@ block_plugin_regex_get_key (void *cls,
366 } 582 }
367 *key = ((struct RegexAcceptBlock *) block)->key; 583 *key = ((struct RegexAcceptBlock *) block)->key;
368 return GNUNET_OK; 584 return GNUNET_OK;
369
370 default: 585 default:
371 GNUNET_break (0); 586 GNUNET_break (0);
372 return GNUNET_SYSERR; 587 return GNUNET_SYSERR;
@@ -380,7 +595,7 @@ block_plugin_regex_get_key (void *cls,
380void * 595void *
381libgnunet_plugin_block_regex_init (void *cls) 596libgnunet_plugin_block_regex_init (void *cls)
382{ 597{
383 static enum GNUNET_BLOCK_Type types[] = { 598 static const enum GNUNET_BLOCK_Type types[] = {
384 GNUNET_BLOCK_TYPE_REGEX, 599 GNUNET_BLOCK_TYPE_REGEX,
385 GNUNET_BLOCK_TYPE_REGEX_ACCEPT, 600 GNUNET_BLOCK_TYPE_REGEX_ACCEPT,
386 GNUNET_BLOCK_TYPE_ANY /* end of list */ 601 GNUNET_BLOCK_TYPE_ANY /* end of list */
@@ -390,6 +605,9 @@ libgnunet_plugin_block_regex_init (void *cls)
390 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 605 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
391 api->evaluate = &block_plugin_regex_evaluate; 606 api->evaluate = &block_plugin_regex_evaluate;
392 api->get_key = &block_plugin_regex_get_key; 607 api->get_key = &block_plugin_regex_get_key;
608 api->check_query = &block_plugin_regex_check_query;
609 api->check_block = &block_plugin_regex_check_block;
610 api->check_reply = &block_plugin_regex_check_reply;
393 api->create_group = &block_plugin_regex_create_group; 611 api->create_group = &block_plugin_regex_create_group;
394 api->types = types; 612 api->types = types;
395 return api; 613 return api;
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index 5fe0ade98..4494ade83 100644
--- a/src/revocation/gnunet-service-revocation.c
+++ b/src/revocation/gnunet-service-revocation.c
@@ -169,14 +169,16 @@ new_peer_entry (const struct GNUNET_PeerIdentity *peer)
169 * @return #GNUNET_YES if the message is verified 169 * @return #GNUNET_YES if the message is verified
170 * #GNUNET_NO if the key/signature don't verify 170 * #GNUNET_NO if the key/signature don't verify
171 */ 171 */
172static int 172static enum GNUNET_GenericReturnValue
173verify_revoke_message (const struct RevokeMessage *rm) 173verify_revoke_message (const struct RevokeMessage *rm)
174{ 174{
175 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1]; 175 const struct GNUNET_REVOCATION_PowP *pow
176 if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow, 176 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
177 (unsigned 177
178 int) revocation_work_required, 178 if (GNUNET_YES !=
179 epoch_duration)) 179 GNUNET_REVOCATION_check_pow (pow,
180 (unsigned int) revocation_work_required,
181 epoch_duration))
180 { 182 {
181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
182 "Proof of work invalid!\n"); 184 "Proof of work invalid!\n");
@@ -263,7 +265,7 @@ handle_query_message (void *cls,
263 * @param value our `struct PeerEntry` for the neighbour 265 * @param value our `struct PeerEntry` for the neighbour
264 * @return #GNUNET_OK (continue to iterate) 266 * @return #GNUNET_OK (continue to iterate)
265 */ 267 */
266static int 268static enum GNUNET_GenericReturnValue
267do_flood (void *cls, 269do_flood (void *cls,
268 const struct GNUNET_PeerIdentity *target, 270 const struct GNUNET_PeerIdentity *target,
269 void *value) 271 void *value)
@@ -278,10 +280,12 @@ do_flood (void *cls,
278 but we have no direct CORE 280 but we have no direct CORE
279 connection for flooding */ 281 connection for flooding */
280 e = GNUNET_MQ_msg_extra (cp, 282 e = GNUNET_MQ_msg_extra (cp,
281 htonl (rm->pow_size), 283 htonl (rm->pow_size),
282 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); 284 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
283 *cp = *rm; 285 *cp = *rm;
284 memcpy (&cp[1], &rm[1], htonl (rm->pow_size)); 286 memcpy (&cp[1],
287 &rm[1],
288 htonl (rm->pow_size));
285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
286 "Flooding revocation to `%s'\n", 290 "Flooding revocation to `%s'\n",
287 GNUNET_i2s (target)); 291 GNUNET_i2s (target));
@@ -300,17 +304,18 @@ do_flood (void *cls,
300 * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error, 304 * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error,
301 * #GNUNET_SYSERR if the message was malformed 305 * #GNUNET_SYSERR if the message was malformed
302 */ 306 */
303static int 307static enum GNUNET_GenericReturnValue
304publicize_rm (const struct RevokeMessage *rm) 308publicize_rm (const struct RevokeMessage *rm)
305{ 309{
306 struct RevokeMessage *cp; 310 struct RevokeMessage *cp;
307 struct GNUNET_HashCode hc; 311 struct GNUNET_HashCode hc;
308 struct GNUNET_SETU_Element e; 312 struct GNUNET_SETU_Element e;
309 ssize_t pklen; 313 ssize_t pklen;
310 const struct GNUNET_IDENTITY_PublicKey *pk; 314 const struct GNUNET_REVOCATION_PowP *pow
315 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
316 const struct GNUNET_IDENTITY_PublicKey *pk
317 = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
311 318
312 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
313 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
314 pklen = GNUNET_IDENTITY_key_get_length (pk); 319 pklen = GNUNET_IDENTITY_key_get_length (pk);
315 if (0 > pklen) 320 if (0 > pklen)
316 { 321 {
diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c
index da5882d59..3beae60bb 100644
--- a/src/revocation/plugin_block_revocation.c
+++ b/src/revocation/plugin_block_revocation.c
@@ -34,19 +34,6 @@
34#define DEBUG_REVOCATION GNUNET_EXTRA_LOGGING 34#define DEBUG_REVOCATION GNUNET_EXTRA_LOGGING
35 35
36/** 36/**
37 * Number of bits we set per entry in the bloomfilter.
38 * Do not change!
39 */
40#define BLOOMFILTER_K 16
41
42
43/**
44 * How big is the BF we use for DHT blocks?
45 */
46#define REVOCATION_BF_SIZE 8
47
48
49/**
50 * Context used inside the plugin. 37 * Context used inside the plugin.
51 */ 38 */
52struct InternalContext 39struct InternalContext
@@ -57,54 +44,6 @@ struct InternalContext
57 44
58 45
59/** 46/**
60 * Create a new block group.
61 *
62 * @param ctx block context in which the block group is created
63 * @param type type of the block for which we are creating the group
64 * @param nonce random value used to seed the group creation
65 * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
66 * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
67 * @param va variable arguments specific to @a type
68 * @return block group handle, NULL if block groups are not supported
69 * by this @a type of block (this is not an error)
70 */
71static struct GNUNET_BLOCK_Group *
72block_plugin_revocation_create_group (void *cls,
73 enum GNUNET_BLOCK_Type type,
74 uint32_t nonce,
75 const void *raw_data,
76 size_t raw_data_size,
77 va_list va)
78{
79 unsigned int bf_size;
80 const char *guard;
81
82 guard = va_arg (va, const char *);
83 if (0 == strcmp (guard,
84 "seen-set-size"))
85 bf_size = GNUNET_BLOCK_GROUP_compute_bloomfilter_size (va_arg (va, unsigned
86 int),
87 BLOOMFILTER_K);
88 else if (0 == strcmp (guard,
89 "filter-size"))
90 bf_size = va_arg (va, unsigned int);
91 else
92 {
93 GNUNET_break (0);
94 bf_size = REVOCATION_BF_SIZE;
95 }
96 GNUNET_break (NULL == va_arg (va, const char *));
97 return GNUNET_BLOCK_GROUP_bf_create (cls,
98 bf_size,
99 BLOOMFILTER_K,
100 type,
101 nonce,
102 raw_data,
103 raw_data_size);
104}
105
106
107/**
108 * Function called to validate a reply or a request. For 47 * Function called to validate a reply or a request. For
109 * request evaluation, simply pass "NULL" for the reply_block. 48 * request evaluation, simply pass "NULL" for the reply_block.
110 * 49 *
@@ -133,7 +72,6 @@ block_plugin_revocation_evaluate (void *cls,
133 size_t reply_block_size) 72 size_t reply_block_size)
134{ 73{
135 struct InternalContext *ic = cls; 74 struct InternalContext *ic = cls;
136 struct GNUNET_HashCode chash;
137 ssize_t pklen; 75 ssize_t pklen;
138 const struct RevokeMessage *rm = reply_block; 76 const struct RevokeMessage *rm = reply_block;
139 77
@@ -160,14 +98,134 @@ block_plugin_revocation_evaluate (void *cls,
160 GNUNET_break_op (0); 98 GNUNET_break_op (0);
161 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; 99 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
162 } 100 }
163 GNUNET_CRYPTO_hash (pk, 101 return GNUNET_BLOCK_EVALUATION_OK_LAST;
164 pklen, 102}
165 &chash); 103
166 if (GNUNET_YES == 104
167 GNUNET_BLOCK_GROUP_bf_test_and_set (group, 105/**
168 &chash)) 106 * Function called to validate a query.
169 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; 107 *
170 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; 108 * @param cls closure
109 * @param ctx block context
110 * @param type block type
111 * @param query original query (hash)
112 * @param xquery extrended query data (can be NULL, depending on type)
113 * @param xquery_size number of bytes in @a xquery
114 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
115 */
116static enum GNUNET_GenericReturnValue
117block_plugin_revocation_check_query (void *cls,
118 enum GNUNET_BLOCK_Type type,
119 const struct GNUNET_HashCode *query,
120 const void *xquery,
121 size_t xquery_size)
122{
123 (void) cls;
124 (void) query;
125 (void) xquery;
126 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
127 return GNUNET_SYSERR;
128 if (0 != xquery_size)
129 return GNUNET_NO;
130 return GNUNET_OK;
131}
132
133
134/**
135 * Function called to validate a block for storage.
136 *
137 * @param cls closure
138 * @param type block type
139 * @param query key for the block (hash), must match exactly
140 * @param block block data to validate
141 * @param block_size number of bytes in @a block
142 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
143 */
144static enum GNUNET_GenericReturnValue
145block_plugin_revocation_check_block (void *cls,
146 enum GNUNET_BLOCK_Type type,
147 const struct GNUNET_HashCode *query,
148 const void *block,
149 size_t block_size)
150{
151 struct InternalContext *ic = cls;
152 const struct RevokeMessage *rm = block;
153 const struct GNUNET_REVOCATION_PowP *pow
154 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
155 struct GNUNET_IDENTITY_PublicKey pk;
156 ssize_t pklen;
157 size_t left;
158
159 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
160 return GNUNET_SYSERR;
161 if (block_size < sizeof(*rm) + sizeof(*pow))
162 {
163 GNUNET_break_op (0);
164 return GNUNET_NO;
165 }
166 if (block_size != sizeof(*rm) + ntohl (rm->pow_size))
167 {
168 GNUNET_break_op (0);
169 return GNUNET_NO;
170 }
171 left = block_size - sizeof (*rm) - sizeof (*pow);
172 pklen = GNUNET_IDENTITY_read_key_from_buffer (&pk,
173 &pow[1],
174 left);
175 if (0 > pklen)
176 {
177 GNUNET_break_op (0);
178 return GNUNET_NO;
179 }
180 if (GNUNET_YES !=
181 GNUNET_REVOCATION_check_pow (pow,
182 ic->matching_bits,
183 ic->epoch_duration))
184 {
185 GNUNET_break_op (0);
186 return GNUNET_NO;
187 }
188 return GNUNET_OK;
189}
190
191
192/**
193 * Function called to validate a reply to a request. Note that it is assumed
194 * that the reply has already been matched to the key (and signatures checked)
195 * as it would be done with the GetKeyFunction and the
196 * BlockEvaluationFunction.
197 *
198 * @param cls closure
199 * @param type block type
200 * @param group which block group to use for evaluation
201 * @param query original query (hash)
202 * @param xquery extrended query data (can be NULL, depending on type)
203 * @param xquery_size number of bytes in @a xquery
204 * @param reply_block response to validate
205 * @param reply_block_size number of bytes in @a reply_block
206 * @return characterization of result
207 */
208static enum GNUNET_BLOCK_ReplyEvaluationResult
209block_plugin_revocation_check_reply (
210 void *cls,
211 enum GNUNET_BLOCK_Type type,
212 struct GNUNET_BLOCK_Group *group,
213 const struct GNUNET_HashCode *query,
214 const void *xquery,
215 size_t xquery_size,
216 const void *reply_block,
217 size_t reply_block_size)
218{
219 (void) cls;
220 (void) group;
221 (void) query;
222 (void) xquery;
223 (void) xquery_size;
224 (void) reply_block;
225 (void) reply_block_size;
226 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
227 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
228 return GNUNET_BLOCK_REPLY_OK_LAST;
171} 229}
172 230
173 231
@@ -182,7 +240,7 @@ block_plugin_revocation_evaluate (void *cls,
182 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 240 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
183 * (or if extracting a key from a block of this type does not work) 241 * (or if extracting a key from a block of this type does not work)
184 */ 242 */
185static int 243static enum GNUNET_GenericReturnValue
186block_plugin_revocation_get_key (void *cls, 244block_plugin_revocation_get_key (void *cls,
187 enum GNUNET_BLOCK_Type type, 245 enum GNUNET_BLOCK_Type type,
188 const void *block, 246 const void *block,
@@ -190,24 +248,35 @@ block_plugin_revocation_get_key (void *cls,
190 struct GNUNET_HashCode *key) 248 struct GNUNET_HashCode *key)
191{ 249{
192 const struct RevokeMessage *rm = block; 250 const struct RevokeMessage *rm = block;
193 ssize_t ksize; 251 const struct GNUNET_REVOCATION_PowP *pow
252 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
253 struct GNUNET_IDENTITY_PublicKey pk;
254 ssize_t pklen;
255 size_t left;
194 256
195 if (block_size <= sizeof(*rm)) 257 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
258 return GNUNET_SYSERR;
259 if (block_size < sizeof(*rm) + sizeof(*pow))
196 { 260 {
197 GNUNET_break_op (0); 261 GNUNET_break_op (0);
198 return GNUNET_SYSERR; 262 return GNUNET_NO;
199 } 263 }
200 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1]; 264 if (block_size != sizeof(*rm) + ntohl (rm->pow_size))
201 const struct GNUNET_IDENTITY_PublicKey *pk;
202 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
203 ksize = GNUNET_IDENTITY_key_get_length (pk);
204 if (0 > ksize)
205 { 265 {
206 GNUNET_break_op (0); 266 GNUNET_break_op (0);
207 return GNUNET_SYSERR; 267 return GNUNET_NO;
208 } 268 }
209 GNUNET_CRYPTO_hash (pk, 269 left = block_size - sizeof (*rm) - sizeof (*pow);
210 ksize, 270 pklen = GNUNET_IDENTITY_read_key_from_buffer (&pk,
271 &pow[1],
272 left);
273 if (0 > pklen)
274 {
275 GNUNET_break_op (0);
276 return GNUNET_NO;
277 }
278 GNUNET_CRYPTO_hash (&pow[1],
279 pklen,
211 key); 280 key);
212 return GNUNET_OK; 281 return GNUNET_OK;
213} 282}
@@ -221,8 +290,8 @@ block_plugin_revocation_get_key (void *cls,
221void * 290void *
222libgnunet_plugin_block_revocation_init (void *cls) 291libgnunet_plugin_block_revocation_init (void *cls)
223{ 292{
224 static enum GNUNET_BLOCK_Type types[] = { 293 static const enum GNUNET_BLOCK_Type types[] = {
225 GNUNET_BLOCK_TYPE_REVOCATION, 294 GNUNET_BLOCK_TYPE_REVOCATION,
226 GNUNET_BLOCK_TYPE_ANY /* end of list */ 295 GNUNET_BLOCK_TYPE_ANY /* end of list */
227 }; 296 };
228 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 297 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
@@ -247,7 +316,10 @@ libgnunet_plugin_block_revocation_init (void *cls)
247 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 316 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
248 api->evaluate = &block_plugin_revocation_evaluate; 317 api->evaluate = &block_plugin_revocation_evaluate;
249 api->get_key = &block_plugin_revocation_get_key; 318 api->get_key = &block_plugin_revocation_get_key;
250 api->create_group = &block_plugin_revocation_create_group; 319 api->check_query = &block_plugin_revocation_check_query;
320 api->check_block = &block_plugin_revocation_check_block;
321 api->check_reply = &block_plugin_revocation_check_reply;
322 api->create_group = NULL;
251 api->types = types; 323 api->types = types;
252 ic = GNUNET_new (struct InternalContext); 324 ic = GNUNET_new (struct InternalContext);
253 ic->matching_bits = (unsigned int) matching_bits; 325 ic->matching_bits = (unsigned int) matching_bits;
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index f2b95bafa..d5bd53e56 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -53,7 +53,7 @@ struct GNUNET_REVOCATION_Query
53 53
54/** 54/**
55 * Helper struct that holds a found pow nonce 55 * Helper struct that holds a found pow nonce
56 * and the corresponding number of leading zeroes. 56 * and the corresponding number of leading zeros.
57 */ 57 */
58struct BestPow 58struct BestPow
59{ 59{
@@ -389,27 +389,10 @@ GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h)
389 389
390 390
391/** 391/**
392 * Count the leading zeroes in hash.
393 *
394 * @param hash to count leading zeros in
395 * @return the number of leading zero bits.
396 */
397static unsigned int
398count_leading_zeroes (const struct GNUNET_HashCode *hash)
399{
400 unsigned int hash_count;
401 hash_count = 0;
402 while ((0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count)))
403 hash_count++;
404 return hash_count;
405}
406
407
408/**
409 * Calculate the average zeros in the pows. 392 * Calculate the average zeros in the pows.
410 * 393 *
411 * @param ph the PowHandle 394 * @param ph the PowHandle
412 * @return the average number of zeroes. 395 * @return the average number of zeros.
413 */ 396 */
414static unsigned int 397static unsigned int
415calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph) 398calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph)
@@ -535,7 +518,7 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
535 buf, 518 buf,
536 sizeof(buf), 519 sizeof(buf),
537 &result); 520 &result);
538 tmp_score = count_leading_zeroes (&result); 521 tmp_score = GNUNET_CRYPTO_hash_count_leading_zeros (&result);
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Score %u with %" PRIu64 " (#%u)\n", 523 "Score %u with %" PRIu64 " (#%u)\n",
541 tmp_score, pow_val, i); 524 tmp_score, pow_val, i);
@@ -732,7 +715,7 @@ GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
732 buf, 715 buf,
733 sizeof(buf), 716 sizeof(buf),
734 &result); 717 &result);
735 zeros = count_leading_zeroes (&result); 718 zeros = GNUNET_CRYPTO_hash_count_leading_zeros (&result);
736 for (unsigned int i = 0; i < POW_COUNT; i++) 719 for (unsigned int i = 0; i < POW_COUNT; i++)
737 { 720 {
738 if (pc->best[i].bits < zeros) 721 if (pc->best[i].bits < zeros)
diff --git a/src/set/plugin_block_set_test.c b/src/set/plugin_block_set_test.c
index 1de086092..3d66831bb 100644
--- a/src/set/plugin_block_set_test.c
+++ b/src/set/plugin_block_set_test.c
@@ -66,6 +66,87 @@ block_plugin_set_test_evaluate (void *cls,
66 66
67 67
68/** 68/**
69 * Function called to validate a query.
70 *
71 * @param cls closure
72 * @param ctx block context
73 * @param type block type
74 * @param query original query (hash)
75 * @param xquery extrended query data (can be NULL, depending on type)
76 * @param xquery_size number of bytes in @a xquery
77 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
78 */
79static enum GNUNET_GenericReturnValue
80block_plugin_set_test_check_query (void *cls,
81 enum GNUNET_BLOCK_Type type,
82 const struct GNUNET_HashCode *query,
83 const void *xquery,
84 size_t xquery_size)
85{
86 return GNUNET_OK;
87}
88
89
90/**
91 * Function called to validate a block for storage.
92 *
93 * @param cls closure
94 * @param type block type
95 * @param query key for the block (hash), must match exactly
96 * @param block block data to validate
97 * @param block_size number of bytes in @a block
98 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
99 */
100static enum GNUNET_GenericReturnValue
101block_plugin_set_test_check_block (void *cls,
102 enum GNUNET_BLOCK_Type type,
103 const struct GNUNET_HashCode *query,
104 const void *block,
105 size_t block_size)
106{
107 if ((NULL == block) ||
108 (0 == block_size) ||
109 (0 != ((char *) block)[0]))
110 return GNUNET_SYSERR;
111 return GNUNET_OK;
112}
113
114
115/**
116 * Function called to validate a reply to a request. Note that it is assumed
117 * that the reply has already been matched to the key (and signatures checked)
118 * as it would be done with the GetKeyFunction and the
119 * BlockEvaluationFunction.
120 *
121 * @param cls closure
122 * @param type block type
123 * @param group which block group to use for evaluation
124 * @param query original query (hash)
125 * @param xquery extrended query data (can be NULL, depending on type)
126 * @param xquery_size number of bytes in @a xquery
127 * @param reply_block response to validate
128 * @param reply_block_size number of bytes in @a reply_block
129 * @return characterization of result
130 */
131static enum GNUNET_BLOCK_ReplyEvaluationResult
132block_plugin_set_test_check_reply (void *cls,
133 enum GNUNET_BLOCK_Type type,
134 struct GNUNET_BLOCK_Group *group,
135 const struct GNUNET_HashCode *query,
136 const void *xquery,
137 size_t xquery_size,
138 const void *reply_block,
139 size_t reply_block_size)
140{
141 if ((NULL == reply_block) ||
142 (0 == reply_block_size) ||
143 (0 != ((char *) reply_block)[0]))
144 return GNUNET_BLOCK_REPLY_INVALID;
145 return GNUNET_BLOCK_REPLY_OK_MORE;
146}
147
148
149/**
69 * Function called to obtain the key for a block. 150 * Function called to obtain the key for a block.
70 * 151 *
71 * @param cls closure 152 * @param cls closure
@@ -76,7 +157,7 @@ block_plugin_set_test_evaluate (void *cls,
76 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 157 * @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) 158 * (or if extracting a key from a block of this type does not work)
78 */ 159 */
79static int 160static enum GNUNET_GenericReturnValue
80block_plugin_set_test_get_key (void *cls, 161block_plugin_set_test_get_key (void *cls,
81 enum GNUNET_BLOCK_Type type, 162 enum GNUNET_BLOCK_Type type,
82 const void *block, 163 const void *block,
@@ -93,7 +174,7 @@ block_plugin_set_test_get_key (void *cls,
93void * 174void *
94libgnunet_plugin_block_set_test_init (void *cls) 175libgnunet_plugin_block_set_test_init (void *cls)
95{ 176{
96 static enum GNUNET_BLOCK_Type types[] = { 177 static const enum GNUNET_BLOCK_Type types[] = {
97 GNUNET_BLOCK_TYPE_SET_TEST, 178 GNUNET_BLOCK_TYPE_SET_TEST,
98 GNUNET_BLOCK_TYPE_ANY /* end of list */ 179 GNUNET_BLOCK_TYPE_ANY /* end of list */
99 }; 180 };
@@ -102,6 +183,9 @@ libgnunet_plugin_block_set_test_init (void *cls)
102 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 183 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
103 api->evaluate = &block_plugin_set_test_evaluate; 184 api->evaluate = &block_plugin_set_test_evaluate;
104 api->get_key = &block_plugin_set_test_get_key; 185 api->get_key = &block_plugin_set_test_get_key;
186 api->check_query = &block_plugin_set_test_check_query;
187 api->check_block = &block_plugin_set_test_check_block;
188 api->check_reply = &block_plugin_set_test_check_reply;
105 api->types = types; 189 api->types = types;
106 return api; 190 return api;
107} 191}
diff --git a/src/seti/plugin_block_seti_test.c b/src/seti/plugin_block_seti_test.c
index 55cf31bea..af86e1af6 100644
--- a/src/seti/plugin_block_seti_test.c
+++ b/src/seti/plugin_block_seti_test.c
@@ -66,6 +66,87 @@ block_plugin_seti_test_evaluate (void *cls,
66 66
67 67
68/** 68/**
69 * Function called to validate a query.
70 *
71 * @param cls closure
72 * @param ctx block context
73 * @param type block type
74 * @param query original query (hash)
75 * @param xquery extrended query data (can be NULL, depending on type)
76 * @param xquery_size number of bytes in @a xquery
77 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
78 */
79static enum GNUNET_GenericReturnValue
80block_plugin_seti_test_check_query (void *cls,
81 enum GNUNET_BLOCK_Type type,
82 const struct GNUNET_HashCode *query,
83 const void *xquery,
84 size_t xquery_size)
85{
86 return GNUNET_OK;
87}
88
89
90/**
91 * Function called to validate a block for storage.
92 *
93 * @param cls closure
94 * @param type block type
95 * @param query key for the block (hash), must match exactly
96 * @param block block data to validate
97 * @param block_size number of bytes in @a block
98 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
99 */
100static enum GNUNET_GenericReturnValue
101block_plugin_seti_test_check_block (void *cls,
102 enum GNUNET_BLOCK_Type type,
103 const struct GNUNET_HashCode *query,
104 const void *block,
105 size_t block_size)
106{
107 if ((NULL == block) ||
108 (0 == block_size) ||
109 (0 != ((char *) block)[0]))
110 return GNUNET_SYSERR;
111 return GNUNET_OK;
112}
113
114
115/**
116 * Function called to validate a reply to a request. Note that it is assumed
117 * that the reply has already been matched to the key (and signatures checked)
118 * as it would be done with the GetKeyFunction and the
119 * BlockEvaluationFunction.
120 *
121 * @param cls closure
122 * @param type block type
123 * @param group which block group to use for evaluation
124 * @param query original query (hash)
125 * @param xquery extrended query data (can be NULL, depending on type)
126 * @param xquery_size number of bytes in @a xquery
127 * @param reply_block response to validate
128 * @param reply_block_size number of bytes in @a reply_block
129 * @return characterization of result
130 */
131static enum GNUNET_BLOCK_ReplyEvaluationResult
132block_plugin_seti_test_check_reply (void *cls,
133 enum GNUNET_BLOCK_Type type,
134 struct GNUNET_BLOCK_Group *group,
135 const struct GNUNET_HashCode *query,
136 const void *xquery,
137 size_t xquery_size,
138 const void *reply_block,
139 size_t reply_block_size)
140{
141 if ( (NULL == reply_block) ||
142 (0 == reply_block_size) ||
143 (0 != ((char *) reply_block)[0]) )
144 return GNUNET_BLOCK_REPLY_INVALID;
145 return GNUNET_BLOCK_REPLY_OK_MORE;
146}
147
148
149/**
69 * Function called to obtain the key for a block. 150 * Function called to obtain the key for a block.
70 * 151 *
71 * @param cls closure 152 * @param cls closure
@@ -76,7 +157,7 @@ block_plugin_seti_test_evaluate (void *cls,
76 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 157 * @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) 158 * (or if extracting a key from a block of this type does not work)
78 */ 159 */
79static int 160static enum GNUNET_GenericReturnValue
80block_plugin_seti_test_get_key (void *cls, 161block_plugin_seti_test_get_key (void *cls,
81 enum GNUNET_BLOCK_Type type, 162 enum GNUNET_BLOCK_Type type,
82 const void *block, 163 const void *block,
@@ -102,6 +183,9 @@ libgnunet_plugin_block_seti_test_init (void *cls)
102 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 183 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
103 api->evaluate = &block_plugin_seti_test_evaluate; 184 api->evaluate = &block_plugin_seti_test_evaluate;
104 api->get_key = &block_plugin_seti_test_get_key; 185 api->get_key = &block_plugin_seti_test_get_key;
186 api->check_query = &block_plugin_seti_test_check_query;
187 api->check_block = &block_plugin_seti_test_check_block;
188 api->check_reply = &block_plugin_seti_test_check_reply;
105 api->types = types; 189 api->types = types;
106 return api; 190 return api;
107} 191}
diff --git a/src/setu/plugin_block_setu_test.c b/src/setu/plugin_block_setu_test.c
index fd0c8a680..9872bba39 100644
--- a/src/setu/plugin_block_setu_test.c
+++ b/src/setu/plugin_block_setu_test.c
@@ -66,6 +66,87 @@ block_plugin_setu_test_evaluate (void *cls,
66 66
67 67
68/** 68/**
69 * Function called to validate a query.
70 *
71 * @param cls closure
72 * @param ctx block context
73 * @param type block type
74 * @param query original query (hash)
75 * @param xquery extrended query data (can be NULL, depending on type)
76 * @param xquery_size number of bytes in @a xquery
77 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
78 */
79static enum GNUNET_GenericReturnValue
80block_plugin_setu_test_check_query (void *cls,
81 enum GNUNET_BLOCK_Type type,
82 const struct GNUNET_HashCode *query,
83 const void *xquery,
84 size_t xquery_size)
85{
86 return GNUNET_OK;
87}
88
89
90/**
91 * Function called to validate a block for storage.
92 *
93 * @param cls closure
94 * @param type block type
95 * @param query key for the block (hash), must match exactly
96 * @param block block data to validate
97 * @param block_size number of bytes in @a block
98 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
99 */
100static enum GNUNET_GenericReturnValue
101block_plugin_setu_test_check_block (void *cls,
102 enum GNUNET_BLOCK_Type type,
103 const struct GNUNET_HashCode *query,
104 const void *block,
105 size_t block_size)
106{
107 if ( (NULL == block) ||
108 (0 == block_size) ||
109 (0 != ((char *) block)[0]) )
110 return GNUNET_SYSERR;
111 return GNUNET_OK;
112}
113
114
115/**
116 * Function called to validate a reply to a request. Note that it is assumed
117 * that the reply has already been matched to the key (and signatures checked)
118 * as it would be done with the GetKeyFunction and the
119 * BlockEvaluationFunction.
120 *
121 * @param cls closure
122 * @param type block type
123 * @param group which block group to use for evaluation
124 * @param query original query (hash)
125 * @param xquery extrended query data (can be NULL, depending on type)
126 * @param xquery_size number of bytes in @a xquery
127 * @param reply_block response to validate
128 * @param reply_block_size number of bytes in @a reply_block
129 * @return characterization of result
130 */
131static enum GNUNET_BLOCK_ReplyEvaluationResult
132block_plugin_setu_test_check_reply (void *cls,
133 enum GNUNET_BLOCK_Type type,
134 struct GNUNET_BLOCK_Group *group,
135 const struct GNUNET_HashCode *query,
136 const void *xquery,
137 size_t xquery_size,
138 const void *reply_block,
139 size_t reply_block_size)
140{
141 if ( (NULL == reply_block) ||
142 (0 == reply_block_size) ||
143 (0 != ((char *) reply_block)[0]) )
144 return GNUNET_BLOCK_REPLY_INVALID;
145 return GNUNET_BLOCK_REPLY_OK_MORE;
146}
147
148
149/**
69 * Function called to obtain the key for a block. 150 * Function called to obtain the key for a block.
70 * 151 *
71 * @param cls closure 152 * @param cls closure
@@ -76,7 +157,7 @@ block_plugin_setu_test_evaluate (void *cls,
76 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 157 * @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) 158 * (or if extracting a key from a block of this type does not work)
78 */ 159 */
79static int 160static enum GNUNET_GenericReturnValue
80block_plugin_setu_test_get_key (void *cls, 161block_plugin_setu_test_get_key (void *cls,
81 enum GNUNET_BLOCK_Type type, 162 enum GNUNET_BLOCK_Type type,
82 const void *block, 163 const void *block,
@@ -102,6 +183,9 @@ libgnunet_plugin_block_setu_test_init (void *cls)
102 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 183 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
103 api->evaluate = &block_plugin_setu_test_evaluate; 184 api->evaluate = &block_plugin_setu_test_evaluate;
104 api->get_key = &block_plugin_setu_test_get_key; 185 api->get_key = &block_plugin_setu_test_get_key;
186 api->check_query = &block_plugin_setu_test_check_query;
187 api->check_block = &block_plugin_setu_test_check_block;
188 api->check_reply = &block_plugin_setu_test_check_reply;
105 api->types = types; 189 api->types = types;
106 return api; 190 return api;
107} 191}
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index 2a5e33e2b..3bfdeaa90 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -115,7 +115,7 @@ GNUNET_NETWORK_STRUCT_BEGIN
115struct TcpHandshakeSignature 115struct TcpHandshakeSignature
116{ 116{
117 /** 117 /**
118 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE 118 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
119 */ 119 */
120 struct GNUNET_CRYPTO_EccSignaturePurpose purpose; 120 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
121 121
@@ -153,7 +153,7 @@ struct TcpHandshakeSignature
153struct TcpHandshakeAckSignature 153struct TcpHandshakeAckSignature
154{ 154{
155 /** 155 /**
156 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK 156 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
157 */ 157 */
158 struct GNUNET_CRYPTO_EccSignaturePurpose purpose; 158 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
159 159
@@ -190,7 +190,7 @@ struct TCPConfirmation
190 struct GNUNET_PeerIdentity sender; 190 struct GNUNET_PeerIdentity sender;
191 191
192 /** 192 /**
193 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE 193 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
194 */ 194 */
195 struct GNUNET_CRYPTO_EddsaSignature sender_sig; 195 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
196 196
@@ -225,7 +225,7 @@ struct TCPConfirmationAck
225 struct GNUNET_PeerIdentity sender; 225 struct GNUNET_PeerIdentity sender;
226 226
227 /** 227 /**
228 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK 228 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
229 */ 229 */
230 struct GNUNET_CRYPTO_EddsaSignature sender_sig; 230 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
231 231
@@ -297,7 +297,7 @@ struct TCPRekey
297 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral; 297 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
298 298
299 /** 299 /**
300 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY 300 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
301 */ 301 */
302 struct GNUNET_CRYPTO_EddsaSignature sender_sig; 302 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
303 303
@@ -315,7 +315,7 @@ struct TCPRekey
315struct TcpRekeySignature 315struct TcpRekeySignature
316{ 316{
317 /** 317 /**
318 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY 318 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
319 */ 319 */
320 struct GNUNET_CRYPTO_EccSignaturePurpose purpose; 320 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
321 321
@@ -1313,7 +1313,7 @@ do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1313{ 1313{
1314 struct TcpRekeySignature thp; 1314 struct TcpRekeySignature thp;
1315 1315
1316 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY); 1316 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1317 thp.purpose.size = htonl (sizeof(thp)); 1317 thp.purpose.size = htonl (sizeof(thp));
1318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1318 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1319 "do_rekey size %u\n", 1319 "do_rekey size %u\n",
@@ -1340,7 +1340,7 @@ do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1340 GNUNET_TIME_absolute_ntoh (thp.monotonic_time))); 1340 GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
1341 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp))); 1341 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1342 if (GNUNET_OK != 1342 if (GNUNET_OK !=
1343 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY, 1343 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY,
1344 &thp, 1344 &thp,
1345 &rekey->sender_sig, 1345 &rekey->sender_sig,
1346 &queue->target.public_key)) 1346 &queue->target.public_key))
@@ -1464,7 +1464,7 @@ send_challenge (struct ChallengeNonceP challenge, struct Queue *queue)
1464 tca.monotonic_time = 1464 tca.monotonic_time =
1465 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); 1465 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1466 thas.purpose.purpose = htonl ( 1466 thas.purpose.purpose = htonl (
1467 GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK); 1467 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
1468 thas.purpose.size = htonl (sizeof(thas)); 1468 thas.purpose.size = htonl (sizeof(thas));
1469 thas.sender = my_identity; 1469 thas.sender = my_identity;
1470 thas.receiver = queue->target; 1470 thas.receiver = queue->target;
@@ -1527,7 +1527,7 @@ inject_rekey (struct Queue *queue)
1527 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral, &rekey.ephemeral); 1527 GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral, &rekey.ephemeral);
1528 rekey.monotonic_time = 1528 rekey.monotonic_time =
1529 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); 1529 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
1530 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY); 1530 thp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY);
1531 thp.purpose.size = htonl (sizeof(thp)); 1531 thp.purpose.size = htonl (sizeof(thp));
1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1533 "inject_rekey size %u\n", 1533 "inject_rekey size %u\n",
@@ -1725,7 +1725,7 @@ try_handle_plaintext (struct Queue *queue)
1725 } 1725 }
1726 1726
1727 thas.purpose.purpose = htonl ( 1727 thas.purpose.purpose = htonl (
1728 GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK); 1728 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
1729 thas.purpose.size = htonl (sizeof(thas)); 1729 thas.purpose.size = htonl (sizeof(thas));
1730 thas.sender = tca->sender; 1730 thas.sender = tca->sender;
1731 thas.receiver = my_identity; 1731 thas.receiver = my_identity;
@@ -1733,7 +1733,7 @@ try_handle_plaintext (struct Queue *queue)
1733 thas.challenge = tca->challenge; 1733 thas.challenge = tca->challenge;
1734 1734
1735 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_verify ( 1735 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_verify (
1736 GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK, 1736 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK,
1737 &thas, 1737 &thas,
1738 &tca->sender_sig, 1738 &tca->sender_sig,
1739 &tca->sender.public_key)) 1739 &tca->sender.public_key))
@@ -2472,7 +2472,7 @@ transmit_kx (struct Queue *queue,
2472 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, 2472 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
2473 &tc.challenge, 2473 &tc.challenge,
2474 sizeof(tc.challenge)); 2474 sizeof(tc.challenge));
2475 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE); 2475 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE);
2476 ths.purpose.size = htonl (sizeof(ths)); 2476 ths.purpose.size = htonl (sizeof(ths));
2477 ths.sender = my_identity; 2477 ths.sender = my_identity;
2478 ths.receiver = queue->target; 2478 ths.receiver = queue->target;
@@ -2625,7 +2625,7 @@ decrypt_and_check_tc (struct Queue *queue,
2625 sizeof(*tc), 2625 sizeof(*tc),
2626 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)], 2626 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
2627 sizeof(*tc))); 2627 sizeof(*tc)));
2628 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE); 2628 ths.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE);
2629 ths.purpose.size = htonl (sizeof(ths)); 2629 ths.purpose.size = htonl (sizeof(ths));
2630 ths.sender = tc->sender; 2630 ths.sender = tc->sender;
2631 ths.receiver = my_identity; 2631 ths.receiver = my_identity;
@@ -2633,7 +2633,7 @@ decrypt_and_check_tc (struct Queue *queue,
2633 ths.monotonic_time = tc->monotonic_time; 2633 ths.monotonic_time = tc->monotonic_time;
2634 ths.challenge = tc->challenge; 2634 ths.challenge = tc->challenge;
2635 ret = GNUNET_CRYPTO_eddsa_verify ( 2635 ret = GNUNET_CRYPTO_eddsa_verify (
2636 GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE, 2636 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE,
2637 &ths, 2637 &ths,
2638 &tc->sender_sig, 2638 &tc->sender_sig,
2639 &tc->sender.public_key); 2639 &tc->sender.public_key);
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
index 201e94e80..b6edff485 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -164,7 +164,7 @@ GNUNET_NETWORK_STRUCT_BEGIN
164struct UdpHandshakeSignature 164struct UdpHandshakeSignature
165{ 165{
166 /** 166 /**
167 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE 167 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE
168 */ 168 */
169 struct GNUNET_CRYPTO_EccSignaturePurpose purpose; 169 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
170 170
@@ -227,7 +227,7 @@ struct UDPConfirmation
227 struct GNUNET_PeerIdentity sender; 227 struct GNUNET_PeerIdentity sender;
228 228
229 /** 229 /**
230 * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE 230 * Sender's signature of type #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE
231 */ 231 */
232 struct GNUNET_CRYPTO_EddsaSignature sender_sig; 232 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
233 233
@@ -284,7 +284,7 @@ struct UDPAck
284struct UdpBroadcastSignature 284struct UdpBroadcastSignature
285{ 285{
286 /** 286 /**
287 * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST 287 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST
288 */ 288 */
289 struct GNUNET_CRYPTO_EccSignaturePurpose purpose; 289 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
290 290
@@ -315,7 +315,7 @@ struct UDPBroadcast
315 315
316 /** 316 /**
317 * Sender's signature of type 317 * Sender's signature of type
318 * #GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST 318 * #GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST
319 */ 319 */
320 struct GNUNET_CRYPTO_EddsaSignature sender_sig; 320 struct GNUNET_CRYPTO_EddsaSignature sender_sig;
321}; 321};
@@ -2202,14 +2202,14 @@ verify_confirmation (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
2202{ 2202{
2203 struct UdpHandshakeSignature uhs; 2203 struct UdpHandshakeSignature uhs;
2204 2204
2205 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE); 2205 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE);
2206 uhs.purpose.size = htonl (sizeof(uhs)); 2206 uhs.purpose.size = htonl (sizeof(uhs));
2207 uhs.sender = uc->sender; 2207 uhs.sender = uc->sender;
2208 uhs.receiver = my_identity; 2208 uhs.receiver = my_identity;
2209 uhs.ephemeral = *ephemeral; 2209 uhs.ephemeral = *ephemeral;
2210 uhs.monotonic_time = uc->monotonic_time; 2210 uhs.monotonic_time = uc->monotonic_time;
2211 return GNUNET_CRYPTO_eddsa_verify ( 2211 return GNUNET_CRYPTO_eddsa_verify (
2212 GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE, 2212 GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE,
2213 &uhs, 2213 &uhs,
2214 &uc->sender_sig, 2214 &uc->sender_sig,
2215 &uc->sender.public_key); 2215 &uc->sender.public_key);
@@ -2350,7 +2350,7 @@ sock_read (void *cls)
2350 "received UDPBroadcast from %s\n", 2350 "received UDPBroadcast from %s\n",
2351 GNUNET_a2s ((const struct sockaddr *) addr_verify, salen)); 2351 GNUNET_a2s ((const struct sockaddr *) addr_verify, salen));
2352 ub = (const struct UDPBroadcast *) buf; 2352 ub = (const struct UDPBroadcast *) buf;
2353 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST); 2353 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST);
2354 uhs.purpose.size = htonl (sizeof(uhs)); 2354 uhs.purpose.size = htonl (sizeof(uhs));
2355 uhs.sender = ub->sender; 2355 uhs.sender = ub->sender;
2356 sender = ub->sender; 2356 sender = ub->sender;
@@ -2366,7 +2366,7 @@ sock_read (void *cls)
2366 GNUNET_i2s (&sender)); 2366 GNUNET_i2s (&sender));
2367 GNUNET_CRYPTO_hash ((struct sockaddr *) addr_verify, salen, &uhs.h_address); 2367 GNUNET_CRYPTO_hash ((struct sockaddr *) addr_verify, salen, &uhs.h_address);
2368 if (GNUNET_OK == 2368 if (GNUNET_OK ==
2369 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST, 2369 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST,
2370 &uhs, 2370 &uhs,
2371 &ub->sender_sig, 2371 &ub->sender_sig,
2372 &ub->sender.public_key)) 2372 &ub->sender.public_key))
@@ -2699,7 +2699,7 @@ mq_send_kx (struct GNUNET_MQ_Handle *mq,
2699 uc.sender = my_identity; 2699 uc.sender = my_identity;
2700 uc.monotonic_time = 2700 uc.monotonic_time =
2701 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); 2701 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
2702 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE); 2702 uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_HANDSHAKE);
2703 uhs.purpose.size = htonl (sizeof(uhs)); 2703 uhs.purpose.size = htonl (sizeof(uhs));
2704 uhs.sender = my_identity; 2704 uhs.sender = my_identity;
2705 uhs.receiver = receiver->target; 2705 uhs.receiver = receiver->target;
@@ -3644,7 +3644,7 @@ iface_proc (void *cls,
3644 bi->salen = addrlen; 3644 bi->salen = addrlen;
3645 bi->found = GNUNET_YES; 3645 bi->found = GNUNET_YES;
3646 bi->bcm.sender = my_identity; 3646 bi->bcm.sender = my_identity;
3647 ubs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST); 3647 ubs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_UDP_BROADCAST);
3648 ubs.purpose.size = htonl (sizeof(ubs)); 3648 ubs.purpose.size = htonl (sizeof(ubs));
3649 ubs.sender = my_identity; 3649 ubs.sender = my_identity;
3650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 9fda40f51..406d42b1e 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -144,7 +144,7 @@ libgnunetutil_la_LIBADD = \
144 144
145libgnunetutil_la_LDFLAGS = \ 145libgnunetutil_la_LDFLAGS = \
146 $(GN_LIB_LDFLAGS) \ 146 $(GN_LIB_LDFLAGS) \
147 -version-info 14:0:0 147 -version-info 15:0:0
148 148
149GNUNET_ECC = gnunet-ecc 149GNUNET_ECC = gnunet-ecc
150GNUNET_SCRYPT = gnunet-scrypt 150GNUNET_SCRYPT = gnunet-scrypt
diff --git a/src/util/crypto_cs.c b/src/util/crypto_cs.c
index 5c441b669..c89ba5d83 100644
--- a/src/util/crypto_cs.c
+++ b/src/util/crypto_cs.c
@@ -147,8 +147,8 @@ GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
147 * @param[out] bs array containing the two derived blinding secrets 147 * @param[out] bs array containing the two derived blinding secrets
148 */ 148 */
149void 149void
150GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret, 150GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct
151 size_t secret_len, 151 GNUNET_CRYPTO_CsNonce *blind_seed,
152 struct GNUNET_CRYPTO_CsBlindingSecret 152 struct GNUNET_CRYPTO_CsBlindingSecret
153 bs[2]) 153 bs[2])
154{ 154{
@@ -161,8 +161,8 @@ GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret,
161 GCRY_MD_SHA256, 161 GCRY_MD_SHA256,
162 "alphabeta", 162 "alphabeta",
163 strlen ("alphabeta"), 163 strlen ("alphabeta"),
164 secret, 164 blind_seed,
165 secret_len, 165 sizeof(*blind_seed),
166 NULL, 166 NULL,
167 0)); 167 0));
168 map_to_scalar_subgroup (&bs[0].alpha); 168 map_to_scalar_subgroup (&bs[0].alpha);
diff --git a/src/util/crypto_ecc_setup.c b/src/util/crypto_ecc_setup.c
index f7cd8c6d9..21ce48eef 100644
--- a/src/util/crypto_ecc_setup.c
+++ b/src/util/crypto_ecc_setup.c
@@ -134,8 +134,10 @@ read_from_file (const char *filename,
134 * @param filename name of file to use to store the key 134 * @param filename name of file to use to store the key
135 * @param do_create should a file be created? 135 * @param do_create should a file be created?
136 * @param[out] pkey set to the private key from @a filename on success 136 * @param[out] pkey set to the private key from @a filename on success
137 * @return #GNUNET_OK on success, #GNUNET_NO if @a do_create was set but 137 * @return - #GNUNET_OK on success,
138 * we found an existing file, #GNUNET_SYSERR on failure 138 * - #GNUNET_NO if @a do_create was set but we found an existing file,
139 * - #GNUNET_SYSERR on failure _or_ if the file didn't exist and @a
140 * do_create was not set
139 */ 141 */
140enum GNUNET_GenericReturnValue 142enum GNUNET_GenericReturnValue
141GNUNET_CRYPTO_eddsa_key_from_file (const char *filename, 143GNUNET_CRYPTO_eddsa_key_from_file (const char *filename,
@@ -152,6 +154,11 @@ GNUNET_CRYPTO_eddsa_key_from_file (const char *filename,
152 /* file existed, report that we didn't create it... */ 154 /* file existed, report that we didn't create it... */
153 return (do_create) ? GNUNET_NO : GNUNET_OK; 155 return (do_create) ? GNUNET_NO : GNUNET_OK;
154 } 156 }
157 else if (! do_create)
158 {
159 return GNUNET_SYSERR;
160 }
161
155 GNUNET_CRYPTO_eddsa_key_create (pkey); 162 GNUNET_CRYPTO_eddsa_key_create (pkey);
156 ret = GNUNET_DISK_fn_write (filename, 163 ret = GNUNET_DISK_fn_write (filename,
157 pkey, 164 pkey,
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index d62ec8012..dcd46e5f9 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -135,18 +135,22 @@ GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a,
135 const struct GNUNET_HashCode *b, 135 const struct GNUNET_HashCode *b,
136 struct GNUNET_HashCode *result) 136 struct GNUNET_HashCode *result)
137{ 137{
138 for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(unsigned int)) - 1; 138 const unsigned long long *lla = (const unsigned long long *) a;
139 i >= 0; 139 const unsigned long long *llb = (const unsigned long long *) b;
140 i--) 140 unsigned long long *llr = (unsigned long long *) result;
141 result->bits[i] = a->bits[i] ^ b->bits[i]; 141
142 GNUNET_static_assert (8 == sizeof (unsigned long long));
143 GNUNET_static_assert (0 == sizeof (*a) % sizeof (unsigned long long));
144 for (int i = sizeof (*result) / sizeof (*llr) - 1; i>=0; i--)
145 llr[i] = lla[i] ^ llb[i];
142} 146}
143 147
144 148
145void 149void
146GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc, 150GNUNET_CRYPTO_hash_to_aes_key (
147 struct GNUNET_CRYPTO_SymmetricSessionKey *skey, 151 const struct GNUNET_HashCode *hc,
148 struct 152 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
149 GNUNET_CRYPTO_SymmetricInitializationVector *iv) 153 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
150{ 154{
151 GNUNET_assert (GNUNET_YES == 155 GNUNET_assert (GNUNET_YES ==
152 GNUNET_CRYPTO_kdf ( 156 GNUNET_CRYPTO_kdf (
@@ -167,33 +171,47 @@ GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc,
167} 171}
168 172
169 173
170int 174unsigned int
171GNUNET_CRYPTO_hash_get_bit_ltr (const struct GNUNET_HashCode *code, 175GNUNET_CRYPTO_hash_count_leading_zeros (const struct GNUNET_HashCode *h)
172 unsigned int bit)
173{ 176{
174 GNUNET_assert (bit < 8 * sizeof(struct GNUNET_HashCode)); 177 const unsigned long long *llp = (const unsigned long long *) h;
175 return (((unsigned char *) code)[bit >> 3] & (128 >> (bit & 7))) > 0; 178 unsigned int ret = 0;
176} 179 unsigned int i;
177
178 180
179int 181 GNUNET_static_assert (8 == sizeof (unsigned long long));
180GNUNET_CRYPTO_hash_get_bit_rtl (const struct GNUNET_HashCode *code, 182 GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
181 unsigned int bit) 183 for (i = 0; i<sizeof (*h) / sizeof (*llp); i++)
182{ 184 {
183 GNUNET_assert (bit < 8 * sizeof(struct GNUNET_HashCode)); 185 if (0LLU != llp[i])
184 return (((unsigned char *) code)[bit >> 3] & (1 << (bit & 7))) > 0; 186 break;
187 ret += sizeof (*llp) * 8;
188 }
189 if (ret == 8 * sizeof (*h))
190 return ret;
191 ret += __builtin_clzll (GNUNET_ntohll ((uint64_t) llp[i]));
192 return ret;
185} 193}
186 194
187 195
188unsigned int 196unsigned int
189GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode *first, 197GNUNET_CRYPTO_hash_count_tailing_zeros (const struct GNUNET_HashCode *h)
190 const struct GNUNET_HashCode *second)
191{ 198{
192 for (unsigned int i = 0; i < sizeof(struct GNUNET_HashCode) * 8; i++) 199 const unsigned long long *llp = (const unsigned long long *) h;
193 if (GNUNET_CRYPTO_hash_get_bit_rtl (first, i) != 200 unsigned int ret = 0;
194 GNUNET_CRYPTO_hash_get_bit_rtl (second, i)) 201 int i;
195 return i; 202
196 return sizeof(struct GNUNET_HashCode) * 8; 203 GNUNET_static_assert (8 == sizeof (unsigned long long));
204 GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
205 for (i = sizeof (*h) / sizeof (*llp) - 1; i>=0; i--)
206 {
207 if (0LLU != llp[i])
208 break;
209 ret += sizeof (*llp) * 8;
210 }
211 if (ret == 8 * sizeof (*h))
212 return ret;
213 ret += __builtin_ctzll (GNUNET_ntohll ((uint64_t) llp[i]));
214 return ret;
197} 215}
198 216
199 217
@@ -224,18 +242,19 @@ GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1,
224 const struct GNUNET_HashCode *h2, 242 const struct GNUNET_HashCode *h2,
225 const struct GNUNET_HashCode *target) 243 const struct GNUNET_HashCode *target)
226{ 244{
227 unsigned int d1; 245 const unsigned long long *l1 = (const unsigned long long *) h1;
228 unsigned int d2; 246 const unsigned long long *l2 = (const unsigned long long *) h2;
247 const unsigned long long *t = (const unsigned long long *) target;
229 248
230 for (ssize_t i = sizeof(struct GNUNET_HashCode) / sizeof(unsigned int) - 1; 249 GNUNET_static_assert (0 == sizeof (*h1) % sizeof (*l1));
231 i >= 0; 250 for (size_t i = 0; i < sizeof(*h1) / sizeof(*l1); i++)
232 i--)
233 { 251 {
234 d1 = ((unsigned int *) h1)[i] ^ ((unsigned int *) target)[i]; 252 unsigned long long x1 = l1[i] ^ t[i];
235 d2 = ((unsigned int *) h2)[i] ^ ((unsigned int *) target)[i]; 253 unsigned long long x2 = l2[i] ^ t[i];
236 if (d1 > d2) 254
255 if (x1 > x2)
237 return 1; 256 return 1;
238 else if (d1 < d2) 257 if (x1 < x2)
239 return -1; 258 return -1;
240 } 259 }
241 return 0; 260 return 0;
@@ -243,25 +262,30 @@ GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1,
243 262
244 263
245void 264void
246GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key, 265GNUNET_CRYPTO_hmac_derive_key (
247 const struct 266 struct GNUNET_CRYPTO_AuthKey *key,
248 GNUNET_CRYPTO_SymmetricSessionKey *rkey, 267 const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
249 const void *salt, size_t salt_len, ...) 268 const void *salt, size_t salt_len,
269 ...)
250{ 270{
251 va_list argp; 271 va_list argp;
252 272
253 va_start (argp, salt_len); 273 va_start (argp,
254 GNUNET_CRYPTO_hmac_derive_key_v (key, rkey, salt, salt_len, argp); 274 salt_len);
275 GNUNET_CRYPTO_hmac_derive_key_v (key,
276 rkey,
277 salt, salt_len,
278 argp);
255 va_end (argp); 279 va_end (argp);
256} 280}
257 281
258 282
259void 283void
260GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, 284GNUNET_CRYPTO_hmac_derive_key_v (
261 const struct 285 struct GNUNET_CRYPTO_AuthKey *key,
262 GNUNET_CRYPTO_SymmetricSessionKey *rkey, 286 const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
263 const void *salt, size_t salt_len, 287 const void *salt, size_t salt_len,
264 va_list argp) 288 va_list argp)
265{ 289{
266 GNUNET_CRYPTO_kdf_v (key->key, sizeof(key->key), 290 GNUNET_CRYPTO_kdf_v (key->key, sizeof(key->key),
267 salt, salt_len, 291 salt, salt_len,
@@ -283,7 +307,9 @@ GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len,
283 { 307 {
284 once = 1; 308 once = 1;
285 GNUNET_assert (GPG_ERR_NO_ERROR == 309 GNUNET_assert (GPG_ERR_NO_ERROR ==
286 gcry_md_open (&md, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC)); 310 gcry_md_open (&md,
311 GCRY_MD_SHA512,
312 GCRY_MD_FLAG_HMAC));
287 } 313 }
288 else 314 else
289 { 315 {
@@ -323,15 +349,12 @@ GNUNET_CRYPTO_hash_context_start ()
323 struct GNUNET_HashContext *hc; 349 struct GNUNET_HashContext *hc;
324 350
325 BENCHMARK_START (hash_context_start); 351 BENCHMARK_START (hash_context_start);
326
327 hc = GNUNET_new (struct GNUNET_HashContext); 352 hc = GNUNET_new (struct GNUNET_HashContext);
328 GNUNET_assert (0 == 353 GNUNET_assert (0 ==
329 gcry_md_open (&hc->hd, 354 gcry_md_open (&hc->hd,
330 GCRY_MD_SHA512, 355 GCRY_MD_SHA512,
331 0)); 356 0));
332
333 BENCHMARK_END (hash_context_start); 357 BENCHMARK_END (hash_context_start);
334
335 return hc; 358 return hc;
336} 359}
337 360
diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c
index 592875531..917aa440b 100644
--- a/src/util/getopt_helpers.c
+++ b/src/util/getopt_helpers.c
@@ -38,7 +38,7 @@
38 * @param value not used (NULL) 38 * @param value not used (NULL)
39 * @return #GNUNET_NO (do not continue, not an error) 39 * @return #GNUNET_NO (do not continue, not an error)
40 */ 40 */
41static int 41static enum GNUNET_GenericReturnValue
42print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 42print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
43 void *scls, 43 void *scls,
44 const char *option, 44 const char *option,
@@ -53,12 +53,6 @@ print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
53} 53}
54 54
55 55
56/**
57 * Define the option to print the version of
58 * the application (-v option)
59 *
60 * @param version string with the version number
61 */
62struct GNUNET_GETOPT_CommandLineOption 56struct GNUNET_GETOPT_CommandLineOption
63GNUNET_GETOPT_option_version (const char *version) 57GNUNET_GETOPT_option_version (const char *version)
64{ 58{
@@ -90,7 +84,7 @@ GNUNET_GETOPT_option_version (const char *version)
90 * @param value not used (NULL) 84 * @param value not used (NULL)
91 * @return #GNUNET_NO (do not continue, not an error) 85 * @return #GNUNET_NO (do not continue, not an error)
92 */ 86 */
93static int 87static enum GNUNET_GenericReturnValue
94format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 88format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
95 void *scls, 89 void *scls,
96 const char *option, 90 const char *option,
@@ -192,12 +186,6 @@ OUTER:
192} 186}
193 187
194 188
195/**
196 * Defining the option to print the command line
197 * help text (-h option).
198 *
199 * @param about string with brief description of the application
200 */
201struct GNUNET_GETOPT_CommandLineOption 189struct GNUNET_GETOPT_CommandLineOption
202GNUNET_GETOPT_option_help (const char *about) 190GNUNET_GETOPT_option_help (const char *about)
203{ 191{
@@ -229,7 +217,7 @@ GNUNET_GETOPT_option_help (const char *about)
229 * @param value not used (NULL) 217 * @param value not used (NULL)
230 * @return #GNUNET_OK 218 * @return #GNUNET_OK
231 */ 219 */
232static int 220static enum GNUNET_GenericReturnValue
233increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 221increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
234 void *scls, 222 void *scls,
235 const char *option, 223 const char *option,
@@ -245,15 +233,6 @@ increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
245} 233}
246 234
247 235
248/**
249 * Increment @a val each time the option flag is given by one.
250 *
251 * @param shortName short name of the option
252 * @param name long name of the option
253 * @param argumentHelp help text for the option argument
254 * @param description long help text for the option
255 * @param[out] val increment by 1 each time the option is present
256 */
257struct GNUNET_GETOPT_CommandLineOption 236struct GNUNET_GETOPT_CommandLineOption
258GNUNET_GETOPT_option_increment_uint (char shortName, 237GNUNET_GETOPT_option_increment_uint (char shortName,
259 const char *name, 238 const char *name,
@@ -272,12 +251,6 @@ GNUNET_GETOPT_option_increment_uint (char shortName,
272} 251}
273 252
274 253
275/**
276 * Define the '-V' verbosity option. Using the option more
277 * than once increments @a level each time.
278 *
279 * @param[out] level set to the verbosity level
280 */
281struct GNUNET_GETOPT_CommandLineOption 254struct GNUNET_GETOPT_CommandLineOption
282GNUNET_GETOPT_option_verbose (unsigned int *level) 255GNUNET_GETOPT_option_verbose (unsigned int *level)
283{ 256{
@@ -308,7 +281,7 @@ GNUNET_GETOPT_option_verbose (unsigned int *level)
308 * @param value not used (NULL) 281 * @param value not used (NULL)
309 * @return #GNUNET_OK 282 * @return #GNUNET_OK
310 */ 283 */
311static int 284static enum GNUNET_GenericReturnValue
312set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 285set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
313 void *scls, 286 void *scls,
314 const char *option, 287 const char *option,
@@ -324,16 +297,6 @@ set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
324} 297}
325 298
326 299
327/**
328 * Allow user to specify a flag (which internally means setting
329 * an integer to 1/#GNUNET_YES/#GNUNET_OK.
330 *
331 * @param shortName short name of the option
332 * @param name long name of the option
333 * @param argumentHelp help text for the option argument
334 * @param description long help text for the option
335 * @param[out] val set to 1 if the option is present
336 */
337struct GNUNET_GETOPT_CommandLineOption 300struct GNUNET_GETOPT_CommandLineOption
338GNUNET_GETOPT_option_flag (char shortName, 301GNUNET_GETOPT_option_flag (char shortName,
339 const char *name, 302 const char *name,
@@ -366,7 +329,7 @@ GNUNET_GETOPT_option_flag (char shortName,
366 * @param value actual value of the option (a string) 329 * @param value actual value of the option (a string)
367 * @return #GNUNET_OK 330 * @return #GNUNET_OK
368 */ 331 */
369static int 332static enum GNUNET_GenericReturnValue
370set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 333set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
371 void *scls, 334 void *scls,
372 const char *option, 335 const char *option,
@@ -383,15 +346,6 @@ set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
383} 346}
384 347
385 348
386/**
387 * Allow user to specify a string.
388 *
389 * @param shortName short name of the option
390 * @param name long name of the option
391 * @param argumentHelp help text for the option argument
392 * @param description long help text for the option
393 * @param[out] str set to the string
394 */
395struct GNUNET_GETOPT_CommandLineOption 349struct GNUNET_GETOPT_CommandLineOption
396GNUNET_GETOPT_option_string (char shortName, 350GNUNET_GETOPT_option_string (char shortName,
397 const char *name, 351 const char *name,
@@ -413,12 +367,6 @@ GNUNET_GETOPT_option_string (char shortName,
413} 367}
414 368
415 369
416/**
417 * Define the '-L' log level option. Note that we do not check
418 * that the log level is valid here.
419 *
420 * @param[out] level set to the log level
421 */
422struct GNUNET_GETOPT_CommandLineOption 370struct GNUNET_GETOPT_CommandLineOption
423GNUNET_GETOPT_option_loglevel (char **level) 371GNUNET_GETOPT_option_loglevel (char **level)
424{ 372{
@@ -447,7 +395,7 @@ GNUNET_GETOPT_option_loglevel (char **level)
447 * @param value actual value of the option (a string) 395 * @param value actual value of the option (a string)
448 * @return #GNUNET_OK 396 * @return #GNUNET_OK
449 */ 397 */
450static int 398static enum GNUNET_GenericReturnValue
451set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 399set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
452 void *scls, 400 void *scls,
453 const char *option, 401 const char *option,
@@ -464,15 +412,6 @@ set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
464} 412}
465 413
466 414
467/**
468 * Allow user to specify a filename (automatically path expanded).
469 *
470 * @param shortName short name of the option
471 * @param name long name of the option
472 * @param argumentHelp help text for the option argument
473 * @param description long help text for the option
474 * @param[out] str set to the string
475 */
476struct GNUNET_GETOPT_CommandLineOption 415struct GNUNET_GETOPT_CommandLineOption
477GNUNET_GETOPT_option_filename (char shortName, 416GNUNET_GETOPT_option_filename (char shortName,
478 const char *name, 417 const char *name,
@@ -494,11 +433,6 @@ GNUNET_GETOPT_option_filename (char shortName,
494} 433}
495 434
496 435
497/**
498 * Allow user to specify log file name (-l option)
499 *
500 * @param[out] logfn set to the name of the logfile
501 */
502struct GNUNET_GETOPT_CommandLineOption 436struct GNUNET_GETOPT_CommandLineOption
503GNUNET_GETOPT_option_logfile (char **logfn) 437GNUNET_GETOPT_option_logfile (char **logfn)
504{ 438{
@@ -517,11 +451,6 @@ GNUNET_GETOPT_option_logfile (char **logfn)
517} 451}
518 452
519 453
520/**
521 * Allow user to specify configuration file name (-c option)
522 *
523 * @param[out] fn set to the name of the configuration file
524 */
525struct GNUNET_GETOPT_CommandLineOption 454struct GNUNET_GETOPT_CommandLineOption
526GNUNET_GETOPT_option_cfgfile (char **fn) 455GNUNET_GETOPT_option_cfgfile (char **fn)
527{ 456{
@@ -552,7 +481,7 @@ GNUNET_GETOPT_option_cfgfile (char **fn)
552 * @param value actual value of the option as a string. 481 * @param value actual value of the option as a string.
553 * @return #GNUNET_OK if parsing the value worked 482 * @return #GNUNET_OK if parsing the value worked
554 */ 483 */
555static int 484static enum GNUNET_GenericReturnValue
556set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 485set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
557 void *scls, 486 void *scls,
558 const char *option, 487 const char *option,
@@ -573,15 +502,6 @@ set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
573} 502}
574 503
575 504
576/**
577 * Allow user to specify an `unsigned long long`
578 *
579 * @param shortName short name of the option
580 * @param name long name of the option
581 * @param argumentHelp help text for the option argument
582 * @param description long help text for the option
583 * @param[out] val set to the value specified at the command line
584 */
585struct GNUNET_GETOPT_CommandLineOption 505struct GNUNET_GETOPT_CommandLineOption
586GNUNET_GETOPT_option_ulong (char shortName, 506GNUNET_GETOPT_option_ulong (char shortName,
587 const char *name, 507 const char *name,
@@ -616,7 +536,7 @@ GNUNET_GETOPT_option_ulong (char shortName,
616 * @param value actual value of the option as a string. 536 * @param value actual value of the option as a string.
617 * @return #GNUNET_OK if parsing the value worked 537 * @return #GNUNET_OK if parsing the value worked
618 */ 538 */
619static int 539static enum GNUNET_GenericReturnValue
620set_timetravel_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 540set_timetravel_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
621 void *scls, 541 void *scls,
622 const char *option, 542 const char *option,
@@ -664,15 +584,6 @@ set_timetravel_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
664} 584}
665 585
666 586
667/**
668 * Allow user to specify a `long long` with an offset to add to the current
669 * system time to construct the time seen by the application. Used for
670 * debugging / testing.
671 *
672 * @param shortName short name of the option
673 * @param name long name of the option
674 * @param[out] val set to the time specified at the command line
675 */
676struct GNUNET_GETOPT_CommandLineOption 587struct GNUNET_GETOPT_CommandLineOption
677GNUNET_GETOPT_option_timetravel (char shortName, 588GNUNET_GETOPT_option_timetravel (char shortName,
678 const char *name) 589 const char *name)
@@ -684,8 +595,7 @@ GNUNET_GETOPT_option_timetravel (char shortName,
684 .description = _ ( 595 .description = _ (
685 "modify system time by given offset (for debugging/testing only)"), 596 "modify system time by given offset (for debugging/testing only)"),
686 .require_argument = 1, 597 .require_argument = 1,
687 .processor = 598 .processor = &set_timetravel_time
688 &set_timetravel_time
689 }; 599 };
690 600
691 return clo; 601 return clo;
@@ -705,7 +615,7 @@ GNUNET_GETOPT_option_timetravel (char shortName,
705 * @param value actual value of the option as a string. 615 * @param value actual value of the option as a string.
706 * @return #GNUNET_OK if parsing the value worked 616 * @return #GNUNET_OK if parsing the value worked
707 */ 617 */
708static int 618static enum GNUNET_GenericReturnValue
709set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 619set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
710 void *scls, 620 void *scls,
711 const char *option, 621 const char *option,
@@ -725,16 +635,6 @@ set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
725} 635}
726 636
727 637
728/**
729 * Allow user to specify a `struct GNUNET_TIME_Relative`
730 * (using human-readable "fancy" time).
731 *
732 * @param shortName short name of the option
733 * @param name long name of the option
734 * @param argumentHelp help text for the option argument
735 * @param description long help text for the option
736 * @param[out] val set to the time specified at the command line
737 */
738struct GNUNET_GETOPT_CommandLineOption 638struct GNUNET_GETOPT_CommandLineOption
739GNUNET_GETOPT_option_relative_time (char shortName, 639GNUNET_GETOPT_option_relative_time (char shortName,
740 const char *name, 640 const char *name,
@@ -748,8 +648,7 @@ GNUNET_GETOPT_option_relative_time (char shortName,
748 .argumentHelp = argumentHelp, 648 .argumentHelp = argumentHelp,
749 .description = description, 649 .description = description,
750 .require_argument = 1, 650 .require_argument = 1,
751 .processor = 651 .processor = &set_relative_time,
752 &set_relative_time,
753 .scls = (void *) val 652 .scls = (void *) val
754 }; 653 };
755 654
@@ -770,7 +669,7 @@ GNUNET_GETOPT_option_relative_time (char shortName,
770 * @param value actual value of the option as a string. 669 * @param value actual value of the option as a string.
771 * @return #GNUNET_OK if parsing the value worked 670 * @return #GNUNET_OK if parsing the value worked
772 */ 671 */
773static int 672static enum GNUNET_GenericReturnValue
774set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 673set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
775 void *scls, 674 void *scls,
776 const char *option, 675 const char *option,
@@ -790,16 +689,6 @@ set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
790} 689}
791 690
792 691
793/**
794 * Allow user to specify a `struct GNUNET_TIME_Absolute`
795 * (using human-readable "fancy" time).
796 *
797 * @param shortName short name of the option
798 * @param name long name of the option
799 * @param argumentHelp help text for the option argument
800 * @param description long help text for the option
801 * @param[out] val set to the time specified at the command line
802 */
803struct GNUNET_GETOPT_CommandLineOption 692struct GNUNET_GETOPT_CommandLineOption
804GNUNET_GETOPT_option_absolute_time (char shortName, 693GNUNET_GETOPT_option_absolute_time (char shortName,
805 const char *name, 694 const char *name,
@@ -813,8 +702,71 @@ GNUNET_GETOPT_option_absolute_time (char shortName,
813 .argumentHelp = argumentHelp, 702 .argumentHelp = argumentHelp,
814 .description = description, 703 .description = description,
815 .require_argument = 1, 704 .require_argument = 1,
816 .processor = 705 .processor = &set_absolute_time,
817 &set_absolute_time, 706 .scls = (void *) val
707 };
708
709 return clo;
710}
711
712
713/**
714 * Set an option of type 'struct GNUNET_TIME_Timestamp' from the command line.
715 * A pointer to this function should be passed as part of the
716 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
717 * of this type. It should be followed by a pointer to a value of
718 * type 'struct GNUNET_TIME_Absolute'.
719 *
720 * @param ctx command line processing context
721 * @param scls additional closure (will point to the `struct GNUNET_TIME_Absolute`)
722 * @param option name of the option
723 * @param value actual value of the option as a string.
724 * @return #GNUNET_OK if parsing the value worked
725 */
726static enum GNUNET_GenericReturnValue
727set_timestamp (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
728 void *scls,
729 const char *option,
730 const char *value)
731{
732 struct GNUNET_TIME_Timestamp *t = scls;
733 struct GNUNET_TIME_Absolute abs;
734
735 (void) ctx;
736 if (GNUNET_OK !=
737 GNUNET_STRINGS_fancy_time_to_absolute (value,
738 &abs))
739 {
740 fprintf (stderr,
741 _ ("You must pass a timestamp to the `%s' option.\n"),
742 option);
743 return GNUNET_SYSERR;
744 }
745 if (0 != abs.abs_value_us % GNUNET_TIME_UNIT_SECONDS.rel_value_us)
746 {
747 fprintf (stderr,
748 _ ("The maximum precision allowed for timestamps is seconds.\n"));
749 return GNUNET_SYSERR;
750 }
751 t->abs_time = abs;
752 return GNUNET_OK;
753}
754
755
756struct GNUNET_GETOPT_CommandLineOption
757GNUNET_GETOPT_option_timestamp (char shortName,
758 const char *name,
759 const char *argumentHelp,
760 const char *description,
761 struct GNUNET_TIME_Timestamp *val)
762{
763 struct GNUNET_GETOPT_CommandLineOption clo = {
764 .shortName = shortName,
765 .name = name,
766 .argumentHelp = argumentHelp,
767 .description = description,
768 .require_argument = 1,
769 .processor = &set_timestamp,
818 .scls = (void *) val 770 .scls = (void *) val
819 }; 771 };
820 772
@@ -835,7 +787,7 @@ GNUNET_GETOPT_option_absolute_time (char shortName,
835 * @param value actual value of the option as a string. 787 * @param value actual value of the option as a string.
836 * @return #GNUNET_OK if parsing the value worked 788 * @return #GNUNET_OK if parsing the value worked
837 */ 789 */
838static int 790static enum GNUNET_GenericReturnValue
839set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 791set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
840 void *scls, 792 void *scls,
841 const char *option, 793 const char *option,
@@ -864,15 +816,6 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
864} 816}
865 817
866 818
867/**
868 * Allow user to specify an unsigned integer.
869 *
870 * @param shortName short name of the option
871 * @param name long name of the option
872 * @param argumentHelp help text for the option argument
873 * @param description long help text for the option
874 * @param[out] val set to the value specified at the command line
875 */
876struct GNUNET_GETOPT_CommandLineOption 819struct GNUNET_GETOPT_CommandLineOption
877GNUNET_GETOPT_option_uint (char shortName, 820GNUNET_GETOPT_option_uint (char shortName,
878 const char *name, 821 const char *name,
@@ -907,7 +850,7 @@ GNUNET_GETOPT_option_uint (char shortName,
907 * @param value actual value of the option as a string. 850 * @param value actual value of the option as a string.
908 * @return #GNUNET_OK if parsing the value worked 851 * @return #GNUNET_OK if parsing the value worked
909 */ 852 */
910static int 853static enum GNUNET_GenericReturnValue
911set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 854set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
912 void *scls, 855 void *scls,
913 const char *option, 856 const char *option,
@@ -938,15 +881,6 @@ set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
938} 881}
939 882
940 883
941/**
942 * Allow user to specify an uint16_t.
943 *
944 * @param shortName short name of the option
945 * @param name long name of the option
946 * @param argumentHelp help text for the option argument
947 * @param description long help text for the option
948 * @param[out] val set to the value specified at the command line
949 */
950struct GNUNET_GETOPT_CommandLineOption 884struct GNUNET_GETOPT_CommandLineOption
951GNUNET_GETOPT_option_uint16 (char shortName, 885GNUNET_GETOPT_option_uint16 (char shortName,
952 const char *name, 886 const char *name,
@@ -998,7 +932,7 @@ struct Base32Context
998 * @param value actual value of the option as a string. 932 * @param value actual value of the option as a string.
999 * @return #GNUNET_OK if parsing the value worked 933 * @return #GNUNET_OK if parsing the value worked
1000 */ 934 */
1001static int 935static enum GNUNET_GenericReturnValue
1002set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, 936set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
1003 void *scls, 937 void *scls,
1004 const char *option, 938 const char *option,
@@ -1036,17 +970,6 @@ free_bc (void *cls)
1036} 970}
1037 971
1038 972
1039/**
1040 * Allow user to specify a binary value using Crockford
1041 * Base32 encoding.
1042 *
1043 * @param shortName short name of the option
1044 * @param name long name of the option
1045 * @param argumentHelp help text for the option argument
1046 * @param description long help text for the option
1047 * @param[out] val binary value decoded from Crockford Base32-encoded argument
1048 * @param val_size size of @a val in bytes
1049 */
1050struct GNUNET_GETOPT_CommandLineOption 973struct GNUNET_GETOPT_CommandLineOption
1051GNUNET_GETOPT_option_base32_fixed_size (char shortName, 974GNUNET_GETOPT_option_base32_fixed_size (char shortName,
1052 const char *name, 975 const char *name,
@@ -1073,12 +996,6 @@ GNUNET_GETOPT_option_base32_fixed_size (char shortName,
1073} 996}
1074 997
1075 998
1076/**
1077 * Make the given option mandatory.
1078 *
1079 * @param opt option to modify
1080 * @return @a opt with the mandatory flag set.
1081 */
1082struct GNUNET_GETOPT_CommandLineOption 999struct GNUNET_GETOPT_CommandLineOption
1083GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt) 1000GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
1084{ 1001{
@@ -1087,12 +1004,6 @@ GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
1087} 1004}
1088 1005
1089 1006
1090/**
1091 * Make the given option mutually exclusive with other options.
1092 *
1093 * @param opt option to modify
1094 * @return @a opt with the exclusive flag set.
1095 */
1096struct GNUNET_GETOPT_CommandLineOption 1007struct GNUNET_GETOPT_CommandLineOption
1097GNUNET_GETOPT_option_exclusive (struct GNUNET_GETOPT_CommandLineOption opt) 1008GNUNET_GETOPT_option_exclusive (struct GNUNET_GETOPT_CommandLineOption opt)
1098{ 1009{
diff --git a/src/util/gnunet-scrypt.c b/src/util/gnunet-scrypt.c
index fe8b6769f..ad46e3f39 100644
--- a/src/util/gnunet-scrypt.c
+++ b/src/util/gnunet-scrypt.c
@@ -78,24 +78,6 @@ shutdown_task (void *cls)
78 78
79 79
80/** 80/**
81 * Count the leading zeroes in hash.
82 *
83 * @param hash to count leading zeros in
84 * @return the number of leading zero bits.
85 */
86static unsigned int
87count_leading_zeroes (const struct GNUNET_HashCode *hash)
88{
89 unsigned int hash_count;
90
91 hash_count = 0;
92 while (0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count))
93 hash_count++;
94 return hash_count;
95}
96
97
98/**
99 * Find our proof of work. 81 * Find our proof of work.
100 * 82 *
101 * @param cls closure (unused) 83 * @param cls closure (unused)
@@ -131,7 +113,8 @@ find_proof (void *cls)
131 buf, 113 buf,
132 sizeof(buf), 114 sizeof(buf),
133 &result); 115 &result);
134 if (nse_work_required <= count_leading_zeroes (&result)) 116 if (nse_work_required <=
117 GNUNET_CRYPTO_hash_count_leading_zeros (&result))
135 { 118 {
136 proof = counter; 119 proof = counter;
137 fprintf (stdout, 120 fprintf (stdout,
diff --git a/src/util/perf_crypto_cs.c b/src/util/perf_crypto_cs.c
index a8c72052b..54c9c8e0e 100644
--- a/src/util/perf_crypto_cs.c
+++ b/src/util/perf_crypto_cs.c
@@ -103,8 +103,6 @@ eval ()
103 for (i = 0; i < ITER; i++) 103 for (i = 0; i < ITER; i++)
104 { 104 {
105 GNUNET_CRYPTO_cs_blinding_secrets_derive (&nonce, 105 GNUNET_CRYPTO_cs_blinding_secrets_derive (&nonce,
106 sizeof(struct
107 GNUNET_CRYPTO_CsNonce),
108 bs); 106 bs);
109 } 107 }
110 printf ("10x derive blinding secrets took %s\n", 108 printf ("10x derive blinding secrets took %s\n",
@@ -167,9 +165,9 @@ eval ()
167 for (i = 0; i < ITER; i++) 165 for (i = 0; i < ITER; i++)
168 { 166 {
169 GNUNET_CRYPTO_cs_verify (&sig, 167 GNUNET_CRYPTO_cs_verify (&sig,
170 &pub, 168 &pub,
171 message, 169 message,
172 message_len); 170 message_len);
173 } 171 }
174 printf ("10x verifying signatures took %s\n", 172 printf ("10x verifying signatures took %s\n",
175 GNUNET_STRINGS_relative_time_to_string ( 173 GNUNET_STRINGS_relative_time_to_string (
diff --git a/src/util/perf_crypto_rsa.c b/src/util/perf_crypto_rsa.c
index aba61786f..a3e041bdf 100644
--- a/src/util/perf_crypto_rsa.c
+++ b/src/util/perf_crypto_rsa.c
@@ -203,6 +203,7 @@ main (int argc, char *argv[])
203{ 203{
204 eval (1024); 204 eval (1024);
205 eval (2048); 205 eval (2048);
206 eval (3072);
206 /* eval (4096); */ 207 /* eval (4096); */
207 return 0; 208 return 0;
208} 209}
diff --git a/src/util/strings.c b/src/util/strings.c
index 673915888..db672da87 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -201,7 +201,7 @@ struct ConversionTable
201 * @param output where to store the result 201 * @param output where to store the result
202 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 202 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
203 */ 203 */
204static int 204static enum GNUNET_GenericReturnValue
205convert_with_table (const char *input, 205convert_with_table (const char *input,
206 const struct ConversionTable *table, 206 const struct ConversionTable *table,
207 unsigned long long *output) 207 unsigned long long *output)
@@ -256,7 +256,7 @@ convert_with_table (const char *input,
256} 256}
257 257
258 258
259int 259enum GNUNET_GenericReturnValue
260GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size, 260GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
261 unsigned long long *size) 261 unsigned long long *size)
262{ 262{
@@ -280,7 +280,7 @@ GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
280} 280}
281 281
282 282
283int 283enum GNUNET_GenericReturnValue
284GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, 284GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
285 struct GNUNET_TIME_Relative *rtime) 285 struct GNUNET_TIME_Relative *rtime)
286{ 286{
@@ -322,7 +322,7 @@ GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
322} 322}
323 323
324 324
325int 325enum GNUNET_GenericReturnValue
326GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time, 326GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
327 struct GNUNET_TIME_Absolute *atime) 327 struct GNUNET_TIME_Absolute *atime)
328{ 328{
@@ -354,6 +354,15 @@ GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
354} 354}
355 355
356 356
357enum GNUNET_GenericReturnValue
358GNUNET_STRINGS_fancy_time_to_timestamp (const char *fancy_time,
359 struct GNUNET_TIME_Timestamp *atime)
360{
361 return GNUNET_STRINGS_fancy_time_to_absolute (fancy_time,
362 &atime->abs_time);
363}
364
365
357char * 366char *
358GNUNET_STRINGS_conv (const char *input, 367GNUNET_STRINGS_conv (const char *input,
359 size_t len, 368 size_t len,
@@ -607,7 +616,7 @@ GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t)
607 time_t tt; 616 time_t tt;
608 struct tm *tp; 617 struct tm *tp;
609 618
610 if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 619 if (GNUNET_TIME_absolute_is_never (t))
611 return "end of time"; 620 return "end of time";
612 tt = t.abs_value_us / 1000LL / 1000LL; 621 tt = t.abs_value_us / 1000LL / 1000LL;
613 tp = localtime (&tt); 622 tp = localtime (&tt);
@@ -616,7 +625,8 @@ GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t)
616 * As for msvcrt, use the wide variant, which always returns utf16 625 * As for msvcrt, use the wide variant, which always returns utf16
617 * (otherwise we'd have to detect current codepage or use W32API character 626 * (otherwise we'd have to detect current codepage or use W32API character
618 * set conversion routines to convert to UTF8). 627 * set conversion routines to convert to UTF8).
619 */strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp); 628 */
629 strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
620 630
621 return buf; 631 return buf;
622} 632}
diff --git a/src/util/test_crypto_cs.c b/src/util/test_crypto_cs.c
index 2978fec0a..d3406516e 100644
--- a/src/util/test_crypto_cs.c
+++ b/src/util/test_crypto_cs.c
@@ -148,8 +148,7 @@ test_generate_rpublic (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
148 148
149 149
150void 150void
151test_derive_blindingsecrets (const void *secret, 151test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
152 size_t secret_len,
153 struct GNUNET_CRYPTO_CsBlindingSecret bs[2]) 152 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
154{ 153{
155 /* TEST 1 154 /* TEST 1
@@ -159,7 +158,7 @@ test_derive_blindingsecrets (const void *secret,
159 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) 158 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
160 * 2); 159 * 2);
161 160
162 GNUNET_CRYPTO_cs_blinding_secrets_derive (secret, secret_len, bs); 161 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
163 162
164 GNUNET_assert (0 != memcmp (&other_bs[0], 163 GNUNET_assert (0 != memcmp (&other_bs[0],
165 &bs[0], 164 &bs[0],
@@ -173,7 +172,7 @@ test_derive_blindingsecrets (const void *secret,
173 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) 172 memcpy (&other_bs[0], &bs[0], sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
174 * 2); 173 * 2);
175 for (int i = 0; i<ITER; i++) { 174 for (int i = 0; i<ITER; i++) {
176 GNUNET_CRYPTO_cs_blinding_secrets_derive (secret, secret_len, bs); 175 GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
177 GNUNET_assert (0 == memcmp (&other_bs[0], 176 GNUNET_assert (0 == memcmp (&other_bs[0],
178 &bs[0], 177 &bs[0],
179 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) 178 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
@@ -493,8 +492,7 @@ main (int argc,
493 // generate blinding secrets 492 // generate blinding secrets
494 struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2]; 493 struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2];
495 test_derive_blindingsecrets (&nonce, 494 test_derive_blindingsecrets (&nonce,
496 sizeof(nonce), 495 blindingsecrets);
497 blindingsecrets);
498 496
499 // calculate blinded c's 497 // calculate blinded c's
500 struct GNUNET_CRYPTO_CsC blinded_cs[2]; 498 struct GNUNET_CRYPTO_CsC blinded_cs[2];
diff --git a/src/util/test_crypto_eddsa.c b/src/util/test_crypto_eddsa.c
index 10d6a4e91..459619ff2 100644
--- a/src/util/test_crypto_eddsa.c
+++ b/src/util/test_crypto_eddsa.c
@@ -216,12 +216,16 @@ testCreateFromFile (void)
216 struct GNUNET_CRYPTO_EddsaPublicKey p1; 216 struct GNUNET_CRYPTO_EddsaPublicKey p1;
217 struct GNUNET_CRYPTO_EddsaPublicKey p2; 217 struct GNUNET_CRYPTO_EddsaPublicKey p2;
218 218
219 GNUNET_assert (0 <= 219 /* do_create == GNUNET_YES and non-existing file MUST return GNUNET_YES */
220 GNUNET_assert (0 == unlink (KEYFILE) || ENOENT == errno);
221 GNUNET_assert (GNUNET_YES ==
220 GNUNET_CRYPTO_eddsa_key_from_file (KEYFILE, 222 GNUNET_CRYPTO_eddsa_key_from_file (KEYFILE,
221 GNUNET_YES, 223 GNUNET_YES,
222 &key)); 224 &key));
223 GNUNET_CRYPTO_eddsa_key_get_public (&key, 225 GNUNET_CRYPTO_eddsa_key_get_public (&key,
224 &p1); 226 &p1);
227
228 /* do_create == GNUNET_YES and _existing_ file MUST return GNUNET_NO */
225 GNUNET_assert (GNUNET_NO == 229 GNUNET_assert (GNUNET_NO ==
226 GNUNET_CRYPTO_eddsa_key_from_file (KEYFILE, 230 GNUNET_CRYPTO_eddsa_key_from_file (KEYFILE,
227 GNUNET_YES, 231 GNUNET_YES,
@@ -231,16 +235,13 @@ testCreateFromFile (void)
231 GNUNET_assert (0 == 235 GNUNET_assert (0 ==
232 GNUNET_memcmp (&p1, 236 GNUNET_memcmp (&p1,
233 &p2)); 237 &p2));
238
239 /* do_create == GNUNET_NO and non-existing file MUST return GNUNET_SYSERR */
234 GNUNET_assert (0 == unlink (KEYFILE)); 240 GNUNET_assert (0 == unlink (KEYFILE));
235 GNUNET_assert (GNUNET_OK == 241 GNUNET_assert (GNUNET_SYSERR ==
236 GNUNET_CRYPTO_eddsa_key_from_file (KEYFILE, 242 GNUNET_CRYPTO_eddsa_key_from_file (KEYFILE,
237 GNUNET_NO, 243 GNUNET_NO,
238 &key)); 244 &key));
239 GNUNET_CRYPTO_eddsa_key_get_public (&key,
240 &p2);
241 GNUNET_assert (0 !=
242 GNUNET_memcmp (&p1,
243 &p2));
244 return GNUNET_OK; 245 return GNUNET_OK;
245} 246}
246 247
@@ -299,7 +300,6 @@ main (int argc, char *argv[])
299 failure_count++; 300 failure_count++;
300 if (GNUNET_OK != testCreateFromFile ()) 301 if (GNUNET_OK != testCreateFromFile ())
301 failure_count++; 302 failure_count++;
302 GNUNET_assert (0 == unlink (KEYFILE));
303 perf_keygen (); 303 perf_keygen ();
304 304
305 if (0 != failure_count) 305 if (0 != failure_count)
diff --git a/src/util/test_crypto_hash.c b/src/util/test_crypto_hash.c
index d22e1f5d3..8241676da 100644
--- a/src/util/test_crypto_hash.c
+++ b/src/util/test_crypto_hash.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2002, 2003, 2004, 2006, 2009 GNUnet e.V. 3 Copyright (C) 2002, 2003, 2004, 2006, 2009, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -37,25 +37,29 @@ test (int number)
37 struct GNUNET_HashCode h2; 37 struct GNUNET_HashCode h2;
38 struct GNUNET_CRYPTO_HashAsciiEncoded enc; 38 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
39 39
40 memset (&h1, number, sizeof(struct GNUNET_HashCode)); 40 memset (&h1,
41 GNUNET_CRYPTO_hash_to_enc (&h1, &enc); 41 number,
42 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &h2)) 42 sizeof(struct GNUNET_HashCode));
43 GNUNET_CRYPTO_hash_to_enc (&h1,
44 &enc);
45 if (GNUNET_OK !=
46 GNUNET_CRYPTO_hash_from_string ((char *) &enc,
47 &h2))
43 { 48 {
44 printf ("enc2hash failed!\n"); 49 printf ("enc2hash failed!\n");
45 return 1; 50 return 1;
46 } 51 }
47 if (0 != memcmp (&h1, &h2, sizeof(struct GNUNET_HashCode))) 52 if (0 != GNUNET_memcmp (&h1,
53 &h2))
48 return 1; 54 return 1;
49 return 0; 55 return 0;
50} 56}
51 57
52 58
53static int 59static int
54testEncoding () 60test_encoding (void)
55{ 61{
56 int i; 62 for (int i = 0; i < 255; i++)
57
58 for (i = 0; i < 255; i++)
59 if (0 != test (i)) 63 if (0 != test (i))
60 return 1; 64 return 1;
61 return 0; 65 return 0;
@@ -63,7 +67,7 @@ testEncoding ()
63 67
64 68
65static int 69static int
66testArithmetic () 70test_arithmetic (void)
67{ 71{
68 struct GNUNET_HashCode h1; 72 struct GNUNET_HashCode h1;
69 struct GNUNET_HashCode h2; 73 struct GNUNET_HashCode h2;
@@ -72,49 +76,80 @@ testArithmetic ()
72 struct GNUNET_CRYPTO_SymmetricSessionKey skey; 76 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
73 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 77 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
74 78
75 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &h1); 79 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
76 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &h2); 80 &h1);
77 if (GNUNET_CRYPTO_hash_distance_u32 (&h1, &h2) != 81 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
78 GNUNET_CRYPTO_hash_distance_u32 (&h2, &h1)) 82 &h2);
79 return 1; 83 if (GNUNET_CRYPTO_hash_distance_u32 (&h1,
80 GNUNET_CRYPTO_hash_difference (&h1, &h2, &d); 84 &h2) !=
81 GNUNET_CRYPTO_hash_sum (&h1, &d, &s); 85 GNUNET_CRYPTO_hash_distance_u32 (&h2,
82 if (0 != GNUNET_CRYPTO_hash_cmp (&s, &h2)) 86 &h1))
83 return 1;
84 GNUNET_CRYPTO_hash_xor (&h1, &h2, &d);
85 GNUNET_CRYPTO_hash_xor (&h1, &d, &s);
86 if (0 != GNUNET_CRYPTO_hash_cmp (&s, &h2))
87 return 1; 87 return 1;
88 if (0 != GNUNET_CRYPTO_hash_xorcmp (&s, &h2, &h1)) 88 GNUNET_CRYPTO_hash_difference (&h1,
89 &h2,
90 &d);
91 GNUNET_CRYPTO_hash_sum (&h1,
92 &d,
93 &s);
94 if (0 !=
95 GNUNET_CRYPTO_hash_cmp (&s,
96 &h2))
89 return 1; 97 return 1;
90 if (-1 != GNUNET_CRYPTO_hash_xorcmp (&h1, &h2, &h1)) 98 GNUNET_CRYPTO_hash_xor (&h1,
99 &h2,
100 &d);
101 GNUNET_CRYPTO_hash_xor (&h1,
102 &d,
103 &s);
104 if (0 !=
105 GNUNET_CRYPTO_hash_cmp (&s,
106 &h2))
91 return 1; 107 return 1;
92 if (1 != GNUNET_CRYPTO_hash_xorcmp (&h1, &h2, &h2)) 108 if (0 !=
109 GNUNET_CRYPTO_hash_xorcmp (&s,
110 &h2,
111 &h1))
93 return 1; 112 return 1;
94 memset (&d, 0x40, sizeof(d)); 113 if (-1 !=
95 if (0 != GNUNET_CRYPTO_hash_get_bit_rtl (&d, 3)) 114 GNUNET_CRYPTO_hash_xorcmp (&h1,
115 &h2,
116 &h1))
96 return 1; 117 return 1;
97 if (1 != GNUNET_CRYPTO_hash_get_bit_rtl (&d, 6)) 118 if (1 !=
119 GNUNET_CRYPTO_hash_xorcmp (&h1,
120 &h2,
121 &h2))
98 return 1; 122 return 1;
99 memset (&d, 0x02, sizeof(d)); 123 memset (&d,
100 if (0 != GNUNET_CRYPTO_hash_get_bit_ltr (&d, 3)) 124 0,
101 return 1; 125 sizeof(d));
102 if (1 != GNUNET_CRYPTO_hash_get_bit_ltr (&d, 6)) 126 GNUNET_CRYPTO_hash_to_aes_key (&d,
103 return 1; 127 &skey,
104 memset (&d, 0, sizeof(d)); 128 &iv);
105 GNUNET_CRYPTO_hash_to_aes_key (&d, &skey, &iv); 129 memset (&h1,
130 0,
131 sizeof (h1));
132 h1.bits[1] = htonl (0x00200000); /* 32 + 8 + 2 = 42 MSB bits cleared */
133 GNUNET_assert (42 ==
134 GNUNET_CRYPTO_hash_count_leading_zeros (&h1));
135 GNUNET_assert (512 - 42 - 1 ==
136 GNUNET_CRYPTO_hash_count_tailing_zeros (&h1));
106 return 0; 137 return 0;
107} 138}
108 139
109 140
110static void 141static void
111finished_task (void *cls, const struct GNUNET_HashCode *res) 142finished_task (void *cls,
143 const struct GNUNET_HashCode *res)
112{ 144{
113 int *ret = cls; 145 int *ret = cls;
114 struct GNUNET_HashCode want; 146 struct GNUNET_HashCode want;
115 147
116 GNUNET_CRYPTO_hash (block, sizeof(block), &want); 148 GNUNET_CRYPTO_hash (block,
117 if (0 != memcmp (res, &want, sizeof(want))) 149 sizeof(block),
150 &want);
151 if (0 != GNUNET_memcmp (res,
152 &want))
118 *ret = 2; 153 *ret = 2;
119 else 154 else
120 *ret = 0; 155 *ret = 0;
@@ -126,43 +161,57 @@ file_hasher (void *cls)
126{ 161{
127 GNUNET_assert (NULL != 162 GNUNET_assert (NULL !=
128 GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 163 GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
129 FILENAME, 1024, &finished_task, cls)); 164 FILENAME,
165 1024,
166 &finished_task,
167 cls));
130} 168}
131 169
132 170
133static int 171static int
134testFileHash () 172test_file_hash (void)
135{ 173{
136 int ret; 174 int ret;
137 FILE *f; 175 FILE *f;
138 176
139 memset (block, 42, sizeof(block) / 2); 177 memset (block,
140 memset (&block[sizeof(block) / 2], 43, sizeof(block) / 2); 178 42,
179 sizeof(block) / 2);
180 memset (&block[sizeof(block) / 2],
181 43,
182 sizeof(block) / 2);
141 GNUNET_assert (NULL != (f = fopen (FILENAME, "w+"))); 183 GNUNET_assert (NULL != (f = fopen (FILENAME, "w+")));
142 GNUNET_break (sizeof(block) == fwrite (block, 1, sizeof(block), f)); 184 GNUNET_break (sizeof(block) ==
185 fwrite (block,
186 1,
187 sizeof(block),
188 f));
143 GNUNET_break (0 == fclose (f)); 189 GNUNET_break (0 == fclose (f));
144 ret = 1; 190 ret = 1;
145 GNUNET_SCHEDULER_run (&file_hasher, &ret); 191 GNUNET_SCHEDULER_run (&file_hasher,
192 &ret);
146 GNUNET_break (0 == unlink (FILENAME)); 193 GNUNET_break (0 == unlink (FILENAME));
147 return ret; 194 return ret;
148} 195}
149 196
150 197
151int 198int
152main (int argc, char *argv[]) 199main (int argc,
200 char *argv[])
153{ 201{
154 int failureCount = 0; 202 int failureCount = 0;
155 int i; 203
156 204 GNUNET_log_setup ("test-crypto-hash",
157 GNUNET_log_setup ("test-crypto-hash", "WARNING", NULL); 205 "WARNING",
158 for (i = 0; i < 10; i++) 206 NULL);
159 failureCount += testEncoding (); 207 for (int i = 0; i < 10; i++)
160 failureCount += testArithmetic (); 208 failureCount += test_encoding ();
161 failureCount += testFileHash (); 209 failureCount += test_arithmetic ();
162 if (failureCount != 0) 210 failureCount += test_file_hash ();
211 if (0 != failureCount)
163 return 1; 212 return 1;
164 return 0; 213 return 0;
165} 214}
166 215
167 216
168/* end of hashingtest.c */ 217/* end of test_crypto_hash.c */
diff --git a/src/util/time.c b/src/util/time.c
index 144e1b401..83b39b4e8 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -58,27 +58,35 @@ GNUNET_TIME_get_offset ()
58} 58}
59 59
60 60
61int 61struct GNUNET_TIME_Timestamp
62GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at) 62GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at)
63{ 63{
64 if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 64 struct GNUNET_TIME_Timestamp ts;
65 return GNUNET_OK; 65
66 if (0 == at->abs_value_us % 1000000) 66 if (GNUNET_TIME_absolute_is_never (at))
67 return GNUNET_OK; 67 return GNUNET_TIME_UNIT_FOREVER_TS;
68 at->abs_value_us -= at->abs_value_us % 1000000; 68 ts.abs_time.abs_value_us = at.abs_value_us - at.abs_value_us % 1000000;
69 return GNUNET_NO; 69 return ts;
70}
71
72
73struct GNUNET_TIME_TimestampNBO
74GNUNET_TIME_timestamp_hton (struct GNUNET_TIME_Timestamp t)
75{
76 struct GNUNET_TIME_TimestampNBO tn;
77
78 tn.abs_time_nbo = GNUNET_TIME_absolute_hton (t.abs_time);
79 return tn;
70} 80}
71 81
72 82
73int 83struct GNUNET_TIME_Timestamp
74GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt) 84GNUNET_TIME_timestamp_ntoh (struct GNUNET_TIME_TimestampNBO tn)
75{ 85{
76 if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) 86 struct GNUNET_TIME_Timestamp t;
77 return GNUNET_OK; 87
78 if (0 == rt->rel_value_us % 1000000) 88 t.abs_time = GNUNET_TIME_absolute_ntoh (tn.abs_time_nbo);
79 return GNUNET_OK; 89 return t;
80 rt->rel_value_us -= rt->rel_value_us % 1000000;
81 return GNUNET_NO;
82} 90}
83 91
84 92
@@ -96,6 +104,14 @@ GNUNET_TIME_absolute_get ()
96} 104}
97 105
98 106
107struct GNUNET_TIME_Timestamp
108GNUNET_TIME_timestamp_get ()
109{
110 return GNUNET_TIME_absolute_to_timestamp (
111 GNUNET_TIME_absolute_get ());
112}
113
114
99struct GNUNET_TIME_Relative 115struct GNUNET_TIME_Relative
100GNUNET_TIME_relative_get_zero_ () 116GNUNET_TIME_relative_get_zero_ ()
101{ 117{
@@ -177,12 +193,114 @@ GNUNET_TIME_absolute_get_forever_ ()
177} 193}
178 194
179 195
196const char *
197GNUNET_TIME_timestamp2s (struct GNUNET_TIME_Timestamp ts)
198{
199 static GNUNET_THREAD_LOCAL char buf[255];
200 time_t tt;
201 struct tm *tp;
202
203 if (GNUNET_TIME_absolute_is_never (ts.abs_time))
204 return "end of time";
205 tt = ts.abs_time.abs_value_us / 1000LL / 1000LL;
206 tp = localtime (&tt);
207 /* This is hacky, but i don't know a way to detect libc character encoding.
208 * Just expect utf8 from glibc these days.
209 * As for msvcrt, use the wide variant, which always returns utf16
210 * (otherwise we'd have to detect current codepage or use W32API character
211 * set conversion routines to convert to UTF8).
212 */
213 strftime (buf,
214 sizeof(buf),
215 "%a %b %d %H:%M:%S %Y",
216 tp);
217 return buf;
218}
219
220
221const char *
222GNUNET_TIME_absolute2s (struct GNUNET_TIME_Absolute t)
223{
224 static GNUNET_THREAD_LOCAL char buf[255];
225 time_t tt;
226 struct tm *tp;
227
228 if (GNUNET_TIME_absolute_is_never (t))
229 return "end of time";
230 tt = t.abs_value_us / 1000LL / 1000LL;
231 tp = localtime (&tt);
232 /* This is hacky, but i don't know a way to detect libc character encoding.
233 * Just expect utf8 from glibc these days.
234 * As for msvcrt, use the wide variant, which always returns utf16
235 * (otherwise we'd have to detect current codepage or use W32API character
236 * set conversion routines to convert to UTF8).
237 */
238 strftime (buf,
239 sizeof(buf),
240 "%a %b %d %H:%M:%S %Y",
241 tp);
242 return buf;
243}
244
245
246const char *
247GNUNET_TIME_relative2s (struct GNUNET_TIME_Relative delta,
248 bool do_round)
249{
250 static GNUNET_THREAD_LOCAL char buf[128];
251 const char *unit = /* time unit */ "µs";
252 uint64_t dval = delta.rel_value_us;
253
254 if (GNUNET_TIME_relative_is_forever (delta))
255 return "forever";
256 if (0 == delta.rel_value_us)
257 return "0 ms";
258 if ( ((GNUNET_YES == do_round) &&
259 (dval > 5 * 1000)) ||
260 (0 == (dval % 1000)))
261 {
262 dval = dval / 1000;
263 unit = /* time unit */ "ms";
264 if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
265 {
266 dval = dval / 1000;
267 unit = /* time unit */ "s";
268 if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
269 {
270 dval = dval / 60;
271 unit = /* time unit */ "m";
272 if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
273 {
274 dval = dval / 60;
275 unit = /* time unit */ "h";
276 if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
277 (0 == (dval % 24)))
278 {
279 dval = dval / 24;
280 if (1 == dval)
281 unit = /* time unit */ "day";
282 else
283 unit = /* time unit */ "days";
284 }
285 }
286 }
287 }
288 }
289 GNUNET_snprintf (buf,
290 sizeof(buf),
291 "%llu %s",
292 (unsigned long long) dval,
293 unit);
294 return buf;
295}
296
297
180struct GNUNET_TIME_Absolute 298struct GNUNET_TIME_Absolute
181GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel) 299GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
182{ 300{
183 struct GNUNET_TIME_Absolute ret; 301 struct GNUNET_TIME_Absolute ret;
184 302
185 if (rel.rel_value_us == UINT64_MAX) 303 if (GNUNET_TIME_relative_is_forever (rel))
186 return GNUNET_TIME_UNIT_FOREVER_ABS; 304 return GNUNET_TIME_UNIT_FOREVER_ABS;
187 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 305 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
188 306
@@ -196,6 +314,14 @@ GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
196} 314}
197 315
198 316
317struct GNUNET_TIME_Timestamp
318GNUNET_TIME_relative_to_timestamp (struct GNUNET_TIME_Relative rel)
319{
320 return GNUNET_TIME_absolute_to_timestamp (
321 GNUNET_TIME_relative_to_absolute (rel));
322}
323
324
199struct GNUNET_TIME_Relative 325struct GNUNET_TIME_Relative
200GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1, 326GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
201 struct GNUNET_TIME_Relative t2) 327 struct GNUNET_TIME_Relative t2)
@@ -228,12 +354,28 @@ GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
228} 354}
229 355
230 356
357struct GNUNET_TIME_Timestamp
358GNUNET_TIME_timestamp_max (struct GNUNET_TIME_Timestamp t1,
359 struct GNUNET_TIME_Timestamp t2)
360{
361 return (t1.abs_time.abs_value_us > t2.abs_time.abs_value_us) ? t1 : t2;
362}
363
364
365struct GNUNET_TIME_Timestamp
366GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1,
367 struct GNUNET_TIME_Timestamp t2)
368{
369 return (t1.abs_time.abs_value_us < t2.abs_time.abs_value_us) ? t1 : t2;
370}
371
372
231struct GNUNET_TIME_Relative 373struct GNUNET_TIME_Relative
232GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future) 374GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
233{ 375{
234 struct GNUNET_TIME_Relative ret; 376 struct GNUNET_TIME_Relative ret;
235 377
236 if (future.abs_value_us == UINT64_MAX) 378 if (GNUNET_TIME_absolute_is_never (future))
237 return GNUNET_TIME_UNIT_FOREVER_REL; 379 return GNUNET_TIME_UNIT_FOREVER_REL;
238 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 380 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
239 381
@@ -250,7 +392,7 @@ GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
250{ 392{
251 struct GNUNET_TIME_Relative ret; 393 struct GNUNET_TIME_Relative ret;
252 394
253 if (end.abs_value_us == UINT64_MAX) 395 if (GNUNET_TIME_absolute_is_never (end))
254 return GNUNET_TIME_UNIT_FOREVER_REL; 396 return GNUNET_TIME_UNIT_FOREVER_REL;
255 if (end.abs_value_us < start.abs_value_us) 397 if (end.abs_value_us < start.abs_value_us)
256 return GNUNET_TIME_UNIT_ZERO; 398 return GNUNET_TIME_UNIT_ZERO;
@@ -279,8 +421,8 @@ GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
279{ 421{
280 struct GNUNET_TIME_Absolute ret; 422 struct GNUNET_TIME_Absolute ret;
281 423
282 if ((start.abs_value_us == UINT64_MAX) || 424 if (GNUNET_TIME_absolute_is_never (start) ||
283 (duration.rel_value_us == UINT64_MAX)) 425 GNUNET_TIME_relative_is_forever (duration))
284 return GNUNET_TIME_UNIT_FOREVER_ABS; 426 return GNUNET_TIME_UNIT_FOREVER_ABS;
285 if (start.abs_value_us + duration.rel_value_us < start.abs_value_us) 427 if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
286 { 428 {
@@ -300,7 +442,7 @@ GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
300 442
301 if (start.abs_value_us <= duration.rel_value_us) 443 if (start.abs_value_us <= duration.rel_value_us)
302 return GNUNET_TIME_UNIT_ZERO_ABS; 444 return GNUNET_TIME_UNIT_ZERO_ABS;
303 if (start.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) 445 if (GNUNET_TIME_absolute_is_never (start))
304 return GNUNET_TIME_UNIT_FOREVER_ABS; 446 return GNUNET_TIME_UNIT_FOREVER_ABS;
305 ret.abs_value_us = start.abs_value_us - duration.rel_value_us; 447 ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
306 return ret; 448 return ret;
@@ -315,7 +457,7 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
315 457
316 if (0 == factor) 458 if (0 == factor)
317 return GNUNET_TIME_UNIT_ZERO; 459 return GNUNET_TIME_UNIT_ZERO;
318 if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) 460 if (GNUNET_TIME_relative_is_forever (rel))
319 return GNUNET_TIME_UNIT_FOREVER_REL; 461 return GNUNET_TIME_UNIT_FOREVER_REL;
320 ret.rel_value_us = rel.rel_value_us * factor; 462 ret.rel_value_us = rel.rel_value_us * factor;
321 if (ret.rel_value_us / factor != rel.rel_value_us) 463 if (ret.rel_value_us / factor != rel.rel_value_us)
@@ -328,7 +470,8 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
328 470
329 471
330struct GNUNET_TIME_Relative 472struct GNUNET_TIME_Relative
331relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor) 473relative_multiply_double (struct GNUNET_TIME_Relative rel,
474 double factor)
332{ 475{
333 struct GNUNET_TIME_Relative out; 476 struct GNUNET_TIME_Relative out;
334 double m; 477 double m;
@@ -337,7 +480,7 @@ relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor)
337 480
338 if (0 == factor) 481 if (0 == factor)
339 return GNUNET_TIME_UNIT_ZERO; 482 return GNUNET_TIME_UNIT_ZERO;
340 if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) 483 if (GNUNET_TIME_relative_is_forever (rel))
341 return GNUNET_TIME_UNIT_FOREVER_REL; 484 return GNUNET_TIME_UNIT_FOREVER_REL;
342 485
343 m = ((double) rel.rel_value_us) * factor; 486 m = ((double) rel.rel_value_us) * factor;
@@ -361,7 +504,7 @@ GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel,
361 504
362 if (0 == factor) 505 if (0 == factor)
363 return GNUNET_TIME_UNIT_ZERO; 506 return GNUNET_TIME_UNIT_ZERO;
364 if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) 507 if (GNUNET_TIME_relative_is_forever (rel))
365 return GNUNET_TIME_UNIT_FOREVER_REL; 508 return GNUNET_TIME_UNIT_FOREVER_REL;
366 ret.rel_value_us = rel.rel_value_us * factor; 509 ret.rel_value_us = rel.rel_value_us * factor;
367 if (ret.rel_value_us / factor != rel.rel_value_us) 510 if (ret.rel_value_us / factor != rel.rel_value_us)
@@ -379,7 +522,7 @@ GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
379 struct GNUNET_TIME_Relative ret; 522 struct GNUNET_TIME_Relative ret;
380 523
381 if ((0 == factor) || 524 if ((0 == factor) ||
382 (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)) 525 (GNUNET_TIME_relative_is_forever (rel)))
383 return GNUNET_TIME_UNIT_FOREVER_REL; 526 return GNUNET_TIME_UNIT_FOREVER_REL;
384 ret.rel_value_us = rel.rel_value_us / factor; 527 ret.rel_value_us = rel.rel_value_us / factor;
385 return ret; 528 return ret;
@@ -538,6 +681,20 @@ GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch)
538} 681}
539 682
540 683
684struct GNUNET_TIME_Timestamp
685GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch)
686{
687 struct GNUNET_TIME_Timestamp ret;
688
689 ret.abs_time.abs_value_us
690 = GNUNET_TIME_UNIT_SECONDS.rel_value_us * s_after_epoch;
691 if (ret.abs_time.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us
692 != s_after_epoch)
693 ret = GNUNET_TIME_UNIT_FOREVER_TS;
694 return ret;
695}
696
697
541struct GNUNET_TIME_Absolute 698struct GNUNET_TIME_Absolute
542GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) 699GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
543{ 700{
@@ -645,6 +802,13 @@ GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
645} 802}
646 803
647 804
805bool
806GNUNET_TIME_absolute_is_zero (struct GNUNET_TIME_Absolute abs)
807{
808 return 0 == abs.abs_value_us;
809}
810
811
648struct GNUNET_TIME_Relative 812struct GNUNET_TIME_Relative
649GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r) 813GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r)
650{ 814{