summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am9
-rw-r--r--src/abd/Makefile.am10
-rw-r--r--src/abd/abd.h61
-rw-r--r--src/abd/abd_api.c8
-rw-r--r--src/abd/abd_serialization.c16
-rw-r--r--src/abd/delegate_misc.c48
-rw-r--r--src/abd/gnunet-abd.c94
-rw-r--r--src/abd/gnunet-service-abd.c102
-rw-r--r--src/abd/plugin_gnsrecord_abd.c16
-rwxr-xr-xsrc/abd/test_abd_bi_and.sh8
-rw-r--r--src/abe/Makefile.am49
-rw-r--r--src/abe/abe.c519
-rw-r--r--src/abe/test_cpabe.c89
-rw-r--r--src/ats/ats.conf.in12
-rw-r--r--src/ats/gnunet-ats-solver-eval.c5
-rw-r--r--src/ats/gnunet-service-ats_addresses.c2
-rw-r--r--src/ats/gnunet-service-ats_connectivity.c7
-rw-r--r--src/block/bg_bf.c42
-rw-r--r--src/block/block.c256
-rw-r--r--src/block/plugin_block_template.c104
-rw-r--r--src/block/plugin_block_test.c136
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c12
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c8
-rw-r--r--src/cadet/gnunet-service-cadet_paths.h5
-rw-r--r--src/consensus/plugin_block_consensus.c158
-rw-r--r--src/consensus/test_consensus.conf2
-rw-r--r--src/core/gnunet-service-core.c16
-rw-r--r--src/core/gnunet-service-core_kx.c7
-rw-r--r--src/curl/curl.c278
-rw-r--r--src/curl/curl_reschedule.c40
-rw-r--r--src/datacache/datacache.c193
-rw-r--r--src/datacache/perf_datacache.c16
-rw-r--r--src/datacache/plugin_datacache_heap.c294
-rw-r--r--src/datacache/plugin_datacache_postgres.c329
-rw-r--r--src/datacache/plugin_datacache_sqlite.c802
-rw-r--r--src/datacache/plugin_datacache_template.c41
-rw-r--r--src/datacache/test_datacache.c80
-rw-r--r--src/datacache/test_datacache_data_postgres.conf4
-rw-r--r--src/datacache/test_datacache_quota.c69
-rw-r--r--src/datastore/gnunet-service-datastore.c3
-rw-r--r--src/dht/.gitignore1
-rw-r--r--src/dht/Makefile.am26
-rw-r--r--src/dht/dht.h29
-rw-r--r--src/dht/dht_api.c684
-rw-r--r--src/dht/dht_test_lib.c15
-rwxr-xr-xsrc/dht/dhtu_testbed_connect.sh31
-rw-r--r--src/dht/dhtu_testbed_deploy.conf26
-rwxr-xr-xsrc/dht/dhtu_testbed_deploy.sh84
-rw-r--r--src/dht/gnunet-dht-get.c108
-rw-r--r--src/dht/gnunet-dht-hello.c178
-rw-r--r--src/dht/gnunet-dht-monitor.c14
-rw-r--r--src/dht/gnunet-dht-put.c75
-rw-r--r--src/dht/gnunet-service-dht.c467
-rw-r--r--src/dht/gnunet-service-dht.h171
-rw-r--r--src/dht/gnunet-service-dht_clients.c1410
-rw-r--r--src/dht/gnunet-service-dht_datacache.c376
-rw-r--r--src/dht/gnunet-service-dht_datacache.h96
-rw-r--r--src/dht/gnunet-service-dht_hello.c148
-rw-r--r--src/dht/gnunet-service-dht_hello.h55
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c3571
-rw-r--r--src/dht/gnunet-service-dht_neighbours.h143
-rw-r--r--src/dht/gnunet-service-dht_nse.c117
-rw-r--r--src/dht/gnunet-service-dht_nse.h52
-rw-r--r--src/dht/gnunet-service-dht_routing.c335
-rw-r--r--src/dht/gnunet-service-dht_routing.h24
-rw-r--r--src/dht/gnunet_dht_profiler.c9
-rw-r--r--src/dht/plugin_block_dht.c339
-rw-r--r--src/dht/test_dht_api.c5
-rw-r--r--src/dht/test_dht_monitor.c24
-rw-r--r--src/dht/test_dht_topo.c209
-rw-r--r--src/dhtu/.gitignore1
-rw-r--r--src/dhtu/Makefile.am14
-rw-r--r--src/dhtu/dhtu.conf7
-rw-r--r--src/dhtu/plugin_dhtu_gnunet.c213
-rw-r--r--src/dhtu/plugin_dhtu_ip.c488
-rw-r--r--src/dhtu/test_dhtu_ip.c7
-rw-r--r--src/dns/plugin_block_dns.c149
-rw-r--r--src/fs/fs_file_information.c2
-rw-r--r--src/fs/fs_uri.c26
-rw-r--r--src/fs/gnunet-search.c599
-rw-r--r--src/fs/gnunet-service-fs.c14
-rw-r--r--src/fs/gnunet-service-fs.h10
-rw-r--r--src/fs/gnunet-service-fs_cp.c27
-rw-r--r--src/fs/gnunet-service-fs_pr.c185
-rw-r--r--src/fs/gnunet-service-fs_pr.h30
-rw-r--r--src/fs/plugin_block_fs.c258
-rw-r--r--src/fs/test_fs_uri.c2
-rw-r--r--src/fs/test_plugin_block_fs.c46
-rw-r--r--src/gns/Makefile.am53
-rw-r--r--src/gns/gns.conf.in3
-rw-r--r--src/gns/gnunet-bcd.c2
-rw-r--r--src/gns/gnunet-dns2gns.c209
-rw-r--r--src/gns/gnunet-gns-proxy-setup-ca.in60
-rw-r--r--src/gns/gnunet-service-gns.c8
-rw-r--r--src/gns/gnunet-service-gns_resolver.c373
-rw-r--r--src/gns/plugin_block_gns.c207
-rw-r--r--src/gns/plugin_gnsrecord_gns.c90
-rwxr-xr-xsrc/gns/test_gns_cname_lookup.sh99
-rwxr-xr-xsrc/gns/test_gns_gns2dns_cname_lookup.sh9
-rwxr-xr-xsrc/gns/test_gns_gns2dns_lookup.sh14
-rwxr-xr-xsrc/gns/test_gns_gns2dns_zkey_lookup.sh14
-rwxr-xr-xsrc/gns/test_gns_redirect_lookup.sh100
-rwxr-xr-xsrc/gns/test_gnunet_gns.sh.in9
-rw-r--r--src/gnsrecord/Makefile.am11
-rw-r--r--src/gnsrecord/gnsrecord.c21
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c559
-rw-r--r--src/gnsrecord/gnsrecord_crypto.h87
-rw-r--r--src/gnsrecord/gnsrecord_misc.c270
-rw-r--r--src/gnsrecord/gnsrecord_serialization.c56
-rw-r--r--src/gnsrecord/gnunet-gnsrecord-tvg.c407
-rw-r--r--src/gnsrecord/perf_gnsrecord_crypto.c6
-rw-r--r--src/gnsrecord/plugin_gnsrecord_dns.c7
-rw-r--r--src/gnsrecord/test_gnsrecord_block_expiration.c6
-rw-r--r--src/gnsrecord/test_gnsrecord_crypto.c16
-rw-r--r--src/gnsrecord/test_gnsrecord_testvectors.c131
-rw-r--r--src/hello/.gitignore2
-rw-r--r--src/hello/Makefile.am19
-rw-r--r--src/hello/hello-uri.c898
-rw-r--r--src/hello/test_hello-ng.c23
-rw-r--r--src/hello/test_hello-uri.c212
-rw-r--r--src/hostlist/gnunet-daemon-hostlist_client.c6
-rw-r--r--src/identity/Makefile.am8
-rw-r--r--src/identity/gnunet-identity.c209
-rw-r--r--src/identity/gnunet-service-identity.c3
-rw-r--r--src/identity/identity_api.c116
-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/Makefile.am3
-rw-r--r--src/include/gnu_name_system_record_types.h148
-rw-r--r--src/include/gnunet_abd_service.h28
-rw-r--r--src/include/gnunet_abe_lib.h193
-rw-r--r--src/include/gnunet_block_group_lib.h4
-rw-r--r--src/include/gnunet_block_lib.h252
-rw-r--r--src/include/gnunet_block_plugin.h129
-rw-r--r--src/include/gnunet_common.h27
-rw-r--r--src/include/gnunet_configuration_lib.h136
-rw-r--r--src/include/gnunet_container_lib.h4
-rw-r--r--src/include/gnunet_crypto_lib.h614
-rw-r--r--src/include/gnunet_datacache_lib.h112
-rw-r--r--src/include/gnunet_datacache_plugin.h75
-rw-r--r--src/include/gnunet_dht_block_types.h156
-rw-r--r--src/include/gnunet_dht_service.h224
-rw-r--r--src/include/gnunet_dhtu_plugin.h89
-rw-r--r--src/include/gnunet_fs_service.h2
-rw-r--r--src/include/gnunet_getopt_lib.h18
-rw-r--r--src/include/gnunet_gns_service.h6
-rw-r--r--src/include/gnunet_gnsrecord_lib.h167
-rw-r--r--src/include/gnunet_gnsrecord_plugin.h17
-rw-r--r--src/include/gnunet_hello_uri_lib.h248
-rw-r--r--src/include/gnunet_identity_service.h65
-rw-r--r--src/include/gnunet_json_lib.h60
-rw-r--r--src/include/gnunet_messenger_service.h23
-rw-r--r--src/include/gnunet_namestore_plugin.h65
-rw-r--r--src/include/gnunet_namestore_service.h134
-rw-r--r--src/include/gnunet_network_lib.h10
-rw-r--r--src/include/gnunet_pq_lib.h92
-rw-r--r--src/include/gnunet_protocols.h24
-rw-r--r--src/include/gnunet_signatures.h266
-rw-r--r--src/include/gnunet_sq_lib.h18
-rw-r--r--src/include/gnunet_strings_lib.h51
-rw-r--r--src/include/gnunet_testing_netjail_lib.h83
-rw-r--r--src/include/gnunet_testing_ng_lib.h468
-rw-r--r--src/include/gnunet_time_lib.h260
-rw-r--r--src/json/json.c34
-rw-r--r--src/json/json_generator.c86
-rw-r--r--src/json/json_helper.c145
-rw-r--r--src/json/json_pack.c22
-rw-r--r--src/json/test_json.c69
-rw-r--r--src/messenger/gnunet-service-messenger.c36
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c253
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.h57
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c170
-rw-r--r--src/messenger/gnunet-service-messenger_handle.h70
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.c6
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c12
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c4
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c16
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c16
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c8
-rw-r--r--src/messenger/gnunet-service-messenger_room.c248
-rw-r--r--src/messenger/gnunet-service-messenger_room.h107
-rw-r--r--src/messenger/gnunet-service-messenger_service.c32
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c14
-rw-r--r--src/messenger/messenger.conf.in6
-rw-r--r--src/messenger/messenger_api.c4
-rw-r--r--src/messenger/messenger_api_message.c12
-rw-r--r--src/messenger/plugin_gnsrecord_messenger.c59
-rw-r--r--src/namecache/test_namecache_api_cache_block.c7
-rw-r--r--src/namestore/gnunet-namestore-fcfsd.c24
-rw-r--r--src/namestore/gnunet-namestore.c105
-rw-r--r--src/namestore/gnunet-service-namestore.c217
-rw-r--r--src/namestore/namestore.conf.in1
-rw-r--r--src/namestore/namestore.h18
-rw-r--r--src/namestore/namestore_api.c182
-rw-r--r--src/namestore/plugin_namestore_sqlite.c10
-rw-r--r--src/namestore/plugin_rest_namestore.c10
-rw-r--r--src/namestore/test_namestore_api_lookup_nick.c4
-rw-r--r--src/namestore/test_namestore_api_lookup_public.c2
-rw-r--r--src/namestore/test_namestore_api_lookup_shadow.c2
-rw-r--r--src/namestore/test_namestore_api_lookup_shadow_filter.c2
-rw-r--r--src/namestore/test_namestore_api_remove.c2
-rw-r--r--src/namestore/test_namestore_api_remove_not_existing_record.c2
-rw-r--r--src/namestore/test_namestore_api_zone_to_name.c10
-rwxr-xr-xsrc/namestore/test_namestore_delete.sh10
-rwxr-xr-xsrc/namestore/test_plugin_rest_namestore.sh10
-rw-r--r--src/nse/gnunet-service-nse.c39
-rw-r--r--src/peerstore/peerstore_api.c19
-rw-r--r--src/pq/Makefile.am2
-rw-r--r--src/pq/pq.h5
-rw-r--r--src/pq/pq_connect.c155
-rw-r--r--src/pq/pq_event.c5
-rw-r--r--src/pq/pq_prepare.c14
-rw-r--r--src/pq/pq_query_helper.c90
-rw-r--r--src/pq/pq_result_helper.c287
-rw-r--r--src/pt/gnunet-daemon-pt.c6
-rw-r--r--src/reclaim/.gitignore1
-rw-r--r--src/reclaim/Makefile.am37
-rw-r--r--src/reclaim/did.h49
-rw-r--r--src/reclaim/did_misc.c70
-rw-r--r--src/reclaim/gnunet-did.c896
-rw-r--r--src/reclaim/oidc_helper.c160
-rw-r--r--src/reclaim/oidc_helper.h49
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c365
-rw-r--r--src/reclaim/reclaim.conf5
-rw-r--r--src/reclaim/reclaim_api.c1
-rw-r--r--src/reclaim/test_reclaim.conf2
-rwxr-xr-xsrc/reclaim/test_reclaim_consume.sh14
-rw-r--r--src/reclaim/test_w3c_ed25519_2020.c69
-rw-r--r--src/regex/gnunet-regex-profiler.c83
-rw-r--r--src/regex/gnunet-service-regex.c22
-rw-r--r--src/regex/plugin_block_regex.c346
-rw-r--r--src/regex/regex_internal.h15
-rw-r--r--src/regex/regex_internal_dht.c12
-rw-r--r--src/regex/regex_internal_lib.h4
-rw-r--r--src/revocation/gnunet-revocation-tvg.c59
-rw-r--r--src/revocation/gnunet-service-revocation.c33
-rw-r--r--src/revocation/plugin_block_revocation.c248
-rw-r--r--src/revocation/revocation.h8
-rw-r--r--src/revocation/revocation_api.c86
-rw-r--r--src/set/plugin_block_set_test.c94
-rw-r--r--src/seti/plugin_block_seti_test.c124
-rw-r--r--src/setu/plugin_block_setu_test.c126
-rw-r--r--src/testbed/gnunet-service-testbed_connectionpool.c33
-rw-r--r--src/testbed/gnunet-service-testbed_oc.c44
-rw-r--r--src/testbed/testbed_api_topology.c2
-rw-r--r--src/testing/.gitignore1
-rw-r--r--src/testing/Makefile.am2
-rw-r--r--src/testing/gnunet-cmds-helper.c11
-rw-r--r--src/testing/testing.c46
-rw-r--r--src/testing/testing_api_cmd_block_until_external_trigger.c48
-rw-r--r--src/testing/testing_api_cmd_local_test_prepared.c25
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c86
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_testsystem.c15
-rw-r--r--src/testing/testing_api_cmd_system_create.c24
-rw-r--r--src/testing/testing_api_cmd_system_destroy.c4
-rw-r--r--src/testing/testing_api_loop.c23
-rw-r--r--src/testing/testing_api_trait_cmd.c79
-rw-r--r--src/testing/testing_api_trait_process.c81
-rw-r--r--src/testing/testing_api_traits.c7
-rw-r--r--src/transport/.gitignore1
-rw-r--r--src/transport/Makefile.am19
-rw-r--r--src/transport/gnunet-communicator-tcp.c58
-rw-r--r--src/transport/gnunet-communicator-udp.c39
-rw-r--r--src/transport/gnunet-service-tng.c1534
-rw-r--r--src/transport/gnunet-service-transport.c4
-rw-r--r--src/transport/gnunet-transport-certificate-creation.in29
-rw-r--r--src/transport/test_transport_api2_tcp_node1.conf5
-rw-r--r--src/transport/test_transport_distance_vector_circle_topo.conf12
-rw-r--r--src/transport/test_transport_distance_vector_topo.conf8
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send.c21
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send_broadcast.c33
-rw-r--r--src/transport/test_transport_plugin_cmd_simple_send_dv.c139
-rw-r--r--src/transport/test_transport_plugin_cmd_udp_backchannel.c15
-rwxr-xr-xsrc/transport/test_transport_simple_send.sh7
-rwxr-xr-xsrc/transport/test_transport_simple_send_broadcast.sh8
-rwxr-xr-xsrc/transport/test_transport_simple_send_dv.sh8
-rwxr-xr-xsrc/transport/test_transport_simple_send_dv_circle.sh11
-rwxr-xr-xsrc/transport/test_transport_simple_send_string.sh8
-rw-r--r--src/transport/test_transport_start_with_config.c6
-rwxr-xr-xsrc/transport/test_transport_udp_backchannel.sh12
-rw-r--r--src/transport/transport-testing-cmds.h110
-rw-r--r--src/transport/transport_api_cmd_backchannel_check.c8
-rw-r--r--src/transport/transport_api_cmd_connecting_peers.c73
-rw-r--r--src/transport/transport_api_cmd_send_simple.c10
-rw-r--r--src/transport/transport_api_cmd_start_peer.c172
-rw-r--r--src/transport/transport_api_cmd_stop_peer.c9
-rw-r--r--src/transport/transport_api_traits.c32
-rw-r--r--src/util/.gitignore4
-rw-r--r--src/util/Makefile.am24
-rw-r--r--src/util/client.c10
-rw-r--r--src/util/common_logging.c25
-rw-r--r--src/util/configuration.c2
-rw-r--r--src/util/container_bloomfilter.c230
-rw-r--r--src/util/crypto_abe.c438
-rw-r--r--src/util/crypto_cs.c343
-rw-r--r--src/util/crypto_ecc_gnsrecord.c55
-rw-r--r--src/util/crypto_ecc_setup.c11
-rw-r--r--src/util/crypto_edx25519.c354
-rw-r--r--src/util/crypto_hash.c130
-rw-r--r--src/util/crypto_hkdf.c118
-rw-r--r--src/util/crypto_kdf.c61
-rw-r--r--src/util/crypto_random.c4
-rw-r--r--src/util/crypto_rsa.c28
-rw-r--r--src/util/dnsstub.c42
-rw-r--r--src/util/getopt_helpers.c252
-rw-r--r--src/util/gnunet-crypto-tvg.c450
-rw-r--r--src/util/gnunet-scrypt.c21
-rw-r--r--src/util/mq.c471
-rw-r--r--src/util/mst.c19
-rw-r--r--src/util/network.c3
-rw-r--r--src/util/os_installation.c27
-rw-r--r--src/util/os_priority.c26
-rw-r--r--src/util/perf_crypto_cs.c183
-rw-r--r--src/util/perf_crypto_rsa.c3
-rw-r--r--src/util/plugin.c4
-rw-r--r--src/util/scheduler.c47
-rw-r--r--src/util/service.c10
-rw-r--r--src/util/strings.c95
-rw-r--r--src/util/test_container_bloomfilter.c50
-rw-r--r--src/util/test_crypto_cs.c609
-rw-r--r--src/util/test_crypto_eddsa.c24
-rw-r--r--src/util/test_crypto_edx25519.c326
-rw-r--r--src/util/test_crypto_hash.c157
-rw-r--r--src/util/test_strings.c6
-rw-r--r--src/util/time.c255
-rw-r--r--src/zonemaster/gnunet-service-zonemaster-monitor.c87
-rw-r--r--src/zonemaster/gnunet-service-zonemaster.c105
328 files changed, 23072 insertions, 14146 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 31215c6d0..d7c0b51f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,13 +5,8 @@ TESTBED = testbed-logger testbed
if HAVE_EXPERIMENTAL
EXP_DIR = \
- rps
- #abd FTBFS
-if HAVE_ABE
- EXP_DIR += \
- abe
-endif
- EXP_DIR += \
+ rps \
+ abd \
auction
endif
diff --git a/src/abd/Makefile.am b/src/abd/Makefile.am
index 34a0438f5..ae9248b43 100644
--- a/src/abd/Makefile.am
+++ b/src/abd/Makefile.am
@@ -3,7 +3,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
EXTRA_DIST = \
test_abd_defaults.conf \
- test_abd_lookup.conf
+ test_abd_lookup.conf \
+ $(check_SCRIPTS) \
+ $(pkgdata_DATA)
if USE_COVERAGE
@@ -51,6 +53,7 @@ libgnunet_plugin_gnsrecord_abd_la_SOURCES = \
libgnunet_plugin_gnsrecord_abd_la_LIBADD = \
libgnunetabd.la \
$(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
$(LTLIBINTL)
libgnunet_plugin_gnsrecord_abd_la_LDFLAGS = \
$(GN_PLUGIN_LDFLAGS)
@@ -64,6 +67,7 @@ gnunet_service_abd_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/gns/libgnunetgns.la \
$(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(GN_LIBINTL)
@@ -75,7 +79,9 @@ libgnunetabd_la_SOURCES = \
delegate_misc.c \
delegate_misc.h
libgnunetabd_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/identity/libgnunetidentity.la \
+ $(XLIB)
libgnunetabd_la_LDFLAGS = \
$(GN_LIB_LDFLAGS)
diff --git a/src/abd/abd.h b/src/abd/abd.h
index 0af0d43ca..61210b3f7 100644
--- a/src/abd/abd.h
+++ b/src/abd/abd.h
@@ -42,12 +42,12 @@ struct CollectMessage
/**
* Subject public key
*/
- struct GNUNET_CRYPTO_EcdsaPrivateKey subject_key;
+ struct GNUNET_IDENTITY_PrivateKey subject_key;
/**
* Trust anchor
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+ struct GNUNET_IDENTITY_PublicKey issuer_key;
/**
* Length of the issuer attribute
@@ -81,12 +81,12 @@ struct VerifyMessage
/**
* Subject public key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+ struct GNUNET_IDENTITY_PublicKey subject_key;
/**
* Trust anchor
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+ struct GNUNET_IDENTITY_PublicKey issuer_key;
/**
* Number of delegates
@@ -170,7 +170,7 @@ struct DelegationRecordData
/**
* Subject key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+ struct GNUNET_IDENTITY_PublicKey subject_key;
/**
* Subject attributes
@@ -184,12 +184,12 @@ struct ChainEntry
/**
* Issuer key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+ struct GNUNET_IDENTITY_PublicKey issuer_key;
/**
* Subject key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+ struct GNUNET_IDENTITY_PublicKey subject_key;
/**
* Issuer attributes
@@ -203,46 +203,12 @@ struct ChainEntry
};
-struct CredentialEntry
+struct DelegateEntry
{
-
/**
* The signature for this credential by the issuer
*/
- struct GNUNET_CRYPTO_EcdsaSignature signature;
-
- /**
- * Signature meta
- */
- struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
-
- /**
- * Public key of the issuer
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
-
- /**
- * Public key of the subject this credential was issued to
- */
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
-
- /**
- * Expiration time of this credential
- */
- uint64_t expiration GNUNET_PACKED;
-
- /**
- * Issuer attribute length
- */
- uint32_t issuer_attribute_len;
-
- /**
- * Followed by the attribute string
- */
-};
-
-struct DelegateEntry
-{
+ struct GNUNET_IDENTITY_Signature signature;
/**
* Signature meta
@@ -250,19 +216,14 @@ struct DelegateEntry
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
- * The signature for this credential by the issuer
- */
- struct GNUNET_CRYPTO_EcdsaSignature signature;
-
- /**
* Public key of the issuer
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+ struct GNUNET_IDENTITY_PublicKey issuer_key;
/**
* Public key of the subject this credential was issued to
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+ struct GNUNET_IDENTITY_PublicKey subject_key;
/**
* Expiration time of this credential
diff --git a/src/abd/abd_api.c b/src/abd/abd_api.c
index cc25d06da..57f831e85 100644
--- a/src/abd/abd_api.c
+++ b/src/abd/abd_api.c
@@ -423,9 +423,9 @@ GNUNET_ABD_request_cancel (struct GNUNET_ABD_Request *lr)
struct GNUNET_ABD_Request *
GNUNET_ABD_collect (
struct GNUNET_ABD_Handle *handle,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const struct GNUNET_IDENTITY_PublicKey *issuer_key,
const char *issuer_attribute,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *subject_key,
+ const struct GNUNET_IDENTITY_PrivateKey *subject_key,
enum GNUNET_ABD_AlgoDirectionFlags direction,
GNUNET_ABD_CredentialResultProcessor proc,
void *proc_cls,
@@ -497,9 +497,9 @@ GNUNET_ABD_collect (
struct GNUNET_ABD_Request *
GNUNET_ABD_verify (
struct GNUNET_ABD_Handle *handle,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key,
+ const struct GNUNET_IDENTITY_PublicKey *issuer_key,
const char *issuer_attribute,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *subject_key,
+ const struct GNUNET_IDENTITY_PublicKey *subject_key,
uint32_t delegate_count,
const struct GNUNET_ABD_Delegate *delegates,
enum GNUNET_ABD_AlgoDirectionFlags direction,
diff --git a/src/abd/abd_serialization.c b/src/abd/abd_serialization.c
index c03fab7dc..2ed24ff2f 100644
--- a/src/abd/abd_serialization.c
+++ b/src/abd/abd_serialization.c
@@ -191,15 +191,15 @@ GNUNET_ABD_delegates_serialize (
off = 0;
for (i = 0; i < c_count; i++)
{
- // c_rec.subject_attribute_len = htonl ((uint32_t) cd[i].subject_attribute_len);
- c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
+ c_rec.subject_attribute_len = htonl (cd[i].subject_attribute_len);
+ c_rec.issuer_attribute_len = htonl (cd[i].issuer_attribute_len);
c_rec.issuer_key = cd[i].issuer_key;
c_rec.subject_key = cd[i].subject_key;
c_rec.signature = cd[i].signature;
c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
c_rec.purpose.size =
htonl ((sizeof (struct DelegateEntry) + cd[i].issuer_attribute_len)
- - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ - sizeof (struct GNUNET_IDENTITY_Signature));
c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
if (off + sizeof (c_rec) > dest_size)
return -1;
@@ -445,13 +445,13 @@ GNUNET_ABD_delegate_serialize (struct GNUNET_ABD_Delegate *dele,
}
cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
cdata->purpose.size =
- htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ htonl (size - sizeof (struct GNUNET_IDENTITY_Signature));
GNUNET_memcpy (&cdata[1], tmp_str, attr_len);
if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
- cdata,
+ GNUNET_IDENTITY_signature_verify_ (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
+ &cdata->purpose,
&cdata->signature,
&cdata->issuer_key))
{
@@ -473,8 +473,8 @@ GNUNET_ABD_delegate_deserialize (const char *data, size_t data_size)
return NULL;
cdata = (struct DelegateEntry *) data;
if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
- cdata,
+ GNUNET_IDENTITY_signature_verify_ (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
+ &cdata->purpose,
&cdata->signature,
&cdata->issuer_key))
{
diff --git a/src/abd/delegate_misc.c b/src/abd/delegate_misc.c
index 4740a3e30..0c5520d52 100644
--- a/src/abd/delegate_misc.c
+++ b/src/abd/delegate_misc.c
@@ -42,10 +42,10 @@ GNUNET_ABD_delegate_to_string (
char *issuer_pkey;
char *signature;
- subject_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
- issuer_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
+ subject_pkey = GNUNET_IDENTITY_public_key_to_string (&cred->subject_key);
+ issuer_pkey = GNUNET_IDENTITY_public_key_to_string (&cred->issuer_key);
GNUNET_STRINGS_base64_encode ((char *) &cred->signature,
- sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
+ sizeof (struct GNUNET_IDENTITY_Signature),
&signature);
if (0 == cred->subject_attribute_len)
{
@@ -80,7 +80,7 @@ struct GNUNET_ABD_Delegate *
GNUNET_ABD_delegate_from_string (const char *s)
{
struct GNUNET_ABD_Delegate *dele;
- size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
+ size_t enclen = (sizeof (struct GNUNET_IDENTITY_PublicKey)) * 8;
if (enclen % 5 > 0)
enclen += 5 - enclen % 5;
enclen /= 5; /* 260/5 = 52 */
@@ -91,12 +91,12 @@ GNUNET_ABD_delegate_from_string (const char *s)
char sub_attr[253 + 1] = "";
char signature[256]; // TODO max payload size
- struct GNUNET_CRYPTO_EcdsaSignature *sig;
+ struct GNUNET_IDENTITY_Signature *sig;
struct GNUNET_TIME_Absolute etime_abs;
// If it's A.a <- B.b...
if (6 != sscanf (s,
- "%52s.%253s -> %52s.%253s | %s | %" SCNu64,
+ "%58s.%253s -> %58s.%253s | %s | %" SCNu64,
issuer_pkey,
iss_attr,
subject_pkey,
@@ -106,7 +106,7 @@ GNUNET_ABD_delegate_from_string (const char *s)
{
// Try if it's A.a <- B
if (5 != sscanf (s,
- "%52s.%253s -> %52s | %s | %" SCNu64,
+ "%58s.%253s -> %58s | %s | %" SCNu64,
issuer_pkey,
iss_attr,
subject_pkey,
@@ -143,13 +143,21 @@ GNUNET_ABD_delegate_from_string (const char *s)
}
tmp_str[attr_len - 1] = '\0';
- GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
- strlen (subject_pkey),
- &dele->subject_key);
- GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_pkey,
- strlen (issuer_pkey),
- &dele->issuer_key);
- GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdsaSignature) ==
+ if (GNUNET_SYSERR ==
+ GNUNET_IDENTITY_public_key_from_string (subject_pkey,
+ &dele->subject_key))
+ {
+ GNUNET_free (dele);
+ return NULL;
+ }
+ if (GNUNET_SYSERR ==
+ GNUNET_IDENTITY_public_key_from_string (issuer_pkey,
+ &dele->issuer_key))
+ {
+ GNUNET_free (dele);
+ return NULL;
+ }
+ GNUNET_assert (sizeof (struct GNUNET_IDENTITY_Signature) ==
GNUNET_STRINGS_base64_decode (signature,
strlen (signature),
(void **) &sig));
@@ -187,8 +195,8 @@ GNUNET_ABD_delegate_from_string (const char *s)
struct GNUNET_ABD_Delegate *
GNUNET_ABD_delegate_issue (
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
- struct GNUNET_CRYPTO_EcdsaPublicKey *subject,
+ const struct GNUNET_IDENTITY_PrivateKey *issuer,
+ struct GNUNET_IDENTITY_PublicKey *subject,
const char *iss_attr,
const char *sub_attr,
struct GNUNET_TIME_Absolute *expiration)
@@ -223,9 +231,9 @@ GNUNET_ABD_delegate_issue (
del = GNUNET_malloc (size);
del->purpose.size =
- htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
+ htonl (size - sizeof (struct GNUNET_IDENTITY_Signature));
del->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
- GNUNET_CRYPTO_ecdsa_key_get_public (issuer, &del->issuer_key);
+ GNUNET_IDENTITY_key_get_public (issuer, &del->issuer_key);
del->subject_key = *subject;
del->expiration = GNUNET_htonll (expiration->abs_value_us);
del->issuer_attribute_len = htonl (strlen (iss_attr) + 1);
@@ -240,12 +248,12 @@ GNUNET_ABD_delegate_issue (
GNUNET_memcpy (&del[1], tmp_str, attr_len);
- GNUNET_CRYPTO_ecdsa_sign (issuer, del, &del->signature);
+ GNUNET_IDENTITY_sign_ (issuer, &del->purpose, &del->signature);
dele = GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate) + attr_len);
dele->signature = del->signature;
dele->expiration = *expiration;
- GNUNET_CRYPTO_ecdsa_key_get_public (issuer, &dele->issuer_key);
+ GNUNET_IDENTITY_key_get_public (issuer, &dele->issuer_key);
dele->subject_key = *subject;
diff --git a/src/abd/gnunet-abd.c b/src/abd/gnunet-abd.c
index b1fb767e3..9f5fef958 100644
--- a/src/abd/gnunet-abd.c
+++ b/src/abd/gnunet-abd.c
@@ -43,7 +43,7 @@ static struct GNUNET_NAMESTORE_Handle *ns;
/**
* Private key for the our zone.
*/
-static struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey;
+static struct GNUNET_IDENTITY_PrivateKey zone_pkey;
/**
* EgoLookup
@@ -98,12 +98,12 @@ static char *expiration;
/**
* Subject key
*/
-struct GNUNET_CRYPTO_EcdsaPublicKey subject_pkey;
+struct GNUNET_IDENTITY_PublicKey subject_pkey;
/**
* Issuer key
*/
-struct GNUNET_CRYPTO_EcdsaPublicKey issuer_pkey;
+struct GNUNET_IDENTITY_PublicKey issuer_pkey;
/**
@@ -206,11 +206,6 @@ static uint64_t etime;
static int etime_is_rel = GNUNET_SYSERR;
/**
- * Fixed size of the public/private keys
- */
-static const int key_length = 52;
-
-/**
* Record label for storing delegations
*/
static char *record_label;
@@ -282,9 +277,9 @@ handle_intermediate_result (void *cls,
printf ("%s Intermediate result: %s.%s <- %s.%s\n",
prefix,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&dd->issuer_key),
+ GNUNET_IDENTITY_public_key_to_string (&dd->issuer_key),
dd->issuer_attribute,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&dd->subject_key),
+ GNUNET_IDENTITY_public_key_to_string (&dd->subject_key),
dd->subject_attribute);
}
@@ -337,8 +332,8 @@ handle_verify_result (void *cls,
printf ("Delegation Chain:\n");
for (i = 0; i < d_count; i++)
{
- iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].issuer_key);
- sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dc[i].subject_key);
+ iss_key = GNUNET_IDENTITY_public_key_to_string (&dc[i].issuer_key);
+ sub_key = GNUNET_IDENTITY_public_key_to_string (&dc[i].subject_key);
if (0 != dc[i].subject_attribute_len)
{
@@ -363,8 +358,8 @@ handle_verify_result (void *cls,
printf ("\nDelegate(s):\n");
for (i = 0; i < c_count; i++)
{
- iss_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dele[i].issuer_key);
- sub_key = GNUNET_CRYPTO_ecdsa_public_key_to_string (&dele[i].subject_key);
+ iss_key = GNUNET_IDENTITY_public_key_to_string (&dele[i].issuer_key);
+ sub_key = GNUNET_IDENTITY_public_key_to_string (&dele[i].subject_key);
printf ("%s.%s <- %s\n", iss_key, dele[i].issuer_attribute, sub_key);
GNUNET_free (iss_key);
GNUNET_free (sub_key);
@@ -386,7 +381,7 @@ handle_verify_result (void *cls,
static void
identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
{
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
+ const struct GNUNET_IDENTITY_PrivateKey *privkey;
el = NULL;
if (NULL == ego)
@@ -405,8 +400,7 @@ identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
{
if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
- strlen (issuer_key),
+ GNUNET_IDENTITY_public_key_from_string (issuer_key,
&issuer_pkey))
{
fprintf (stderr,
@@ -507,7 +501,7 @@ add_continuation (void *cls, int32_t success, const char *emsg)
static void
get_existing_record (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
+ const struct GNUNET_IDENTITY_PrivateKey *zone_key,
const char *rec_name,
unsigned int rd_count,
const struct GNUNET_GNSRECORD_Data *rd)
@@ -550,6 +544,10 @@ static void
store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
{
const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct GNUNET_ABD_Delegate *cred;
+ struct GNUNET_IDENTITY_PublicKey zone_pubkey;
+ char *subject_pubkey_str;
+ char *zone_pubkey_str;
el = NULL;
@@ -562,30 +560,45 @@ store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
return;
}
+ if (NULL == ego)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Ego does not exist!\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
// Key handling
zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
if (GNUNET_GNSRECORD_TYPE_DELEGATE == type)
{
// Parse import
- struct GNUNET_ABD_Delegate *cred;
cred = GNUNET_ABD_delegate_from_string (import);
+ if (NULL == cred)
+ {
+ fprintf (stderr,
+ "%s is not a valid credential\n", import);
+ GNUNET_SCHEDULER_shutdown();
+ return;
+ }
+
// Get import subject public key string
- char *subject_pubkey_str =
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
+ subject_pubkey_str =
+ GNUNET_IDENTITY_public_key_to_string (&cred->subject_key);
// Get zone public key string
- struct GNUNET_CRYPTO_EcdsaPublicKey zone_pubkey;
GNUNET_IDENTITY_ego_get_public_key (ego, &zone_pubkey);
- char *zone_pubkey_str =
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&zone_pubkey);
+ zone_pubkey_str =
+ GNUNET_IDENTITY_public_key_to_string (&zone_pubkey);
// Check if the subject key in the signed import matches the zone's key it is issued to
if (strcmp (zone_pubkey_str, subject_pubkey_str) != 0)
{
fprintf (stderr,
"Import signed delegate does not match this ego's public key.\n");
+ GNUNET_free (cred);
GNUNET_SCHEDULER_shutdown ();
return;
}
@@ -606,12 +619,12 @@ store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
{
if (typestring == NULL)
{
- fputs ("No value for unknown record type\n", stderr);
+ fputs ("Value for unknown record type not well-formed.\n", stderr);
}
else if (subject == NULL)
{
fprintf (stderr,
- "No value for record type`%s'\n",
+ "Value for record type `%s' not well-formed.\n",
typestring);
}
else
@@ -655,7 +668,7 @@ store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
static void
sign_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
{
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
+ const struct GNUNET_IDENTITY_PrivateKey *privkey;
struct GNUNET_ABD_Delegate *dele;
struct GNUNET_TIME_Absolute etime_abs;
char *res;
@@ -686,16 +699,7 @@ sign_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
// Subject Public Key
token = strtok (subject, " ");
- if (key_length == strlen (token))
- {
- subject_pubkey_str = token;
- }
- else
- {
- fprintf (stderr, "Key error, wrong length: %ld!\n", strlen (token));
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
+ subject_pubkey_str = token;
// Subject Attribute(s)
token = strtok (NULL, " ");
if (NULL != token)
@@ -706,9 +710,15 @@ sign_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
// work on keys
privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+ if (NULL == subject_pubkey_str)
+ {
+ fprintf (stderr,
+ "Subject pubkey not given\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pubkey_str,
- strlen (subject_pubkey_str),
+ GNUNET_IDENTITY_public_key_from_string (subject_pubkey_str,
&subject_pkey))
{
fprintf (stderr,
@@ -873,8 +883,7 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
- if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (subject,
- strlen (subject),
+ if (GNUNET_OK != GNUNET_IDENTITY_public_key_from_string (subject,
&subject_pkey))
{
fprintf (stderr,
@@ -893,8 +902,7 @@ run (void *cls,
return;
}
if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (issuer_key,
- strlen (issuer_key),
+ GNUNET_IDENTITY_public_key_from_string (issuer_key,
&issuer_pkey))
{
fprintf (stderr,
diff --git a/src/abd/gnunet-service-abd.c b/src/abd/gnunet-service-abd.c
index 93368da45..407d5bdc3 100644
--- a/src/abd/gnunet-service-abd.c
+++ b/src/abd/gnunet-service-abd.c
@@ -61,12 +61,12 @@ struct DelegationChainEntry
/**
* The issuer
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+ struct GNUNET_IDENTITY_PublicKey issuer_key;
/**
* The subject
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+ struct GNUNET_IDENTITY_PublicKey subject_key;
/**
* The issued attribute
@@ -166,7 +166,7 @@ struct DelegationSetQueueEntry
/**
* Issuer key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey *issuer_key;
+ struct GNUNET_IDENTITY_PublicKey *issuer_key;
/**
* Queue entries of this set
@@ -267,7 +267,7 @@ struct VerifyRequestHandle
/**
* Issuer public key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
+ struct GNUNET_IDENTITY_PublicKey issuer_key;
/**
* Issuer attribute
@@ -277,7 +277,7 @@ struct VerifyRequestHandle
/**
* Subject public key
*/
- struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
+ struct GNUNET_IDENTITY_PublicKey subject_key;
/**
* Delegate DLL
@@ -352,10 +352,10 @@ print_deleset (struct DelegationSetQueueEntry *dsentry, char *text)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"%s %s.%s <- %s.%s\n",
text,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
+ GNUNET_IDENTITY_public_key_to_string (
&dsentry->delegation_chain_entry->issuer_key),
dsentry->delegation_chain_entry->issuer_attribute,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
+ GNUNET_IDENTITY_public_key_to_string (
&dsentry->delegation_chain_entry->subject_key),
dsentry->delegation_chain_entry->subject_attribute);
}
@@ -512,6 +512,8 @@ send_intermediate_response (struct VerifyRequestHandle *vrh, struct
size,
(char *) &rmsg[1]));
GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (vrh->client), env);
+
+ GNUNET_free (dd);
}
@@ -697,7 +699,7 @@ handle_bidirectional_match (struct DelegationSetQueueEntry *actual_entry,
{
if (0 != memcmp (&last_entry->delegation_chain_entry->subject_key,
&del_entry->delegate->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
continue;
if (0 != strcmp (last_entry->delegation_chain_entry->subject_attribute,
del_entry->delegate->issuer_attribute))
@@ -740,12 +742,13 @@ forward_resolution (void *cls,
uint32_t rd_count,
const struct GNUNET_GNSRECORD_Data *rd)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
-
struct VerifyRequestHandle *vrh;
struct DelegationSetQueueEntry *current_set;
struct DelegationSetQueueEntry *ds_entry;
struct DelegationQueueEntry *dq_entry;
+ struct GNUNET_ABD_Delegate *del;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d entries.\n", rd_count);
current_set = cls;
// set handle to NULL (as el = NULL)
@@ -760,9 +763,11 @@ forward_resolution (void *cls,
continue;
// Start deserialize into Delegate
- struct GNUNET_ABD_Delegate *del;
del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
+ if (NULL == del)
+ continue;
+
// Start: Create DQ Entry
dq_entry = GNUNET_new (struct DelegationQueueEntry);
// AND delegations are not possible, only 1 solution
@@ -828,12 +833,13 @@ forward_resolution (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Entry not relevant, discarding: %s.%s <- %s.%s\n",
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
+ GNUNET_IDENTITY_public_key_to_string (
&del->issuer_key),
del->issuer_attribute,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
+ GNUNET_IDENTITY_public_key_to_string (
&del->subject_key),
del->subject_attribute);
+ GNUNET_free (del);
continue;
}
else
@@ -844,10 +850,10 @@ forward_resolution (void *cls,
// Start: Credential Chain Entry
// issuer key is subject key, who needs to be contacted to resolve this (forward, therefore subject)
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
GNUNET_memcpy (ds_entry->issuer_key,
&del->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ sizeof (struct GNUNET_IDENTITY_PublicKey));
ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
ds_entry->delegation_chain_entry->subject_key = del->subject_key;
@@ -868,7 +874,7 @@ forward_resolution (void *cls,
// if: issuer key we looking for
if (0 == memcmp (&del->issuer_key,
&vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
{
// if: issuer attr we looking for
if (0 == strcmp (del->issuer_attribute, vrh->issuer_attribute))
@@ -899,7 +905,7 @@ forward_resolution (void *cls,
{
if (0 == memcmp (&del_entry->delegate->issuer_key,
&vrh->delegation_chain_head->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
{
if (0 == strcmp (del_entry->delegate->issuer_attribute,
vrh->delegation_chain_head->subject_attribute))
@@ -910,6 +916,7 @@ forward_resolution (void *cls,
}
send_lookup_response (vrh);
+ GNUNET_free (del);
return;
}
}
@@ -926,7 +933,7 @@ forward_resolution (void *cls,
// key of list entry matches actual key
if (0 == memcmp (&del_entry->delegation_chain_entry->subject_key,
&ds_entry->delegation_chain_entry->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
{
// compare entry subject attributes to this trailer (iss attr + old trailer)
if (0 == strcmp (del_entry->unresolved_attribute_delegation,
@@ -936,6 +943,7 @@ forward_resolution (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Forward: Found match with above!\n");
+ GNUNET_free (del);
// one node on the path still needs solutions: return
if (GNUNET_NO ==
handle_bidirectional_match (ds_entry, del_entry, vrh))
@@ -955,7 +963,7 @@ forward_resolution (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting to look up trailer %s in zone %s\n",
ds_entry->attr_trailer,
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&del->issuer_key));
+ GNUNET_IDENTITY_public_key_to_string (&del->issuer_key));
ds_entry->lookup_request =
GNUNET_GNS_lookup (gns,
@@ -965,6 +973,7 @@ forward_resolution (void *cls,
GNUNET_GNS_LO_DEFAULT,
&forward_resolution,
ds_entry);
+ GNUNET_free (del);
}
if (0 == vrh->pending_lookups)
@@ -1064,10 +1073,10 @@ backward_resolution (void *cls,
ds_entry->delegation_chain_entry =
GNUNET_new (struct DelegationChainEntry);
ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
GNUNET_memcpy (ds_entry->issuer_key,
&set[j].subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ sizeof (struct GNUNET_IDENTITY_PublicKey));
if (0 < set[j].subject_attribute_len)
ds_entry->delegation_chain_entry->subject_attribute =
GNUNET_strdup (set[j].subject_attribute);
@@ -1091,7 +1100,7 @@ backward_resolution (void *cls,
// If key and attribute match credential: continue and backtrack
if (0 != memcmp (&set[j].subject_key,
&del_pointer->delegate->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
continue;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Checking if %s matches %s\n",
@@ -1173,7 +1182,7 @@ backward_resolution (void *cls,
// key of list entry matches actual key
if (0 == memcmp (&del_entry->delegation_chain_entry->issuer_key,
&ds_entry->delegation_chain_entry->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
{
// compare entry subject attributes to this trailer (iss attr + old trailer)
if (0 == strcmp (del_entry->attr_trailer,
@@ -1262,7 +1271,7 @@ delegation_chain_bw_resolution_start (void *cls)
{
if (0 != memcmp (&del_entry->delegate->issuer_key,
&vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
continue;
if (0 !=
strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
@@ -1284,10 +1293,10 @@ delegation_chain_bw_resolution_start (void *cls)
ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
ds_entry->from_bw = true;
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
GNUNET_memcpy (ds_entry->issuer_key,
&vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ sizeof (struct GNUNET_IDENTITY_PublicKey));
ds_entry->issuer_attribute = GNUNET_strdup (vrh->issuer_attribute);
ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
@@ -1344,7 +1353,7 @@ delegation_chain_fw_resolution_start (void *cls)
{
if (0 != memcmp (&del_entry->delegate->issuer_key,
&vrh->issuer_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ sizeof (struct GNUNET_IDENTITY_PublicKey)))
continue;
if (0 !=
strcmp (del_entry->delegate->issuer_attribute, vrh->issuer_attribute))
@@ -1366,17 +1375,17 @@ delegation_chain_fw_resolution_start (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Looking for %s.%s\n",
- GNUNET_CRYPTO_ecdsa_public_key_to_string (
+ GNUNET_IDENTITY_public_key_to_string (
&del_entry->delegate->issuer_key),
del_entry->delegate->issuer_attribute);
ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
GNUNET_CONTAINER_DLL_insert (vrh->dsq_head, vrh->dsq_tail, ds_entry);
ds_entry->from_bw = false;
- ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
GNUNET_memcpy (ds_entry->issuer_key,
&del_entry->delegate->subject_key,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ sizeof (struct GNUNET_IDENTITY_PublicKey));
ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
ds_entry->delegation_chain_entry->subject_key =
@@ -1580,40 +1589,35 @@ delegate_collection_finished (void *cls)
static void
handle_delegate_collection_cb (void *cls,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+ const struct GNUNET_IDENTITY_PrivateKey *key,
const char *label,
unsigned int rd_count,
const struct GNUNET_GNSRECORD_Data *rd)
{
struct VerifyRequestHandle *vrh = cls;
- struct GNUNET_ABD_Delegate *del;
struct DelegateRecordEntry *del_entry;
- int cred_record_count;
- cred_record_count = 0;
vrh->dele_qe = NULL;
for (uint32_t i = 0; i < rd_count; i++)
{
if (GNUNET_GNSRECORD_TYPE_DELEGATE != rd[i].record_type)
continue;
- cred_record_count++;
- del = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
- if (NULL == del)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
- continue;
- }
// only add the entries that are explicitly marked as private
// and therefore symbolize the end of a chain
- if (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)
+ if (0 == (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))
+ continue;
+ del_entry = GNUNET_new (struct DelegateRecordEntry);
+ del_entry->delegate = GNUNET_ABD_delegate_deserialize (rd[i].data, rd[i].data_size);
+ if (NULL == del_entry->delegate)
{
- del_entry = GNUNET_new (struct DelegateRecordEntry);
- del_entry->delegate = del;
- GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
- vrh->del_chain_tail,
- del_entry);
- vrh->del_chain_size++;
+ GNUNET_free (del_entry);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid delegate found\n");
+ continue;
}
+ GNUNET_CONTAINER_DLL_insert_tail (vrh->del_chain_head,
+ vrh->del_chain_tail,
+ del_entry);
+ vrh->del_chain_size++;
}
delegate_collection_finished (vrh);
@@ -1643,7 +1647,7 @@ handle_collect (void *cls, const struct CollectMessage *c_msg)
vrh->client = client;
vrh->request_id = c_msg->id;
vrh->issuer_key = c_msg->issuer_key;
- GNUNET_CRYPTO_ecdsa_key_get_public (&c_msg->subject_key, &vrh->subject_key);
+ GNUNET_IDENTITY_key_get_public (&c_msg->subject_key, &vrh->subject_key);
vrh->issuer_attribute = GNUNET_strdup (issuer_attribute);
vrh->resolution_algo = ntohs (c_msg->resolution_algo);
diff --git a/src/abd/plugin_gnsrecord_abd.c b/src/abd/plugin_gnsrecord_abd.c
index 25dc20152..7b2f4af5b 100644
--- a/src/abd/plugin_gnsrecord_abd.c
+++ b/src/abd/plugin_gnsrecord_abd.c
@@ -77,7 +77,7 @@ abd_value_to_string (void *cls,
for (i = 0; i < ntohl (sets.set_count); i++)
{
subject_pkey =
- GNUNET_CRYPTO_ecdsa_public_key_to_string (&set[i].subject_key);
+ GNUNET_IDENTITY_public_key_to_string (&set[i].subject_key);
if (0 == set[i].subject_attribute_len)
{
@@ -158,7 +158,7 @@ abd_string_to_value (void *cls,
{
struct GNUNET_ABD_DelegationRecord *sets;
char attr_str[253 + 1];
- char subject_pkey[52 + 1];
+ char subject_pkey[58 + 1];
char *token;
char *tmp_str;
int matches = 0;
@@ -207,9 +207,13 @@ abd_string_to_value (void *cls,
matches = sscanf (token, "%s %s", subject_pkey, attr_str);
// sets the public key for the set entry
- GNUNET_CRYPTO_ecdsa_public_key_from_string (subject_pkey,
- strlen (subject_pkey),
- &set[i].subject_key);
+ if (GNUNET_SYSERR ==
+ GNUNET_IDENTITY_public_key_from_string (subject_pkey,
+ &set[i].subject_key))
+ {
+ GNUNET_free (tmp_str);
+ return GNUNET_SYSERR;
+ }
// If not just key, also set subject attribute (Not A.a <- B but A.a <- B.b)
if (2 == matches)
@@ -253,7 +257,7 @@ abd_string_to_value (void *cls,
cred = GNUNET_ABD_delegate_from_string (s);
*data_size = GNUNET_ABD_delegate_serialize (cred, (char **) data);
-
+ GNUNET_free (cred);
return GNUNET_OK;
}
default:
diff --git a/src/abd/test_abd_bi_and.sh b/src/abd/test_abd_bi_and.sh
index b32313636..99c89a344 100755
--- a/src/abd/test_abd_bi_and.sh
+++ b/src/abd/test_abd_bi_and.sh
@@ -55,16 +55,16 @@ gnunet-namestore -D -z b
gnunet-abd --createIssuerSide --ego=g --attribute="g" --subject="$HKEY h" --ttl=5m -c test_abd_lookup.conf
gnunet-namestore -D -z b
-SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2049-12-12 10:00:00"`
gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
gnunet-namestore -D -z d
-SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2049-12-12 10:00:00"`
gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
gnunet-namestore -D -z e
-SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2049-12-12 10:00:00"`
gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
gnunet-namestore -D -z f
-SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=h --attribute="h" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=h --attribute="h" --subject="$FKEY" --ttl="2049-12-12 10:00:00"`
gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
gnunet-namestore -D -z h
diff --git a/src/abe/Makefile.am b/src/abe/Makefile.am
deleted file mode 100644
index cccd3ccb0..000000000
--- a/src/abe/Makefile.am
+++ /dev/null
@@ -1,49 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-plugindir = $(libdir)/gnunet
-
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-if USE_COVERAGE
- AM_CFLAGS = --coverage -O0
- XLIB = -lgcov
-endif
-
-libgnunetabe_la_SOURCES = abe.c
-
-libgnunetabe_la_LIBADD = \
- $(GCLIBADD)\
- $(LIBGCRYPT_LIBS) \
- $(LTLIBICONV) \
- $(LTLIBINTL) \
- $(ABE_LIBADD) \
- $(top_builddir)/src/util/libgnunetutil.la \
- -lgmp \
- -lgabe \
- -lpbc \
- -lglib-2.0 \
- -lltdl $(Z_LIBS) -lunistring $(XLIB)
-
-libgnunetabe_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS) \
- -version-info 1:0:0
-
-lib_LTLIBRARIES = libgnunetabe.la
-
-if ENABLE_TEST_RUN
-AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
-TESTS = $(check_PROGRAMS)
-endif
-
-check_PROGRAMS = test_cpabe
-
-test_cpabe_SOURCES = \
- test_cpabe.c
-test_cpabe_LDADD = \
- libgnunetabe.la \
- $(top_builddir)/src/util/libgnunetutil.la
-check_PROGRAMS += \
- test_cpabe
diff --git a/src/abe/abe.c b/src/abe/abe.c
deleted file mode 100644
index a03944821..000000000
--- a/src/abe/abe.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- This file is part of GNUnet. Copyright (C) 2001-2018 Christian Grothoff
- (and other contributing authors)
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
-
- */
-
-/**
- * @file abe/abe.c
- * @brief functions for Attribute-Based Encryption
- * @author Martin Schanzenbach
- */
-
-
-#include "platform.h"
-#include <pbc/pbc.h>
-#include <gabe.h>
-
-#include "gnunet_crypto_lib.h"
-#include "gnunet_abe_lib.h"
-
-struct GNUNET_ABE_AbeMasterKey
-{
- gabe_pub_t*pub;
- gabe_msk_t*msk;
-};
-
-struct GNUNET_ABE_AbeKey
-{
- gabe_pub_t*pub;
- gabe_prv_t*prv;
-};
-
-static int
-init_aes (element_t k, int enc,
- gcry_cipher_hd_t*handle,
- struct GNUNET_CRYPTO_SymmetricSessionKey *key,
- unsigned char*iv)
-{
- int rc;
- int key_len;
- unsigned char*key_buf;
-
- key_len = element_length_in_bytes (k) < 33 ? 3 : element_length_in_bytes (k);
- key_buf = (unsigned char *) malloc (key_len);
- element_to_bytes (key_buf, k);
-
- GNUNET_memcpy (key->aes_key, key_buf, GNUNET_CRYPTO_AES_KEY_LENGTH);
- GNUNET_assert (0 ==
- gcry_cipher_open (handle, GCRY_CIPHER_AES256,
- GCRY_CIPHER_MODE_CFB, 0));
- rc = gcry_cipher_setkey (*handle,
- key->aes_key,
- sizeof(key->aes_key));
- GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
- memset (iv, 0, 16); // TODO make reasonable
- rc = gcry_cipher_setiv (*handle,
- iv,
- 16);
- GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
-
- free (key_buf);
- return rc;
-}
-
-
-static int
-aes_128_cbc_encrypt (char*pt,
- int size,
- element_t k,
- char **ct)
-{
- gcry_cipher_hd_t handle;
- struct GNUNET_CRYPTO_SymmetricSessionKey skey;
- unsigned char iv[16];
- char*buf;
- int padding;
- int buf_size;
- uint8_t len[4];
-
- init_aes (k, 1, &handle, &skey, iv);
-
- /* TODO make less crufty */
-
- /* stuff in real length (big endian) before padding */
- len[0] = (size & 0xff000000) >> 24;
- len[1] = (size & 0xff0000) >> 16;
- len[2] = (size & 0xff00) >> 8;
- len[3] = (size & 0xff) >> 0;
- padding = 16 - ((4 + size) % 16);
- buf_size = 4 + size + padding;
- buf = GNUNET_malloc (buf_size);
- GNUNET_memcpy (buf, len, 4);
- GNUNET_memcpy (buf + 4, pt, size);
- *ct = GNUNET_malloc (buf_size);
-
- GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf,
- buf_size));
- gcry_cipher_close (handle);
- // AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
- GNUNET_free (buf);
- return buf_size;
-}
-
-
-static int
-aes_128_cbc_decrypt (char*ct,
- int size,
- element_t k,
- char **pt)
-{
- struct GNUNET_CRYPTO_SymmetricSessionKey skey;
- gcry_cipher_hd_t handle;
- unsigned char iv[16];
- char*tmp;
- uint32_t len;
-
- init_aes (k, 1, &handle, &skey, iv);
-
- tmp = GNUNET_malloc (size);
-
- // AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
- GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
- gcry_cipher_close (handle);
- /* TODO make less crufty */
-
- /* get real length */
- len = 0;
- len = len
- | ((tmp[0]) << 24) | ((tmp[1]) << 16)
- | ((tmp[2]) << 8) | ((tmp[3]) << 0);
- /* truncate any garbage from the padding */
- *pt = GNUNET_malloc (len);
- GNUNET_memcpy (*pt, tmp + 4, len);
- GNUNET_free (tmp);
- return len;
-}
-
-
-/**
- * @ingroup abe
- * Create a new CP-ABE master key. Caller must free return value.
- *
- * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_master_key
- */
-struct GNUNET_ABE_AbeMasterKey*
-GNUNET_ABE_cpabe_create_master_key (void)
-{
- struct GNUNET_ABE_AbeMasterKey*key;
-
- key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
- gabe_setup (&key->pub, &key->msk);
- GNUNET_assert (NULL != key->pub);
- GNUNET_assert (NULL != key->msk);
- return key;
-}
-
-
-/**
- * @ingroup abe
- * Delete a CP-ABE master key.
- *
- * @param key the master key
- * @return fresh private key; free using #GNUNET_free
- */
-void
-GNUNET_ABE_cpabe_delete_master_key (struct GNUNET_ABE_AbeMasterKey *key)
-{
- gabe_msk_free (key->msk);
- gabe_pub_free (key->pub);
- // GNUNET_free (key->msk);
- // gabe_msk_free (key->msk); //For some reason free of pub implicit?
- GNUNET_free (key);
-}
-
-
-/**
- * @ingroup abe
- * Create a new CP-ABE key. Caller must free return value.
- *
- * @param key the master key
- * @param attrs the attributes to append to the key
- * @return fresh private key; free using #GNUNET_ABE_cpabe_delete_key
- */
-struct GNUNET_ABE_AbeKey*
-GNUNET_ABE_cpabe_create_key (struct GNUNET_ABE_AbeMasterKey *key,
- char **attrs)
-{
- struct GNUNET_ABE_AbeKey *prv_key;
- int size;
- char *tmp;
-
- prv_key = GNUNET_new (struct GNUNET_ABE_AbeKey);
- prv_key->prv = gabe_keygen (key->pub, key->msk, attrs);
- size = gabe_pub_serialize (key->pub, &tmp);
- prv_key->pub = gabe_pub_unserialize (tmp, size);
- GNUNET_free (tmp);
- GNUNET_assert (NULL != prv_key->prv);
- return prv_key;
-}
-
-
-/**
- * @ingroup abe
- * Delete a CP-ABE key.
- *
- * @param key the key to delete
- * @param delete_pub GNUNE_YES if the public key should also be freed (bug in gabe)
- * @return fresh private key; free using #GNUNET_free
- */
-void
-GNUNET_ABE_cpabe_delete_key (struct GNUNET_ABE_AbeKey *key,
- int delete_pub)
-{
- // Memory management in gabe is buggy
- gabe_prv_free (key->prv);
- if (GNUNET_YES == delete_pub)
- gabe_pub_free (key->pub);
- GNUNET_free (key);
-}
-
-
-static ssize_t
-write_cpabe (void **result,
- uint32_t file_len,
- char*cph_buf,
- int cph_buf_len,
- char*aes_buf,
- int aes_buf_len)
-{
- char *ptr;
- uint32_t *len;
-
- *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
- ptr = *result;
- len = (uint32_t *) ptr;
- *len = htonl (file_len);
- ptr += 4;
- len = (uint32_t *) ptr;
- *len = htonl (aes_buf_len);
- ptr += 4;
- GNUNET_memcpy (ptr, aes_buf, aes_buf_len);
- ptr += aes_buf_len;
- len = (uint32_t *) ptr;
- *len = htonl (cph_buf_len);
- ptr += 4;
- GNUNET_memcpy (ptr, cph_buf, cph_buf_len);
- return 12 + cph_buf_len + aes_buf_len;
-}
-
-
-static ssize_t
-read_cpabe (const void *data,
- char**cph_buf,
- int *cph_buf_len,
- char**aes_buf,
- int *aes_buf_len)
-{
- int buf_len;
- char *ptr;
- uint32_t *len;
-
- ptr = (char *) data;
- len = (uint32_t *) ptr;
- buf_len = ntohl (*len);
- ptr += 4;
- len = (uint32_t *) ptr;
- *aes_buf_len = ntohl (*len);
- ptr += 4;
- *aes_buf = GNUNET_malloc (*aes_buf_len);
- GNUNET_memcpy (*aes_buf, ptr, *aes_buf_len);
- ptr += *aes_buf_len;
- len = (uint32_t *) ptr;
- *cph_buf_len = ntohl (*len);
- ptr += 4;
- *cph_buf = GNUNET_malloc (*cph_buf_len);
- GNUNET_memcpy (*cph_buf, ptr, *cph_buf_len);
-
- return buf_len;
-}
-
-
-/**
- * @ingroup abe
- * Encrypt a block using sessionkey.
- *
- * @param block the block to encrypt
- * @param size the size of the @a block
- * @param policy the ABE policy
- * @param key the key used to encrypt
- * @param result the result buffer. Will be allocated. Free using #GNUNET_free
- * @return the size of the encrypted block, -1 for errors
- */
-ssize_t
-GNUNET_ABE_cpabe_encrypt (const void *block,
- size_t size,
- const char *policy,
- const struct GNUNET_ABE_AbeMasterKey *key,
- void **result)
-{
- gabe_cph_t*cph;
- char*plt;
- char*cph_buf;
- char*aes_buf;
- element_t m;
- int cph_buf_len;
- int aes_buf_len;
- ssize_t result_len;
-
- if (! (cph = gabe_enc (key->pub, m, (char *) policy)))
- return GNUNET_SYSERR;
- cph_buf_len = gabe_cph_serialize (cph,
- &cph_buf);
- gabe_cph_free (cph);
- GNUNET_free (cph);
- plt = GNUNET_memdup (block, size);
- aes_buf_len = aes_128_cbc_encrypt (plt, size, m, &aes_buf);
- GNUNET_free (plt);
- element_clear (m);
- result_len = write_cpabe (result, size, cph_buf, cph_buf_len, aes_buf,
- aes_buf_len);
- GNUNET_free (cph_buf);
- GNUNET_free (aes_buf);
- return result_len;
-}
-
-
-/**
- * @ingroup abe
- * Decrypt a block using the ABE key.
- *
- * @param block the block to encrypt
- * @param size the size of the @a block
- * @param key the key used to decrypt
- * @param result the result buffer. Will be allocated. Free using #GNUNET_free
- * @return the size of the encrypted block, -1 for errors
- */
-ssize_t
-GNUNET_ABE_cpabe_decrypt (const void *block,
- size_t size,
- const struct GNUNET_ABE_AbeKey *key,
- void **result)
-{
- char*aes_buf;
- char*cph_buf;
- gabe_cph_t*cph;
- element_t m;
- int cph_buf_size;
- int aes_buf_size;
- int plt_len;
-
- read_cpabe (block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
- cph = gabe_cph_unserialize (key->pub, cph_buf, cph_buf_size);
- if (! gabe_dec (key->pub, key->prv, cph, m))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s\n", gabe_error ());
- GNUNET_free (aes_buf);
- GNUNET_free (cph_buf);
- gabe_cph_free (cph);
- GNUNET_free (cph);
- element_clear (m);
- return GNUNET_SYSERR;
- }
- gabe_cph_free (cph);
- GNUNET_free (cph);
- plt_len = aes_128_cbc_decrypt (aes_buf, aes_buf_size, m, (char **) result);
- GNUNET_free (cph_buf);
- GNUNET_free (aes_buf);
- element_clear (m);
- // freeing is buggy in gabe
- // gabe_prv_free (prv);
- // gabe_pub_free (pub);
- return plt_len;
-}
-
-
-/**
- * @ingroup abe
- * Serialize an ABE key.
- *
- * @param key the key to serialize
- * @param result the result buffer. Will be allocated. Free using #GNUNET_free
- * @return the size of the encrypted block, -1 for errors
- */
-ssize_t
-GNUNET_ABE_cpabe_serialize_key (const struct GNUNET_ABE_AbeKey *key,
- void **result)
-{
- ssize_t len;
- char *pub;
- char *prv;
- int pub_len;
- int prv_len;
-
- pub_len = gabe_pub_serialize (key->pub, &pub);
- prv_len = gabe_prv_serialize (key->prv, &prv);
-
- len = pub_len + prv_len + 12;
- write_cpabe (result, len, pub, pub_len, prv, prv_len);
-
- GNUNET_free (pub);
- GNUNET_free (prv);
-
- return len;
-}
-
-
-/**
- * @ingroup abe
- * Deserialize a serialized ABE key.
- *
- * @param data the data to deserialize
- * @param len the length of the data.
- * @return the ABE key. NULL of unsuccessful
- */
-struct GNUNET_ABE_AbeKey*
-GNUNET_ABE_cpabe_deserialize_key (const void *data,
- size_t len)
-{
- struct GNUNET_ABE_AbeKey *key;
- char *pub;
- char *prv;
- int prv_len;
- int pub_len;
-
- key = GNUNET_new (struct GNUNET_ABE_AbeKey);
- read_cpabe (data,
- &pub,
- &pub_len,
- &prv,
- &prv_len);
- key->pub = gabe_pub_unserialize (pub, pub_len);
- key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
-
- GNUNET_free (pub);
- GNUNET_free (prv);
- return key;
-}
-
-
-/**
- * @ingroup abe
- * Serialize an ABE master key.
- *
- * @param key the key to serialize
- * @param result the result buffer. Will be allocated. Free using #GNUNET_free
- * @return the size of the encrypted block, -1 for errors
- */
-ssize_t
-GNUNET_ABE_cpabe_serialize_master_key (const struct
- GNUNET_ABE_AbeMasterKey *key,
- void **result)
-{
- ssize_t len;
- char *pub;
- char *msk;
- int pub_len;
- int msk_len;
-
- pub_len = gabe_pub_serialize (key->pub, &pub);
- msk_len = gabe_msk_serialize (key->msk, &msk);
-
- len = pub_len + msk_len + 12;
- write_cpabe (result, len, pub, pub_len, msk, msk_len);
-
- GNUNET_free (pub);
- GNUNET_free (msk);
-
- return len;
-}
-
-
-/**
- * @ingroup abe
- * Deserialize an ABE master key.
- *
- * @param data the data to deserialize
- * @param len the length of the data.
- * @return the ABE key. NULL of unsuccessful
- */
-struct GNUNET_ABE_AbeMasterKey*
-GNUNET_ABE_cpabe_deserialize_master_key (const void *data,
- size_t len)
-{
- struct GNUNET_ABE_AbeMasterKey *key;
- char *msk;
- char *pub;
- int msk_len;
- int pub_len;
-
- key = GNUNET_new (struct GNUNET_ABE_AbeMasterKey);
- read_cpabe (data,
- &pub,
- &pub_len,
- &msk,
- &msk_len);
- key->pub = gabe_pub_unserialize (pub, pub_len);
- key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
-
- GNUNET_free (pub);
- GNUNET_free (msk);
-
- return key;
-}
diff --git a/src/abe/test_cpabe.c b/src/abe/test_cpabe.c
deleted file mode 100644
index aefb0f99f..000000000
--- a/src/abe/test_cpabe.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2002, 2003, 2004, 2006 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
-
- */
-/**
- * @author Martin Schanzenbach
- * @file util/test_crypto_abe.c
- * @brief test for ABE ciphers
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_abe_lib.h"
-
-#define TESTSTRING "Hello World!"
-
-static int
-testAbecipher ()
-{
- struct GNUNET_ABE_AbeMasterKey *msk;
- struct GNUNET_ABE_AbeKey *key;
- char *result;
- char **attrs;
- int size;
- char *res;
-
- msk = GNUNET_ABE_cpabe_create_master_key ();
- size = GNUNET_ABE_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1,
- "testattr", // Policy
- msk,
- (void *) &result);
- GNUNET_assert (-1 != size);
- attrs = GNUNET_malloc (2 * sizeof(char*));
- attrs[0] = "testattr";
- attrs[1] = NULL;
- key = GNUNET_ABE_cpabe_create_key (msk,
- attrs);
-
- size = GNUNET_ABE_cpabe_decrypt (result, size,
- key,
- (void *) &res);
- if (strlen (TESTSTRING) + 1 != size)
- {
- printf ("abeciphertest failed: decryptBlock returned %d\n", size);
- return 1;
- }
- if (0 != strcmp (res, TESTSTRING))
- {
- printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING);
- return 1;
- }
- else
- return 0;
-}
-
-
-int
-main (int argc, char *argv[])
-{
- int failureCount = 0;
-
- GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL);
- failureCount += testAbecipher ();
-
- if (failureCount != 0)
- {
- printf ("%d TESTS FAILED!\n", failureCount);
- return -1;
- }
- return 0;
-}
-
-
-/* end of test_crypto_aes.c */
diff --git a/src/ats/ats.conf.in b/src/ats/ats.conf.in
index 4abddd99c..2c65869dd 100644
--- a/src/ats/ats.conf.in
+++ b/src/ats/ats.conf.in
@@ -15,8 +15,8 @@ MODE = proportional
# IMPORTANT: Do not lower those quotas below 10 MiB
# Or your peer may not bootstrap correctly.
# Network specific inbound/outbound quotas
-UNSPECIFIED_QUOTA_IN = 10 MiB
-UNSPECIFIED_QUOTA_OUT = 10 MiB
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
# LOOPBACK
LOOPBACK_QUOTA_IN = unlimited
LOOPBACK_QUOTA_OUT = unlimited
@@ -27,8 +27,8 @@ LAN_QUOTA_OUT = unlimited
WAN_QUOTA_IN = 10 MiB
WAN_QUOTA_OUT = 10 MiB
# WLAN
-WLAN_QUOTA_IN = 10 MiB
-WLAN_QUOTA_OUT = 10 MiB
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
# BLUETOOTH
BLUETOOTH_QUOTA_IN = 10 MiB
BLUETOOTH_QUOTA_OUT = 10 MiB
@@ -38,7 +38,7 @@ BLUETOOTH_QUOTA_OUT = 10 MiB
# How proportional to preferences is bandwidth distribution in a network
# 1.0: Fair with respect to addresses without preferences
# > 1.0: The bigger, the more respect is paid to preferences
-PROP_PROPORTIONALITY_FACTOR = 2.00
-# Should we stick to existing connections are prefer to switch?
+PROP_PROPORTIONALITY_FACTOR = 10.00
+# Should we stick to existing connections or prefer to switch?
# [1.0...2.0], lower value prefers to switch, bigger value is more tolerant
PROP_STABILITY_FACTOR = 1.25
diff --git a/src/ats/gnunet-ats-solver-eval.c b/src/ats/gnunet-ats-solver-eval.c
index 25b963532..ba7994686 100644
--- a/src/ats/gnunet-ats-solver-eval.c
+++ b/src/ats/gnunet-ats-solver-eval.c
@@ -442,7 +442,7 @@ GNUNET_ATS_solver_logging_write_to_disk (struct LoggingHandle *l, int
}
}
-cleanup:
+ cleanup:
next = lf_head;
for (cur = next; NULL != cur; cur = next)
{
@@ -1414,7 +1414,8 @@ load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
}
else
{
- GNUNET_STRINGS_utf8_toupper (op_network, op_network);
+ GNUNET_break (GNUNET_OK == GNUNET_STRINGS_utf8_toupper (op_network,
+ op_network));
if (0 == strcmp (op_network, "UNSPECIFIED"))
{
o->address_network = GNUNET_NT_UNSPECIFIED;
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
index 3cd831a39..d02efd939 100644
--- a/src/ats/gnunet-service-ats_addresses.c
+++ b/src/ats/gnunet-service-ats_addresses.c
@@ -389,6 +389,8 @@ GAS_addresses_destroy_all ()
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Destroying all addresses\n");
+ if (NULL == GSA_addresses)
+ return;
if (0 ==
GNUNET_CONTAINER_multipeermap_size (GSA_addresses))
return;
diff --git a/src/ats/gnunet-service-ats_connectivity.c b/src/ats/gnunet-service-ats_connectivity.c
index 05046f007..5ee9b60f5 100644
--- a/src/ats/gnunet-service-ats_connectivity.c
+++ b/src/ats/gnunet-service-ats_connectivity.c
@@ -162,9 +162,10 @@ GAS_handle_request_address_cancel (struct GNUNET_SERVICE_Client *client,
void
GAS_connectivity_remove_client (struct GNUNET_SERVICE_Client *client)
{
- GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
- &free_matching_requests,
- client);
+ if (NULL != connection_requests)
+ GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
+ &free_matching_requests,
+ client);
}
diff --git a/src/block/bg_bf.c b/src/block/bg_bf.c
index ae8ee0e51..b79ea3c55 100644
--- a/src/block/bg_bf.c
+++ b/src/block/bg_bf.c
@@ -55,34 +55,34 @@ struct BfGroupInternals
* Serialize state of a block group.
*
* @param bg group to serialize
- * @param[out] nonce set to the nonce of the @a bg
* @param[out] raw_data set to the serialized state
* @param[out] raw_data_size set to the number of bytes in @a raw_data
* @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
* supported, #GNUNET_SYSERR on error
*/
-static int
+static enum GNUNET_GenericReturnValue
bf_group_serialize_cb (struct GNUNET_BLOCK_Group *bg,
- uint32_t *nonce,
void **raw_data,
size_t *raw_data_size)
{
struct BfGroupInternals *gi = bg->internal_cls;
- char *raw;
+ void *raw;
- raw = GNUNET_malloc (gi->bf_size);
+ raw = GNUNET_malloc (gi->bf_size + sizeof (uint32_t));
if (GNUNET_OK !=
GNUNET_CONTAINER_bloomfilter_get_raw_data (gi->bf,
- raw,
+ raw + sizeof (uint32_t),
gi->bf_size))
{
GNUNET_free (raw);
GNUNET_break (0);
return GNUNET_SYSERR;
}
- *nonce = gi->bf_mutator;
+ memcpy (raw,
+ &gi->bf_mutator,
+ sizeof (uint32_t));
*raw_data = raw;
- *raw_data_size = gi->bf_size;
+ *raw_data_size = gi->bf_size + sizeof (uint32_t);
return GNUNET_OK;
}
@@ -124,7 +124,7 @@ bf_group_mark_seen_cb (struct GNUNET_BLOCK_Group *bg,
* @return #GNUNET_OK on success, #GNUNET_NO if the nonces were different and thus
* we failed.
*/
-static int
+static enum GNUNET_GenericReturnValue
bf_group_merge_cb (struct GNUNET_BLOCK_Group *bg1,
const struct GNUNET_BLOCK_Group *bg2)
{
@@ -164,7 +164,6 @@ bf_group_destroy_cb (struct GNUNET_BLOCK_Group *bg)
* @param bf_size size of the Bloom filter
* @param bf_k K-value for the Bloom filter
* @param type block type
- * @param nonce random value used to seed the group creation
* @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
* @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
* @return block group handle, NULL if block groups are not supported
@@ -175,13 +174,32 @@ GNUNET_BLOCK_GROUP_bf_create (void *cls,
size_t bf_size,
unsigned int bf_k,
enum GNUNET_BLOCK_Type type,
- uint32_t nonce,
const void *raw_data,
size_t raw_data_size)
{
struct BfGroupInternals *gi;
struct GNUNET_BLOCK_Group *bg;
+ uint32_t nonce;
+ if ( (NULL != raw_data) &&
+ (raw_data_size < sizeof (nonce)) )
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ if (NULL != raw_data)
+ {
+ memcpy (&nonce,
+ raw_data,
+ sizeof (nonce));
+ raw_data += sizeof (nonce);
+ raw_data_size -= sizeof (nonce);
+ }
+ else
+ {
+ nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+ UINT32_MAX);
+ }
gi = GNUNET_new (struct BfGroupInternals);
gi->bf = GNUNET_CONTAINER_bloomfilter_init ((bf_size != raw_data_size) ?
NULL : raw_data,
@@ -210,7 +228,7 @@ GNUNET_BLOCK_GROUP_bf_create (void *cls,
* @return #GNUNET_YES if @a hc is (likely) a duplicate
* #GNUNET_NO if @a hc was definitively not in @bg (but now is)
*/
-int
+enum GNUNET_GenericReturnValue
GNUNET_BLOCK_GROUP_bf_test_and_set (struct GNUNET_BLOCK_Group *bg,
const struct GNUNET_HashCode *hc)
{
diff --git a/src/block/block.c b/src/block/block.c
index 975c0f747..4b2d8a960 100644
--- a/src/block/block.c
+++ b/src/block/block.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2010, 2017 GNUnet e.V.
+ Copyright (C) 2010, 2017, 2021, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -70,26 +70,41 @@ struct GNUNET_BLOCK_Context
};
+GNUNET_NETWORK_STRUCT_BEGIN
+
+
/**
- * Mingle hash with the mingle_number to produce different bits.
- *
- * @param in original hash code
- * @param mingle_number number for hash permutation
- * @param hc where to store the result.
+ * Serialization to use in #GNUNET_BLOCK_mingle_hash.
*/
+struct MinglePacker
+{
+ /**
+ * Original hash.
+ */
+ struct GNUNET_HashCode in;
+
+ /**
+ * Mingle value.
+ */
+ uint32_t mingle GNUNET_PACKED;
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
void
GNUNET_BLOCK_mingle_hash (const struct GNUNET_HashCode *in,
uint32_t mingle_number,
struct GNUNET_HashCode *hc)
{
- struct GNUNET_HashCode m;
-
- GNUNET_CRYPTO_hash (&mingle_number,
- sizeof(uint32_t),
- &m);
- GNUNET_CRYPTO_hash_xor (&m,
- in,
- hc);
+ struct MinglePacker mp = {
+ .in = *in,
+ .mingle = mingle_number
+ };
+
+ GNUNET_CRYPTO_hash (&mp,
+ sizeof(mp),
+ hc);
}
@@ -121,12 +136,6 @@ add_plugin (void *cls,
}
-/**
- * Create a block context. Loads the block plugins.
- *
- * @param cfg configuration to use
- * @return NULL on error
- */
struct GNUNET_BLOCK_Context *
GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
@@ -143,11 +152,6 @@ GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
}
-/**
- * Destroy the block context.
- *
- * @param ctx context to destroy
- */
void
GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
{
@@ -167,23 +171,11 @@ GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
}
-/**
- * Serialize state of a block group.
- *
- * @param bg group to serialize
- * @param[out] nonce set to the nonce of the @a bg
- * @param[out] raw_data set to the serialized state
- * @param[out] raw_data_size set to the number of bytes in @a raw_data
- * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
- * supported, #GNUNET_SYSERR on error
- */
-int
+enum GNUNET_GenericReturnValue
GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
- uint32_t *nonce,
void **raw_data,
size_t *raw_data_size)
{
- *nonce = 0;
*raw_data = NULL;
*raw_data_size = 0;
if (NULL == bg)
@@ -191,17 +183,11 @@ GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
if (NULL == bg->serialize_cb)
return GNUNET_NO;
return bg->serialize_cb (bg,
- nonce,
raw_data,
raw_data_size);
}
-/**
- * Destroy resources used by a block group.
- *
- * @param bg group to destroy, NULL is allowed
- */
void
GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg)
{
@@ -211,23 +197,11 @@ GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg)
}
-/**
- * Try merging two block groups. Afterwards, @a bg1 should remain
- * valid and contain the rules from both @a bg1 and @bg2, and
- * @a bg2 should be destroyed (as part of this call). The latter
- * should happen even if merging is not supported.
- *
- * @param[in,out] bg1 first group to merge, is updated
- * @param bg2 second group to merge, is destroyed
- * @return #GNUNET_OK on success,
- * #GNUNET_NO if merge failed due to different nonce
- * #GNUNET_SYSERR if merging is not supported
- */
-int
+enum GNUNET_GenericReturnValue
GNUNET_BLOCK_group_merge (struct GNUNET_BLOCK_Group *bg1,
struct GNUNET_BLOCK_Group *bg2)
{
- int ret;
+ enum GNUNET_GenericReturnValue ret;
if (NULL == bg2)
return GNUNET_OK;
@@ -257,39 +231,21 @@ static struct GNUNET_BLOCK_PluginFunctions *
find_plugin (struct GNUNET_BLOCK_Context *ctx,
enum GNUNET_BLOCK_Type type)
{
- struct Plugin *plugin;
- unsigned int j;
-
for (unsigned i = 0; i < ctx->num_plugins; i++)
{
- plugin = ctx->plugins[i];
- j = 0;
- while (0 != (plugin->api->types[j]))
- {
+ struct Plugin *plugin = ctx->plugins[i];
+
+ for (unsigned int j = 0; 0 != plugin->api->types[j]; j++)
if (type == plugin->api->types[j])
return plugin->api;
- j++;
- }
}
return NULL;
}
-/**
- * Create a new block group.
- *
- * @param ctx block context in which the block group is created
- * @param type type of the block for which we are creating the group
- * @param nonce random value used to seed the group creation
- * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
- * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
- * @return block group handle, NULL if block groups are not supported
- * by this @a type of block (this is not an error)
- */
struct GNUNET_BLOCK_Group *
GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
enum GNUNET_BLOCK_Type type,
- uint32_t nonce,
const void *raw_data,
size_t raw_data_size,
...)
@@ -308,7 +264,6 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
raw_data_size);
bg = plugin->create_group (plugin->cls,
type,
- nonce,
raw_data,
raw_data_size,
ap);
@@ -317,65 +272,7 @@ GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
}
-/**
- * Function called to validate a reply or a request. For
- * request evaluation, simply pass "NULL" for the reply_block.
- * Note that it is assumed that the reply has already been
- * matched to the key (and signatures checked) as it would
- * be done with the "get_key" function.
- *
- * @param ctx block contxt
- * @param type block type
- * @param block block group to use
- * @param eo control flags
- * @param query original query (hash)
- * @param xquery extended query data (can be NULL, depending on type)
- * @param xquery_size number of bytes in @a xquery
- * @param reply_block response to validate
- * @param reply_block_size number of bytes in @a reply_block
- * @return characterization of result
- */
-enum GNUNET_BLOCK_EvaluationResult
-GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_BLOCK_Group *group,
- enum GNUNET_BLOCK_EvaluationOptions eo,
- const struct GNUNET_HashCode *query,
- const void *xquery,
- size_t xquery_size,
- const void *reply_block,
- size_t reply_block_size)
-{
- struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
- type);
-
- if (NULL == plugin)
- return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
- return plugin->evaluate (plugin->cls,
- ctx,
- type,
- group,
- eo,
- query,
- xquery,
- xquery_size,
- reply_block,
- reply_block_size);
-}
-
-
-/**
- * Function called to obtain the key for a block.
- *
- * @param ctx block context
- * @param type block type
- * @param block block to get the key for
- * @param block_size number of bytes in @a block
- * @param key set to the key (query) for the given block
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
- * (or if extracting a key from a block of this type does not work)
- */
-int
+enum GNUNET_GenericReturnValue
GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
enum GNUNET_BLOCK_Type type,
const void *block,
@@ -385,8 +282,8 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
type);
- if (plugin == NULL)
- return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
+ if (NULL == plugin)
+ return GNUNET_SYSERR;
return plugin->get_key (plugin->cls,
type,
block,
@@ -395,18 +292,71 @@ GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
}
-/**
- * Update block group to filter out the given results. Note that the
- * use of a hash for seen results implies that the caller magically
- * knows how the specific block engine hashes for filtering
- * duplicates, so this API may not always apply.
- *
- * @param bf_mutator mutation value to use
- * @param seen_results results already seen
- * @param seen_results_count number of entries in @a seen_results
- * @return #GNUNET_SYSERR if not supported, #GNUNET_OK on success
- */
-int
+enum GNUNET_GenericReturnValue
+GNUNET_BLOCK_check_query (struct GNUNET_BLOCK_Context *ctx,
+ enum GNUNET_BLOCK_Type type,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size)
+{
+ struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
+ type);
+
+ if (NULL == plugin)
+ return GNUNET_SYSERR;
+ return plugin->check_query (plugin->cls,
+ type,
+ query,
+ xquery,
+ xquery_size);
+}
+
+
+enum GNUNET_GenericReturnValue
+GNUNET_BLOCK_check_block (struct GNUNET_BLOCK_Context *ctx,
+ enum GNUNET_BLOCK_Type type,
+ const void *block,
+ size_t block_size)
+{
+ struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
+ type);
+
+ if (NULL == plugin)
+ return GNUNET_SYSERR;
+ return plugin->check_block (plugin->cls,
+ type,
+ block,
+ block_size);
+}
+
+
+enum GNUNET_BLOCK_ReplyEvaluationResult
+GNUNET_BLOCK_check_reply (struct GNUNET_BLOCK_Context *ctx,
+ enum GNUNET_BLOCK_Type type,
+ struct GNUNET_BLOCK_Group *group,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size,
+ const void *reply_block,
+ size_t reply_block_size)
+{
+ struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx,
+ type);
+
+ if (NULL == plugin)
+ return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
+ return plugin->check_reply (plugin->cls,
+ type,
+ group,
+ query,
+ xquery,
+ xquery_size,
+ reply_block,
+ reply_block_size);
+}
+
+
+enum GNUNET_GenericReturnValue
GNUNET_BLOCK_group_set_seen (struct GNUNET_BLOCK_Group *bg,
const struct GNUNET_HashCode *seen_results,
unsigned int seen_results_count)
diff --git a/src/block/plugin_block_template.c b/src/block/plugin_block_template.c
index ecd46e364..46a370924 100644
--- a/src/block/plugin_block_template.c
+++ b/src/block/plugin_block_template.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2010 GNUnet e.V.
+ Copyright (C) 2010, 2021, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -48,7 +48,6 @@
*
* @param ctx block context in which the block group is created
* @param type type of the block for which we are creating the group
- * @param nonce random value used to seed the group creation
* @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
* @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
* @param va variable arguments specific to @a type
@@ -58,7 +57,6 @@
static struct GNUNET_BLOCK_Group *
block_plugin_template_create_group (void *cls,
enum GNUNET_BLOCK_Type type,
- uint32_t nonce,
const void *raw_data,
size_t raw_data_size,
va_list va)
@@ -85,52 +83,80 @@ block_plugin_template_create_group (void *cls,
bf_size,
BLOOMFILTER_K,
type,
- nonce,
raw_data,
raw_data_size);
}
/**
- * Function called to validate a reply or a request. For
- * request evaluation, simply pass "NULL" for the reply_block.
+ * Function called to validate a query.
*
* @param cls closure
- * @param ctx context
+ * @param ctx block context
* @param type block type
- * @param group block group to use
- * @param eo control flags
* @param query original query (hash)
* @param xquery extrended query data (can be NULL, depending on type)
- * @param xquery_size number of bytes in xquery
+ * @param xquery_size number of bytes in @a xquery
+ * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not, #GNUNET_SYSERR if not supported
+ */
+static enum GNUNET_GenericReturnValue
+block_plugin_template_check_query (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size)
+{
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called to validate a block for storage.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param block block data to validate
+ * @param block_size number of bytes in @a block
+ * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not, #GNUNET_SYSERR if not supported
+ */
+static enum GNUNET_GenericReturnValue
+block_plugin_template_check_block (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ const void *block,
+ size_t block_size)
+{
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called to validate a reply to a request. Note that it is assumed
+ * that the reply has already been matched to the key (and signatures checked)
+ * as it would be done with the GetKeyFunction and the
+ * BlockEvaluationFunction.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param group which block group to use for evaluation
+ * @param query original query (hash)
+ * @param xquery extrended query data (can be NULL, depending on type)
+ * @param xquery_size number of bytes in @a xquery
* @param reply_block response to validate
- * @param reply_block_size number of bytes in reply block
+ * @param reply_block_size number of bytes in @a reply_block
* @return characterization of result
*/
-static enum GNUNET_BLOCK_EvaluationResult
-block_plugin_template_evaluate (void *cls,
- struct GNUNET_BLOCK_Context *ctx,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_BLOCK_Group *group,
- enum GNUNET_BLOCK_EvaluationOptions eo,
- const struct GNUNET_HashCode *query,
- const void *xquery,
- size_t xquery_size,
- const void *reply_block,
- size_t reply_block_size)
+static enum GNUNET_BLOCK_ReplyEvaluationResult
+block_plugin_template_check_reply (
+ void *cls,
+ enum GNUNET_BLOCK_Type type,
+ struct GNUNET_BLOCK_Group *group,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size,
+ const void *reply_block,
+ size_t reply_block_size)
{
- struct GNUNET_HashCode chash;
-
- if (NULL == reply_block)
- return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
- GNUNET_CRYPTO_hash (reply_block,
- reply_block_size,
- &chash);
- if (GNUNET_YES ==
- GNUNET_BLOCK_GROUP_bf_test_and_set (group,
- &chash))
- return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
- return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
+ return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
}
@@ -145,7 +171,7 @@ block_plugin_template_evaluate (void *cls,
* @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
* (or if extracting a key from a block of this type does not work)
*/
-static int
+static enum GNUNET_GenericReturnValue
block_plugin_template_get_key (void *cls,
enum GNUNET_BLOCK_Type type,
const void *block,
@@ -164,15 +190,17 @@ block_plugin_template_get_key (void *cls,
void *
libgnunet_plugin_block_template_init (void *cls)
{
- static enum GNUNET_BLOCK_Type types[] = {
- /* FIXME: insert supported block types here */
+ static const enum GNUNET_BLOCK_Type types[] = {
+ /* NOTE: insert supported block types here */
GNUNET_BLOCK_TYPE_ANY /* end of list */
};
struct GNUNET_BLOCK_PluginFunctions *api;
api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
- api->evaluate = &block_plugin_template_evaluate;
api->get_key = &block_plugin_template_get_key;
+ api->check_query = &block_plugin_template_check_query;
+ api->check_block = &block_plugin_template_check_block;
+ api->check_reply = &block_plugin_template_check_reply;
api->create_group = &block_plugin_template_create_group;
api->types = types;
return api;
diff --git a/src/block/plugin_block_test.c b/src/block/plugin_block_test.c
index 45d54d339..2e404bbc2 100644
--- a/src/block/plugin_block_test.c
+++ b/src/block/plugin_block_test.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2010 GNUnet e.V.
+ Copyright (C) 2010, 2021, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -46,7 +46,6 @@
*
* @param ctx block context in which the block group is created
* @param type type of the block for which we are creating the group
- * @param nonce random value used to seed the group creation
* @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
* @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
* @param va variable arguments specific to @a type
@@ -56,7 +55,6 @@
static struct GNUNET_BLOCK_Group *
block_plugin_test_create_group (void *cls,
enum GNUNET_BLOCK_Type type,
- uint32_t nonce,
const void *raw_data,
size_t raw_data_size,
va_list va)
@@ -83,21 +81,82 @@ block_plugin_test_create_group (void *cls,
bf_size,
BLOOMFILTER_K,
type,
- nonce,
raw_data,
raw_data_size);
}
/**
- * Function called to validate a reply or a request. For
- * request evaluation, simply pass "NULL" for the reply_block.
+ * Function called to validate a query.
*
* @param cls closure
* @param ctx block context
* @param type block type
- * @param group group to check against
- * @param eo control flags
+ * @param query original query (hash)
+ * @param xquery extrended query data (can be NULL, depending on type)
+ * @param xquery_size number of bytes in @a xquery
+ * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not, #GNUNET_SYSERR if @a type is not supported
+ */
+static enum GNUNET_GenericReturnValue
+block_plugin_test_check_query (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size)
+{
+ (void) cls;
+ (void) query;
+ (void) xquery;
+ if (GNUNET_BLOCK_TYPE_TEST != type)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 != xquery_size)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_NO;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called to validate a block for storage.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param block block data to validate
+ * @param block_size number of bytes in @a block
+ * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not, #GNUNET_SYSERR if @a type is not supported
+ */
+static enum GNUNET_GenericReturnValue
+block_plugin_test_check_block (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ const void *block,
+ size_t block_size)
+{
+ (void) cls;
+ (void) block;
+ (void) block_size;
+ if (GNUNET_BLOCK_TYPE_TEST != type)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called to validate a reply to a request. Note that it is assumed
+ * that the reply has already been matched to the key (and signatures checked)
+ * as it would be done with the GetKeyFunction and the
+ * BlockEvaluationFunction.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param group which block group to use for evaluation
* @param query original query (hash)
* @param xquery extrended query data (can be NULL, depending on type)
* @param xquery_size number of bytes in @a xquery
@@ -105,40 +164,35 @@ block_plugin_test_create_group (void *cls,
* @param reply_block_size number of bytes in @a reply_block
* @return characterization of result
*/
-static enum GNUNET_BLOCK_EvaluationResult
-block_plugin_test_evaluate (void *cls,
- struct GNUNET_BLOCK_Context *ctx,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_BLOCK_Group *group,
- enum GNUNET_BLOCK_EvaluationOptions eo,
- const struct GNUNET_HashCode *query,
- const void *xquery,
- size_t xquery_size,
- const void *reply_block,
- size_t reply_block_size)
+static enum GNUNET_BLOCK_ReplyEvaluationResult
+block_plugin_test_check_reply (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ struct GNUNET_BLOCK_Group *group,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size,
+ const void *reply_block,
+ size_t reply_block_size)
{
struct GNUNET_HashCode chash;
+ (void) cls;
+ (void) query;
+ (void) xquery;
+ (void) xquery_size;
if (GNUNET_BLOCK_TYPE_TEST != type)
{
GNUNET_break (0);
- return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
- }
- if (0 != xquery_size)
- {
- GNUNET_break_op (0);
- return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
+ return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
}
- if (NULL == reply_block)
- return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
GNUNET_CRYPTO_hash (reply_block,
reply_block_size,
&chash);
if (GNUNET_YES ==
GNUNET_BLOCK_GROUP_bf_test_and_set (group,
&chash))
- return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
- return GNUNET_BLOCK_EVALUATION_OK_MORE;
+ return GNUNET_BLOCK_REPLY_OK_DUPLICATE;
+ return GNUNET_BLOCK_REPLY_OK_MORE;
}
@@ -150,19 +204,25 @@ block_plugin_test_evaluate (void *cls,
* @param block block to get the key for
* @param block_size number of bytes in @a block
* @param key set to the key (query) for the given block
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
- * (or if extracting a key from a block of this type does not work)
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported, #GNUNET_NO if extracting a key from a block of this type does not work
*/
-static int
+static enum GNUNET_GenericReturnValue
block_plugin_test_get_key (void *cls,
enum GNUNET_BLOCK_Type type,
const void *block,
size_t block_size,
struct GNUNET_HashCode *key)
{
- /* always fails since there is no fixed relationship between
- * keys and values for test values */
- return GNUNET_SYSERR;
+ (void) cls;
+ (void) block;
+ (void) block_size;
+ (void) key;
+ if (GNUNET_BLOCK_TYPE_TEST != type)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_NO;
}
@@ -175,15 +235,17 @@ block_plugin_test_get_key (void *cls,
void *
libgnunet_plugin_block_test_init (void *cls)
{
- static enum GNUNET_BLOCK_Type types[] = {
+ static const enum GNUNET_BLOCK_Type types[] = {
GNUNET_BLOCK_TYPE_TEST,
GNUNET_BLOCK_TYPE_ANY /* end of list */
};
struct GNUNET_BLOCK_PluginFunctions *api;
api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
- api->evaluate = &block_plugin_test_evaluate;
api->get_key = &block_plugin_test_get_key;
+ api->check_query = &block_plugin_test_check_query;
+ api->check_block = &block_plugin_test_check_block;
+ api->check_reply = &block_plugin_test_check_reply;
api->create_group = &block_plugin_test_create_group;
api->types = types;
return api;
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c
index 6caac474d..3df2687de 100644
--- a/src/cadet/gnunet-service-cadet_dht.c
+++ b/src/cadet/gnunet-service-cadet_dht.c
@@ -101,6 +101,7 @@ static struct GNUNET_TIME_Relative announce_delay;
* @param cls closure
* @param exp when will this value expire
* @param key key of the result
+ * @param trunc_peer peer preceeding with invalid signature, or NULL
* @param get_path path of the get request
* @param get_path_length length of @a get_path
* @param put_path path of the put request
@@ -112,17 +113,18 @@ static struct GNUNET_TIME_Relative announce_delay;
static void
dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
const struct GNUNET_HashCode *key,
- const struct GNUNET_PeerIdentity *get_path,
+ const struct GNUNET_PeerIdentity *trunc_peer,
+ const struct GNUNET_DHT_PathElement *get_path,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
+ const struct GNUNET_DHT_PathElement *put_path,
unsigned int put_path_length,
enum GNUNET_BLOCK_Type type,
size_t size,
const void *data)
{
const struct GNUNET_HELLO_Message *hello = data;
- struct CadetPeer *peer;
+ (void) trunc_peer;
GCPP_try_path_from_dht (get_path,
get_path_length,
put_path,
@@ -131,7 +133,9 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
(ntohs (hello->header.size) == size) &&
(size == GNUNET_HELLO_size (hello)))
{
- peer = GCP_get (&put_path[0],
+ struct CadetPeer *peer;
+
+ peer = GCP_get (&put_path[0].pred,
GNUNET_YES);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Got HELLO for %s\n",
diff --git a/src/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c
index 2da4e2708..aa31aaa74 100644
--- a/src/cadet/gnunet-service-cadet_paths.c
+++ b/src/cadet/gnunet-service-cadet_paths.c
@@ -468,9 +468,9 @@ extend_path (struct CadetPeerPath *path,
* @return a path through the network
*/
void
-GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
+GCPP_try_path_from_dht (const struct GNUNET_DHT_PathElement *get_path,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
+ const struct GNUNET_DHT_PathElement *put_path,
unsigned int put_path_length)
{
struct CadetPeer *cpath[get_path_length + put_path_length];
@@ -490,8 +490,8 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
const struct GNUNET_PeerIdentity *pid;
pid = (off < get_path_length)
- ? &get_path[get_path_length - off - 1]
- : &put_path[get_path_length + put_path_length - off - 1];
+ ? &get_path[get_path_length - off - 1].pred
+ : &put_path[get_path_length + put_path_length - off - 1].pred;
/* Check that I am not in the path */
if (0 == GNUNET_memcmp (&my_full_id,
pid))
diff --git a/src/cadet/gnunet-service-cadet_paths.h b/src/cadet/gnunet-service-cadet_paths.h
index 3961dd721..afd193596 100644
--- a/src/cadet/gnunet-service-cadet_paths.h
+++ b/src/cadet/gnunet-service-cadet_paths.h
@@ -28,6 +28,7 @@
#define GNUNET_SERVICE_CADET_PATHS_H
#include "gnunet_util_lib.h"
+#include "gnunet_dht_service.h"
#include "gnunet-service-cadet.h"
/**
@@ -42,9 +43,9 @@
* @param put_path_length length of the @a put_path
*/
void
-GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
+GCPP_try_path_from_dht (const struct GNUNET_DHT_PathElement *get_path,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
+ const struct GNUNET_DHT_PathElement *put_path,
unsigned int put_path_length);
diff --git a/src/consensus/plugin_block_consensus.c b/src/consensus/plugin_block_consensus.c
index cdac12ed5..f30b9b0d7 100644
--- a/src/consensus/plugin_block_consensus.c
+++ b/src/consensus/plugin_block_consensus.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2017 GNUnet e.V.
+ Copyright (C) 2017, 2021 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -31,51 +31,126 @@
/**
- * Function called to validate a reply or a request. For
- * request evaluation, simply pass "NULL" for the reply_block.
+ * Our closure.
+ */
+struct BlockContext
+{
+ /**
+ * Configuration to use.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Lazily initialized block context.
+ */
+ struct GNUNET_BLOCK_Context *bc;
+};
+
+
+
+/**
+ * Function called to validate a query.
+ *
+ * @param cls closure
+ * @param ctx block context
+ * @param type block type
+ * @param query original query (hash)
+ * @param xquery extrended query data (can be NULL, depending on type)
+ * @param xquery_size number of bytes in @a xquery
+ * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
+ */
+static enum GNUNET_GenericReturnValue
+block_plugin_consensus_check_query (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size)
+{
+ /* consensus does not use queries/DHT */
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called to validate a block for storage.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param block block data to validate
+ * @param block_size number of bytes in @a block
+ * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
+ */
+static enum GNUNET_GenericReturnValue
+block_plugin_consensus_check_block (void *cls,
+ enum GNUNET_BLOCK_Type type,
+ const void *block,
+ size_t block_size)
+{
+ struct BlockContext *ctx = cls;
+ const struct ConsensusElement *ce = block;
+
+ if (block_size < sizeof(*ce))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_NO;
+ }
+ if ( (0 != ce->marker) ||
+ (0 == ce->payload_type) )
+ return GNUNET_OK;
+ if (NULL == ctx->bc)
+ ctx->bc = GNUNET_BLOCK_context_create (ctx->cfg);
+ return GNUNET_BLOCK_check_block (ctx->bc,
+ ntohl (ce->payload_type),
+ &ce[1],
+ block_size - sizeof(*ce));
+}
+
+
+/**
+ * Function called to validate a reply to a request. Note that it is assumed
+ * that the reply has already been matched to the key (and signatures checked)
+ * as it would be done with the GetKeyFunction and the
+ * BlockEvaluationFunction.
*
* @param cls closure
- * @param ctx context
* @param type block type
- * @param group block group to use
- * @param eo control flags
+ * @param group which block group to use for evaluation
* @param query original query (hash)
* @param xquery extrended query data (can be NULL, depending on type)
- * @param xquery_size number of bytes in xquery
+ * @param xquery_size number of bytes in @a xquery
* @param reply_block response to validate
- * @param reply_block_size number of bytes in reply block
+ * @param reply_block_size number of bytes in @a reply_block
* @return characterization of result
*/
-static enum GNUNET_BLOCK_EvaluationResult
-block_plugin_consensus_evaluate (void *cls,
- struct GNUNET_BLOCK_Context *ctx,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_BLOCK_Group *group,
- enum GNUNET_BLOCK_EvaluationOptions eo,
- const struct GNUNET_HashCode *query,
- const void *xquery,
- size_t xquery_size,
- const void *reply_block,
- size_t reply_block_size)
+static enum GNUNET_BLOCK_ReplyEvaluationResult
+block_plugin_consensus_check_reply (
+ void *cls,
+ enum GNUNET_BLOCK_Type type,
+ struct GNUNET_BLOCK_Group *group,
+ const struct GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size,
+ const void *reply_block,
+ size_t reply_block_size)
{
+ struct BlockContext *ctx = cls;
const struct ConsensusElement *ce = reply_block;
- if (reply_block_size < sizeof(struct ConsensusElement))
- return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+ GNUNET_assert (reply_block_size >= sizeof(struct ConsensusElement));
if ( (0 != ce->marker) ||
(0 == ce->payload_type) )
- return GNUNET_BLOCK_EVALUATION_OK_MORE;
-
- return GNUNET_BLOCK_evaluate (ctx,
- type,
- group,
- eo,
- query,
- xquery,
- xquery_size,
- &ce[1],
- reply_block_size
- - sizeof(struct ConsensusElement));
+ return GNUNET_BLOCK_REPLY_OK_MORE;
+ if (NULL == ctx->bc)
+ ctx->bc = GNUNET_BLOCK_context_create (ctx->cfg);
+ return GNUNET_BLOCK_check_reply (ctx->bc,
+ ntohl (ce->payload_type),
+ group,
+ query,
+ xquery,
+ xquery_size,
+ &ce[1],
+ reply_block_size - sizeof(*ce));
}
@@ -90,7 +165,7 @@ block_plugin_consensus_evaluate (void *cls,
* @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
* (or if extracting a key from a block of this type does not work)
*/
-static int
+static enum GNUNET_GenericReturnValue
block_plugin_consensus_get_key (void *cls,
enum GNUNET_BLOCK_Type type,
const void *block,
@@ -107,15 +182,22 @@ block_plugin_consensus_get_key (void *cls,
void *
libgnunet_plugin_block_consensus_init (void *cls)
{
- static enum GNUNET_BLOCK_Type types[] = {
+ static const enum GNUNET_BLOCK_Type types[] = {
GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT,
GNUNET_BLOCK_TYPE_ANY /* end of list */
};
+ const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct BlockContext *ctx;
struct GNUNET_BLOCK_PluginFunctions *api;
+ ctx = GNUNET_new (struct BlockContext);
+ ctx->cfg = cfg;
api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
- api->evaluate = &block_plugin_consensus_evaluate;
+ api->cls = ctx;
api->get_key = &block_plugin_consensus_get_key;
+ api->check_query = &block_plugin_consensus_check_query;
+ api->check_block = &block_plugin_consensus_check_block;
+ api->check_reply = &block_plugin_consensus_check_reply;
api->types = types;
return api;
}
@@ -128,7 +210,11 @@ void *
libgnunet_plugin_block_consensus_done (void *cls)
{
struct GNUNET_BLOCK_PluginFunctions *api = cls;
+ struct BlockContext *ctx = api->cls;
+ if (NULL != ctx->bc)
+ GNUNET_BLOCK_context_destroy (ctx->bc);
+ GNUNET_free (ctx);
GNUNET_free (api);
return NULL;
}
diff --git a/src/consensus/test_consensus.conf b/src/consensus/test_consensus.conf
index 67b366405..df7fb6861 100644
--- a/src/consensus/test_consensus.conf
+++ b/src/consensus/test_consensus.conf
@@ -3,7 +3,7 @@ GNUNET_TEST_HOME = $GNUNET_TMP/test-consensus/
[consensus]
#OPTIONS = -L INFO
-BINARY = gnunet-service-evil-consensus
+BINARY = gnunet-service-consensus
#PREFIX = valgrind
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 8f53072d9..c9c3e3ff5 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -271,9 +271,9 @@ GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car)
GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &car->target))
{
/* connection has gone down since, drop request */
- GNUNET_assert (0 != memcmp (&car->target,
- &GSC_my_identity,
- sizeof(struct GNUNET_PeerIdentity)));
+ GNUNET_assert (0 !=
+ GNUNET_memcmp (&car->target,
+ &GSC_my_identity));
GSC_SESSIONS_dequeue_request (car);
GSC_CLIENTS_reject_request (car, GNUNET_NO);
return;
@@ -314,9 +314,8 @@ handle_client_send_request (void *cls, const struct SendMessageRequest *req)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client asked for transmission to `%s'\n",
GNUNET_i2s (&req->peer));
- is_loopback = (0 == memcmp (&req->peer,
- &GSC_my_identity,
- sizeof(struct GNUNET_PeerIdentity)));
+ is_loopback = (0 == GNUNET_memcmp (&req->peer,
+ &GSC_my_identity));
if ((! is_loopback) &&
(GNUNET_YES !=
GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &req->peer)))
@@ -419,9 +418,8 @@ tokenized_cb (void *cls, const struct GNUNET_MessageHeader *message)
gettext_noop ("# bytes of messages of type %u received"),
(unsigned int) ntohs (message->type));
GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO);
- if (0 == memcmp (&car->target,
- &GSC_my_identity,
- sizeof(struct GNUNET_PeerIdentity)))
+ if (0 == GNUNET_memcmp (&car->target,
+ &GSC_my_identity))
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Delivering message of type %u to myself\n",
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
index a79ef075b..07c346485 100644
--- a/src/core/gnunet-service-core_kx.c
+++ b/src/core/gnunet-service-core_kx.c
@@ -1797,8 +1797,8 @@ do_rekey (void *cls)
int
GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
{
- struct GNUNET_MQ_MessageHandler handlers[] =
- { GNUNET_MQ_hd_fixed_size (ephemeral_key,
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_fixed_size (ephemeral_key,
GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
struct EphemeralKeyMessage,
NULL),
@@ -1814,7 +1814,8 @@ GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
struct EncryptedMessage,
NULL),
- GNUNET_MQ_handler_end () };
+ GNUNET_MQ_handler_end ()
+ };
my_private_key = *pk;
GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
diff --git a/src/curl/curl.c b/src/curl/curl.c
index 30c2f8c01..e45612e94 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -201,14 +201,6 @@ struct GNUNET_CURL_Context
};
-/**
- * Force use of the provided username and password
- * for client authentication for all operations performed
- * with @a ctx.
- *
- * @param ctx context to set authentication data for
- * @param userpass string with "$USERNAME:$PASSWORD"
- */
void
GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
const char *userpass)
@@ -219,21 +211,6 @@ GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Force use of the provided TLS client certificate
- * for client authentication for all operations performed
- * with @a ctx.
- *
- * Note that if the provided information is incorrect,
- * the earliest operation that could fail is
- * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()!
- *
- * @param ctx context to set authentication data for
- * @param certtype type of the certificate
- * @param certfile file with the certificate
- * @param keyfile file with the private key
- * @param keypass passphrase to decrypt @a keyfile (or NULL)
- */
void
GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
const char *certtype,
@@ -256,14 +233,6 @@ GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Initialise this library. This function should be called before using any of
- * the following functions.
- *
- * @param cb function to call when rescheduling is required
- * @param cb_cls closure for @a cb
- * @return library context
- */
struct GNUNET_CURL_Context *
GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
void *cb_cls)
@@ -299,12 +268,6 @@ GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb,
}
-/**
- * Enable sending the async scope ID as a header.
- *
- * @param ctx the context to enable this for
- * @param header_name name of the header to send.
- */
void
GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx,
const char *header_name)
@@ -313,15 +276,6 @@ GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Return #GNUNET_YES if given a valid scope ID and
- * #GNUNET_NO otherwise. See #setup_job_headers,
- * logic related to
- * #GNUNET_CURL_enable_async_scope_header() for the
- * code that generates such a @a scope_id.
- *
- * @returns #GNUNET_YES iff given a valid scope ID
- */
int
GNUNET_CURL_is_valid_scope_id (const char *scope_id)
{
@@ -447,7 +401,9 @@ setup_job (CURL *eh,
struct GNUNET_CURL_Job *job;
if (CURLE_OK !=
- curl_easy_setopt (eh, CURLOPT_HTTPHEADER, all_headers))
+ curl_easy_setopt (eh,
+ CURLOPT_HTTPHEADER,
+ all_headers))
{
GNUNET_break (0);
curl_slist_free_all (all_headers);
@@ -491,12 +447,6 @@ setup_job (CURL *eh,
}
-/**
- * Add @a extra_headers to the HTTP headers for @a job.
- *
- * @param[in,out] job the job to modify
- * @param extra_headers headers to append
- */
void
GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
const struct curl_slist *extra_headers)
@@ -515,21 +465,6 @@ GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
}
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion. Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh. Used to download
- * resources that are NOT in JSON. The raw body will be returned.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- * be executed AND cleaned up
- * @param job_headers extra headers to add for this request
- * @param max_reply_size largest acceptable response body
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
struct GNUNET_CURL_Job *
GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
CURL *eh,
@@ -554,25 +489,6 @@ GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion. Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.
- *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header if @a add_json is set.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will be executed AND
- * cleaned up. NOTE: the handle should _never_ have gotten
- * any headers list, as that would then be overridden by
- * @a jcc. Therefore, always pass custom headers as the
- * @a job_headers parameter.
- * @param job_headers extra headers to add for this request
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
struct GNUNET_CURL_Job *
GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
CURL *eh,
@@ -624,21 +540,6 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion. Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.
- *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- * be executed AND cleaned up
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
struct GNUNET_CURL_Job *
GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
CURL *eh,
@@ -661,18 +562,6 @@ GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion. Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- * be executed AND cleaned up
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- * @return NULL on error (in this case, @eh is still released!)
- */
struct GNUNET_CURL_Job *
GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
CURL *eh,
@@ -687,12 +576,6 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Cancel a job. Must only be called before the job completion
- * callback is called for the respective job.
- *
- * @param job job to cancel
- */
void
GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job)
{
@@ -746,24 +629,6 @@ is_json (const char *ct)
}
-/**
- * Obtain information about the final result about the
- * HTTP download. If the download was successful, parses
- * the JSON in the @a db and returns it. Also returns
- * the HTTP @a response_code. If the download failed,
- * the return value is NULL. The response code is set
- * in any case, on download errors to zero.
- *
- * Calling this function also cleans up @a db.
- *
- * @param db download buffer
- * @param eh CURL handle (to get the response code)
- * @param[out] response_code set to the HTTP response code
- * (or zero if we aborted the download, for example
- * because the response was too big, or if
- * the JSON we received was malformed).
- * @return NULL if downloading a JSON reply failed.
- */
void *
GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
CURL *eh,
@@ -838,13 +703,6 @@ GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
}
-/**
- * Add custom request header.
- *
- * @param ctx cURL context.
- * @param header header string; will be given to the context AS IS.
- * @return #GNUNET_OK if no errors occurred, #GNUNET_SYSERR otherwise.
- */
enum GNUNET_GenericReturnValue
GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
const char *header)
@@ -858,93 +716,6 @@ GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx,
}
-#if ENABLE_BENCHMARK
-static void
-do_benchmark (CURLMsg *cmsg)
-{
- char *url = NULL;
- double total_as_double = 0;
- struct GNUNET_TIME_Relative total;
- struct UrlRequestData *urd;
- /* Some care required, as curl is using data types (long vs curl_off_t vs
- * double) inconsistently to store byte count. */
- curl_off_t size_curl = 0;
- long size_long = 0;
- uint64_t bytes_sent = 0;
- uint64_t bytes_received = 0;
-
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_TOTAL_TIME,
- &total_as_double));
- total.rel_value_us = total_as_double * 1000 * 1000;
-
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_EFFECTIVE_URL,
- &url));
-
- /* HEADER_SIZE + SIZE_DOWNLOAD_T is hopefully the total
- number of bytes received, not clear from curl docs. */
-
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_HEADER_SIZE,
- &size_long));
- bytes_received += size_long;
-
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_SIZE_DOWNLOAD_T,
- &size_curl));
- bytes_received += size_curl;
-
- /* REQUEST_SIZE + SIZE_UPLOAD_T is hopefully the total number of bytes
- sent, again docs are not completely clear. */
-
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_REQUEST_SIZE,
- &size_long));
- bytes_sent += size_long;
-
- /* We obtain this value to check an invariant, but never use it otherwise. */
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_SIZE_UPLOAD_T,
- &size_curl));
-
- /* CURLINFO_SIZE_UPLOAD_T <= CURLINFO_REQUEST_SIZE should
- be an invariant.
- As verified with
- curl -w "foo%{size_request} -XPOST --data "ABC" $URL
- the CURLINFO_REQUEST_SIZE should be the whole size of the request
- including headers and body.
- */
- GNUNET_break (size_curl <= size_long);
-
- urd = get_url_benchmark_data (url, (unsigned int) response_code);
- urd->count++;
- urd->time = GNUNET_TIME_relative_add (urd->time,
- total);
- urd->time_max = GNUNET_TIME_relative_max (total,
- urd->time_max);
- urd->bytes_sent += bytes_sent;
- urd->bytes_received += bytes_received;
-}
-
-
-#endif
-
-
-/**
- * Run the main event loop for the HTTP interaction.
- *
- * @param ctx the library context
- * @param rp parses the raw response returned from
- * the Web server.
- * @param rc cleans/frees the response
- */
void
GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
GNUNET_CURL_RawParser rp,
@@ -994,19 +765,11 @@ GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx,
response);
rc (response);
}
-#if ENABLE_BENCHMARK
- do_benchmark (cmsg);
-#endif
GNUNET_CURL_job_cancel (job);
}
}
-/**
- * Run the main event loop for the HTTP interaction.
- *
- * @param ctx the library context
- */
void
GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
{
@@ -1016,34 +779,6 @@ GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx)
}
-/**
- * Obtain the information for a select() call to wait until
- * #GNUNET_CURL_perform() is ready again. Note that calling
- * any other GNUNET_CURL-API may also imply that the library
- * is again ready for #GNUNET_CURL_perform().
- *
- * Basically, a client should use this API to prepare for select(),
- * then block on select(), then call #GNUNET_CURL_perform() and then
- * start again until the work with the context is done.
- *
- * This function will NOT zero out the sets and assumes that @a max_fd
- * and @a timeout are already set to minimal applicable values. It is
- * safe to give this API FD-sets and @a max_fd and @a timeout that are
- * already initialized to some other descriptors that need to go into
- * the select() call.
- *
- * @param ctx context to get the event loop information for
- * @param read_fd_set will be set for any pending read operations
- * @param write_fd_set will be set for any pending write operations
- * @param except_fd_set is here because curl_multi_fdset() has this argument
- * @param max_fd set to the highest FD included in any set;
- * if the existing sets have no FDs in it, the initial
- * value should be "-1". (Note that `max_fd + 1` will need
- * to be passed to select().)
- * @param timeout set to the timeout in milliseconds (!); -1 means
- * no timeout (NULL, blocking forever is OK), 0 means to
- * proceed immediately with #GNUNET_CURL_perform().
- */
void
GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx,
fd_set *read_fd_set,
@@ -1077,13 +812,6 @@ GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx,
}
-/**
- * Cleanup library initialisation resources. This function should be called
- * after using this library to cleanup the resources occupied during library's
- * initialisation.
- *
- * @param ctx the library context
- */
void
GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx)
{
diff --git a/src/curl/curl_reschedule.c b/src/curl/curl_reschedule.c
index a1fe55aa5..0c19bd171 100644
--- a/src/curl/curl_reschedule.c
+++ b/src/curl/curl_reschedule.c
@@ -59,12 +59,6 @@ struct GNUNET_CURL_RescheduleContext
};
-/**
- * Initialize reschedule context; with custom response parser
- *
- * @param ctx context to manage
- * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
- */
struct GNUNET_CURL_RescheduleContext *
GNUNET_CURL_gnunet_rc_create_with_parser (struct GNUNET_CURL_Context *ctx,
GNUNET_CURL_RawParser rp,
@@ -93,12 +87,6 @@ clean_result (void *response)
}
-/**
- * Initialize reschedule context.
- *
- * @param ctx context to manage
- * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
- */
struct GNUNET_CURL_RescheduleContext *
GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx)
{
@@ -112,11 +100,6 @@ GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx)
}
-/**
- * Destroy reschedule context.
- *
- * @param rc context to destroy
- */
void
GNUNET_CURL_gnunet_rc_destroy (struct GNUNET_CURL_RescheduleContext *rc)
{
@@ -159,13 +142,18 @@ context_task (void *cls)
&timeout);
if (timeout >= 0)
delay =
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, timeout);
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+ timeout);
else
delay = GNUNET_TIME_UNIT_FOREVER_REL;
rs = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (rs, &read_fd_set, max_fd + 1);
+ GNUNET_NETWORK_fdset_copy_native (rs,
+ &read_fd_set,
+ max_fd + 1);
ws = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (ws, &write_fd_set, max_fd + 1);
+ GNUNET_NETWORK_fdset_copy_native (ws,
+ &write_fd_set,
+ max_fd + 1);
if (NULL == rc->task)
rc->task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
delay,
@@ -178,15 +166,6 @@ context_task (void *cls)
}
-/**
- * Implementation of the #GNUNET_CURL_RescheduleCallback for GNUnet's
- * scheduler. Will run the CURL context using GNUnet's scheduler.
- * Note that you MUST immediately destroy the reschedule context after
- * calling #GNUNET_CURL_fini().
- *
- * @param cls must point to a `struct GNUNET_CURL_RescheduleContext *`
- * (pointer to a pointer!)
- */
void
GNUNET_CURL_gnunet_scheduler_reschedule (void *cls)
{
@@ -194,7 +173,8 @@ GNUNET_CURL_gnunet_scheduler_reschedule (void *cls)
if (NULL != rc->task)
GNUNET_SCHEDULER_cancel (rc->task);
- rc->task = GNUNET_SCHEDULER_add_now (&context_task, rc);
+ rc->task = GNUNET_SCHEDULER_add_now (&context_task,
+ rc);
}
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 331a9b784..c93ed58d6 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2015 GNUnet e.V.
+ Copyright (C) 2004-2010, 2015, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -101,7 +101,9 @@ struct GNUNET_DATACACHE_Handle
* @param size number of bytes that were made available
*/
static void
-env_delete_notify (void *cls, const struct GNUNET_HashCode *key, size_t size)
+env_delete_notify (void *cls,
+ const struct GNUNET_HashCode *key,
+ size_t size)
{
struct GNUNET_DATACACHE_Handle *h = cls;
@@ -112,23 +114,16 @@ env_delete_notify (void *cls, const struct GNUNET_HashCode *key, size_t size)
h->utilization -= size;
GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# bytes stored"),
+ "# bytes stored",
-(long long) size,
GNUNET_NO);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# items stored"),
+ "# items stored",
-1,
GNUNET_NO);
}
-/**
- * Create a data cache.
- *
- * @param cfg configuration to use
- * @param section section in the configuration that contains our options
- * @return handle to use to access the service
- */
struct GNUNET_DATACACHE_Handle *
GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *section)
@@ -141,15 +136,25 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
const struct GNUNET_OS_ProjectData *pd;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota))
+ GNUNET_CONFIGURATION_get_value_size (cfg,
+ section,
+ "QUOTA",
+ &quota))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "QUOTA");
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "QUOTA");
return NULL;
}
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name))
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "DATABASE",
+ &name))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "DATABASE");
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "DATABASE");
return NULL;
}
bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
@@ -157,10 +162,14 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
ret = GNUNET_new (struct GNUNET_DATACACHE_Handle);
if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF"))
+ GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ section,
+ "DISABLE_BF"))
{
if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC"))
+ GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ section,
+ "DISABLE_BF_RC"))
{
ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
}
@@ -179,7 +188,8 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
5); /* approx. 3% false positives at max use */
}
}
- ret->stats = GNUNET_STATISTICS_create ("datacache", cfg);
+ ret->stats = GNUNET_STATISTICS_create ("datacache",
+ cfg);
ret->section = GNUNET_strdup (section);
ret->env.cfg = cfg;
ret->env.delete_notify = &env_delete_notify;
@@ -187,25 +197,31 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
ret->env.cls = ret;
ret->env.delete_notify = &env_delete_notify;
ret->env.quota = quota;
- LOG (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' datacache plugin\n"), name);
- GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name);
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ "Loading `%s' datacache plugin\n",
+ name);
+ GNUNET_asprintf (&libname,
+ "libgnunet_plugin_datacache_%s",
+ name);
ret->short_name = name;
ret->lib_name = libname;
/* Load the plugin within GNUnet's default context */
pd = GNUNET_OS_project_data_get ();
- GNUNET_OS_init(GNUNET_OS_project_data_default ());
- ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
- GNUNET_OS_init(pd);
+ GNUNET_OS_init (GNUNET_OS_project_data_default ());
+ ret->api = GNUNET_PLUGIN_load (libname,
+ &ret->env);
+ GNUNET_OS_init (pd);
if (NULL == ret->api)
{
/* Try to load the plugin within the application's context
This normally happens when the application is not GNUnet itself but a
third party; inside GNUnet this is effectively a double failure. */
- ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
+ ret->api = GNUNET_PLUGIN_load (libname,
+ &ret->env);
if (NULL == ret->api)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
- _ ("Failed to load datacache plugin for `%s'\n"),
+ "Failed to load datacache plugin for `%s'\n",
name);
GNUNET_DATACACHE_destroy (ret);
return NULL;
@@ -215,18 +231,15 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
}
-/**
- * Destroy a data cache (and free associated resources).
- *
- * @param h handle to the datastore
- */
void
GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
{
if (NULL != h->filter)
GNUNET_CONTAINER_bloomfilter_free (h->filter);
if (NULL != h->api)
- GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api));
+ GNUNET_break (NULL ==
+ GNUNET_PLUGIN_unload (h->lib_name,
+ h->api));
GNUNET_free (h->lib_name);
GNUNET_free (h->short_name);
GNUNET_free (h->section);
@@ -244,42 +257,16 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
}
-/**
- * Store an item in the datastore.
- *
- * @param h handle to the datacache
- * @param key key to store data under
- * @param xor_distance distance of @a key to our PID
- * @param data_size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error, #GNUNET_NO if duplicate
- */
-int
+enum GNUNET_GenericReturnValue
GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
- const struct GNUNET_HashCode *key,
uint32_t xor_distance,
- size_t data_size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute discard_time,
- unsigned int path_info_len,
- const struct GNUNET_PeerIdentity *path_info)
+ const struct GNUNET_DATACACHE_Block *block)
{
ssize_t used;
used = h->api->put (h->api->cls,
- key,
xor_distance,
- data_size,
- data,
- type,
- discard_time,
- path_info_len,
- path_info);
+ block);
if (-1 == used)
{
GNUNET_break (0);
@@ -292,35 +279,26 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Stored data under key `%s' in cache\n",
- GNUNET_h2s (key));
+ GNUNET_h2s (&block->key));
if (NULL != h->filter)
- GNUNET_CONTAINER_bloomfilter_add (h->filter, key);
+ GNUNET_CONTAINER_bloomfilter_add (h->filter,
+ &block->key);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# bytes stored"),
+ "# bytes stored",
used,
GNUNET_NO);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# items stored"),
+ "# items stored",
1,
GNUNET_NO);
while (h->utilization + used > h->env.quota)
- GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls));
+ GNUNET_assert (GNUNET_OK ==
+ h->api->del (h->api->cls));
h->utilization += used;
return GNUNET_OK;
}
-/**
- * Iterate over the results for a particular key
- * in the datacache.
- *
- * @param h handle to the datacache
- * @param key what to look up
- * @param type entries of which type are relevant?
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found
- */
unsigned int
GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
const struct GNUNET_HashCode *key,
@@ -329,18 +307,19 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
void *iter_cls)
{
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# requests received"),
+ "# requests received",
1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing request for key `%s'\n",
GNUNET_h2s (key));
- if ((NULL != h->filter) &&
- (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key)))
+ if ( (NULL != h->filter) &&
+ (GNUNET_OK !=
+ GNUNET_CONTAINER_bloomfilter_test (h->filter,
+ key)) )
{
GNUNET_STATISTICS_update (h->stats,
- gettext_noop (
- "# requests filtered by bloom filter"),
+ "# requests filtered by bloom filter",
1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -348,62 +327,34 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
GNUNET_h2s (key));
return 0; /* can not be present */
}
- return h->api->get (h->api->cls, key, type, iter, iter_cls);
-}
-
-
-/**
- * Obtain a random element from the datacache.
- *
- * @param h handle to the datacache
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found (zero or 1)
- */
-unsigned int
-GNUNET_DATACACHE_get_random (struct GNUNET_DATACACHE_Handle *h,
- GNUNET_DATACACHE_Iterator iter,
- void *iter_cls)
-{
- GNUNET_STATISTICS_update (h->stats,
- gettext_noop (
- "# requests for random value received"),
- 1,
- GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing request for random value\n");
- return h->api->get_random (h->api->cls, iter, iter_cls);
+ return h->api->get (h->api->cls,
+ key,
+ type,
+ iter, iter_cls);
}
-/**
- * Iterate over the results that are "close" to a particular key in
- * the datacache. "close" is defined as numerically larger than @a
- * key (when interpreted as a circular address space), with small
- * distance.
- *
- * @param h handle to the datacache
- * @param key area of the keyspace to look into
- * @param num_results number of results that should be returned to @a iter
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found
- */
unsigned int
GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
GNUNET_STATISTICS_update (h->stats,
- gettext_noop (
- "# proximity search requests received"),
+ "# proximity search requests received",
1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing proximity search at `%s'\n",
GNUNET_h2s (key));
- return h->api->get_closest (h->api->cls, key, num_results, iter, iter_cls);
+ return h->api->get_closest (h->api->cls,
+ key,
+ type,
+ num_results,
+ iter,
+ iter_cls);
}
diff --git a/src/datacache/perf_datacache.c b/src/datacache/perf_datacache.c
index ce3b4c25d..84bc4a852 100644
--- a/src/datacache/perf_datacache.c
+++ b/src/datacache/perf_datacache.c
@@ -47,21 +47,27 @@ static const char *plugin_name;
static int
checkIt (void *cls,
- const struct GNUNET_HashCode *key, size_t size, const char *data,
+ const struct GNUNET_HashCode *key,
+ size_t size,
+ const char *data,
enum GNUNET_BLOCK_Type type,
struct GNUNET_TIME_Absolute exp,
unsigned int path_len,
- const struct GNUNET_PeerIdentity *path)
+ const struct GNUNET_DHT_PathElement *path)
{
- if ((size == sizeof(struct GNUNET_HashCode)) && (0 == memcmp (data, cls,
- size)))
+ if ( (size == sizeof(struct GNUNET_HashCode)) &&
+ (0 == memcmp (data,
+ cls,
+ size)) )
found++;
return GNUNET_OK;
}
static void
-run (void *cls, char *const *args, const char *cfgfile,
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_DATACACHE_Handle *h;
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index 074437e7d..0dd8e47f8 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2012, 2015 GNUnet e.V.
+ Copyright (C) 2012, 2015, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -63,14 +63,9 @@ struct Plugin
struct Value
{
/**
- * Key for the entry.
+ * Block data.
*/
- struct GNUNET_HashCode key;
-
- /**
- * Expiration time.
- */
- struct GNUNET_TIME_Absolute discard_time;
+ struct GNUNET_DATACACHE_Block block;
/**
* Corresponding node in the heap.
@@ -78,29 +73,15 @@ struct Value
struct GNUNET_CONTAINER_HeapNode *hn;
/**
- * Path information.
- */
- struct GNUNET_PeerIdentity *path_info;
-
- /**
- * Payload (actual payload follows this struct)
- */
- size_t size;
-
- /**
- * Number of entries in @e path_info.
+ * Put path as a non-const pointer.
*/
- unsigned int path_info_len;
+ struct GNUNET_DHT_PathElement *put_path;
/**
* How close is the hash to us? Determines which heap we are in!
*/
uint32_t distance;
- /**
- * Type of the block.
- */
- enum GNUNET_BLOCK_Type type;
};
@@ -113,39 +94,14 @@ struct Value
struct PutContext
{
/**
- * Expiration time for the new value.
- */
- struct GNUNET_TIME_Absolute discard_time;
-
- /**
- * Data for the new value.
- */
- const char *data;
-
- /**
- * Path information.
+ * Block data.
*/
- const struct GNUNET_PeerIdentity *path_info;
+ const struct GNUNET_DATACACHE_Block *block;
/**
- * Number of bytes in @e data.
+ * Value to set to true if an equivalent block was found.
*/
- size_t size;
-
- /**
- * Type of the node.
- */
- enum GNUNET_BLOCK_Type type;
-
- /**
- * Number of entries in @e path_info.
- */
- unsigned int path_info_len;
-
- /**
- * Value to set to #GNUNET_YES if an equivalent block was found.
- */
- int found;
+ bool found;
};
@@ -158,7 +114,7 @@ struct PutContext
* @param value an existing value
* @return #GNUNET_YES if not found (to continue to iterate)
*/
-static int
+static enum GNUNET_GenericReturnValue
put_cb (void *cls,
const struct GNUNET_HashCode *key,
void *value)
@@ -166,30 +122,31 @@ put_cb (void *cls,
struct PutContext *put_ctx = cls;
struct Value *val = value;
- if ((val->size == put_ctx->size) &&
- (val->type == put_ctx->type) &&
- (0 == memcmp (&val[1],
- put_ctx->data,
- put_ctx->size)))
+ if ((val->block.data_size == put_ctx->block->data_size) &&
+ (val->block.type == put_ctx->block->type) &&
+ (0 == memcmp (val->block.data,
+ put_ctx->block->data,
+ put_ctx->block->data_size)))
{
- put_ctx->found = GNUNET_YES;
- val->discard_time = GNUNET_TIME_absolute_max (val->discard_time,
- put_ctx->discard_time);
+ put_ctx->found = true;
+ val->block.expiration_time
+ = GNUNET_TIME_absolute_max (val->block.expiration_time,
+ put_ctx->block->expiration_time);
/* replace old path with new path */
- GNUNET_array_grow (val->path_info,
- val->path_info_len,
- put_ctx->path_info_len);
- GNUNET_memcpy (val->path_info,
- put_ctx->path_info,
- put_ctx->path_info_len * sizeof(struct GNUNET_PeerIdentity));
+ GNUNET_free (val->put_path);
+ val->put_path = GNUNET_memdup (put_ctx->block->put_path,
+ put_ctx->block->put_path_length
+ * sizeof (struct GNUNET_DHT_PathElement));
+ val->block.put_path = val->put_path;
+ val->block.put_path_length = put_ctx->block->put_path_length;
GNUNET_CONTAINER_heap_update_cost (val->hn,
- val->discard_time.abs_value_us);
+ val->block.expiration_time.abs_value_us);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got same value for key %s and type %d (size %u vs %u)\n",
+ "Got same value for key %s and type %u (size %u vs %u)\n",
GNUNET_h2s (key),
- val->type,
- (unsigned int) val->size,
- (unsigned int) put_ctx->size);
+ (unsigned int) val->block.type,
+ (unsigned int) val->block.data_size,
+ (unsigned int) put_ctx->block->data_size);
return GNUNET_NO;
}
return GNUNET_YES;
@@ -200,70 +157,61 @@ put_cb (void *cls,
* Store an item in the datastore.
*
* @param cls closure (our `struct Plugin`)
- * @param key key to store data under
* @param xor_distance how close is @a key to our PID?
- * @param size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block data to store
* @return 0 if duplicate, -1 on error, number of bytes used otherwise
*/
static ssize_t
heap_plugin_put (void *cls,
- const struct GNUNET_HashCode *key,
uint32_t xor_distance,
- size_t size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute discard_time,
- unsigned int path_info_len,
- const struct GNUNET_PeerIdentity *path_info)
+ const struct GNUNET_DATACACHE_Block *block)
{
struct Plugin *plugin = cls;
struct Value *val;
- struct PutContext put_ctx;
-
- put_ctx.found = GNUNET_NO;
- put_ctx.data = data;
- put_ctx.size = size;
- put_ctx.path_info = path_info;
- put_ctx.path_info_len = path_info_len;
- put_ctx.discard_time = discard_time;
- put_ctx.type = type;
+ struct PutContext put_ctx = {
+ .block = block,
+ .found = false
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Storing %u bytes under key %s with path length %u\n",
+ (unsigned int) block->data_size,
+ GNUNET_h2s (&block->key),
+ block->put_path_length);
GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map,
- key,
+ &block->key,
&put_cb,
&put_ctx);
if (GNUNET_YES == put_ctx.found)
return 0;
- val = GNUNET_malloc (sizeof(struct Value) + size);
+ val = GNUNET_malloc (sizeof(struct Value)
+ + block->data_size);
GNUNET_memcpy (&val[1],
- data,
- size);
- val->key = *key;
- val->type = type;
- val->discard_time = discard_time;
- val->size = size;
+ block->data,
+ block->data_size);
+ val->block = *block;
+ val->block.data = &val[1];
if (xor_distance >= NUM_HEAPS)
val->distance = NUM_HEAPS - 1;
else
val->distance = xor_distance;
- GNUNET_array_grow (val->path_info,
- val->path_info_len,
- path_info_len);
- GNUNET_memcpy (val->path_info,
- path_info,
- path_info_len * sizeof(struct GNUNET_PeerIdentity));
+ if (0 != block->put_path_length)
+ {
+ val->put_path
+ = GNUNET_memdup (block->put_path,
+ block->put_path_length
+ * sizeof (struct GNUNET_DHT_PathElement));
+ val->block.put_path = val->put_path;
+ }
(void) GNUNET_CONTAINER_multihashmap_put (plugin->map,
- &val->key,
+ &val->block.key,
val,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- val->hn = GNUNET_CONTAINER_heap_insert (plugin->heaps[val->distance],
- val,
- val->discard_time.abs_value_us);
- return size + OVERHEAD;
+ val->hn = GNUNET_CONTAINER_heap_insert (
+ plugin->heaps[val->distance],
+ val,
+ val->block.expiration_time.abs_value_us);
+ return val->block.data_size + OVERHEAD;
}
@@ -303,30 +251,37 @@ struct GetContext
* @param value an existing value
* @return #GNUNET_YES to continue to iterate
*/
-static int
+static enum GNUNET_GenericReturnValue
get_cb (void *cls,
const struct GNUNET_HashCode *key,
void *value)
{
struct GetContext *get_ctx = cls;
struct Value *val = value;
- int ret;
+ enum GNUNET_GenericReturnValue ret;
- if ((get_ctx->type != val->type) &&
- (GNUNET_BLOCK_TYPE_ANY != get_ctx->type))
+ if ( (get_ctx->type != val->block.type) &&
+ (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Result for key %s does not match block type %d\n",
+ GNUNET_h2s (key),
+ get_ctx->type);
return GNUNET_OK;
- if (0 ==
- GNUNET_TIME_absolute_get_remaining (val->discard_time).rel_value_us)
+ }
+ if (GNUNET_TIME_absolute_is_past (val->block.expiration_time))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Result for key %s is expired\n",
+ GNUNET_h2s (key));
return GNUNET_OK;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found result for key %s\n",
+ GNUNET_h2s (key));
if (NULL != get_ctx->iter)
ret = get_ctx->iter (get_ctx->iter_cls,
- key,
- val->size,
- (const char *) &val[1],
- val->type,
- val->discard_time,
- val->path_info_len,
- val->path_info);
+ &val->block);
else
ret = GNUNET_YES;
get_ctx->cnt++;
@@ -374,7 +329,7 @@ heap_plugin_get (void *cls,
* @param cls closure (our `struct Plugin`)
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
-static int
+static enum GNUNET_GenericReturnValue
heap_plugin_del (void *cls)
{
struct Plugin *plugin = cls;
@@ -390,58 +345,34 @@ heap_plugin_del (void *cls)
return GNUNET_SYSERR;
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (plugin->map,
- &val->key,
+ &val->block.key,
val));
plugin->env->delete_notify (plugin->env->cls,
- &val->key,
- val->size + OVERHEAD);
- GNUNET_free (val->path_info);
+ &val->block.key,
+ val->block.data_size + OVERHEAD);
+ GNUNET_free (val->put_path);
GNUNET_free (val);
return GNUNET_OK;
}
/**
- * Return a random value from the datastore.
- *
- * @param cls closure (our `struct Plugin`)
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found
- */
-static unsigned int
-heap_plugin_get_random (void *cls,
- GNUNET_DATACACHE_Iterator iter,
- void *iter_cls)
-{
- struct Plugin *plugin = cls;
- struct GetContext get_ctx;
-
- get_ctx.type = GNUNET_BLOCK_TYPE_ANY;
- get_ctx.iter = iter;
- get_ctx.iter_cls = iter_cls;
- get_ctx.cnt = 0;
- GNUNET_CONTAINER_multihashmap_get_random (plugin->map,
- &get_cb,
- &get_ctx);
- return get_ctx.cnt;
-}
-
-
-/**
* Closure for #find_closest().
*/
struct GetClosestContext
{
struct Value **values;
+ const struct GNUNET_HashCode *key;
+
+ enum GNUNET_BLOCK_Type type;
+
unsigned int num_results;
- const struct GNUNET_HashCode *key;
};
-static int
+static enum GNUNET_GenericReturnValue
find_closest (void *cls,
const struct GNUNET_HashCode *key,
void *value)
@@ -453,6 +384,9 @@ find_closest (void *cls,
if (1 != GNUNET_CRYPTO_hash_cmp (key,
gcc->key))
return GNUNET_OK; /* useless */
+ if ( (val->block.type != gcc->type) &&
+ (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
+ return GNUNET_OK; /* useless */
j = gcc->num_results;
for (unsigned int i = 0; i < gcc->num_results; i++)
{
@@ -461,8 +395,9 @@ find_closest (void *cls,
j = i;
break;
}
- if (1 == GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key,
- key))
+ if (1 ==
+ GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->block.key,
+ key))
{
j = i;
break;
@@ -483,6 +418,7 @@ find_closest (void *cls,
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -491,6 +427,7 @@ find_closest (void *cls,
static unsigned int
heap_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
@@ -499,27 +436,29 @@ heap_plugin_get_closest (void *cls,
struct Value *values[num_results];
struct GetClosestContext gcc = {
.values = values,
- .num_results = num_results,
+ .type = type,
+ .num_results = num_results * 2,
.key = key
};
GNUNET_CONTAINER_multihashmap_iterate (plugin->map,
&find_closest,
&gcc);
- for (unsigned int i = 0; i < num_results; i++)
+ for (unsigned int i = 0; i < num_results * 2; i++)
{
if (NULL == values[i])
return i;
- iter (iter_cls,
- &values[i]->key,
- values[i]->size,
- (void *) &values[i][1],
- values[i]->type,
- values[i]->discard_time,
- values[i]->path_info_len,
- values[i]->path_info);
+ if ( (NULL != iter) &&
+ (GNUNET_SYSERR ==
+ iter (iter_cls,
+ &values[i]->block)) )
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Ending iteration (client error)\n");
+ return i;
+ }
}
- return num_results;
+ return num_results * 2;
}
@@ -548,7 +487,6 @@ libgnunet_plugin_datacache_heap_init (void *cls)
api->get = &heap_plugin_get;
api->put = &heap_plugin_put;
api->del = &heap_plugin_del;
- api->get_random = &heap_plugin_get_random;
api->get_closest = &heap_plugin_get_closest;
LOG (GNUNET_ERROR_TYPE_INFO,
_ ("Heap datacache running\n"));
@@ -575,9 +513,9 @@ libgnunet_plugin_datacache_heap_done (void *cls)
{
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (plugin->map,
- &val->key,
+ &val->block.key,
val));
- GNUNET_free (val->path_info);
+ GNUNET_free (val->put_path);
GNUNET_free (val);
}
GNUNET_CONTAINER_heap_destroy (plugin->heaps[i]);
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c
index 6613ae928..b1f9a1b8e 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018 GNUnet e.V.
+ Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -63,66 +63,76 @@ struct Plugin
* @param plugin global context
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
-static int
+static enum GNUNET_GenericReturnValue
init_connection (struct Plugin *plugin)
{
struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute ("CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn011dc_oid_seq"),
- GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn011dc ("
- " oid OID NOT NULL DEFAULT nextval('gn011dc_oid_seq'),"
- " type INTEGER NOT NULL,"
- " prox INTEGER NOT NULL,"
- " discard_time BIGINT NOT NULL,"
- " key BYTEA NOT NULL,"
+ GNUNET_PQ_make_try_execute (
+ "CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn180dc_oid_seq"),
+ GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn180dc ("
+ " oid OID NOT NULL DEFAULT nextval('gn180dc_oid_seq'),"
+ " type INT4 NOT NULL,"
+ " ro INT4 NOT NULL,"
+ " prox INT4 NOT NULL,"
+ " expiration_time INT8 NOT NULL,"
+ " key BYTEA NOT NULL CHECK(LENGTH(key)=64),"
+ " trunc BYTEA NOT NULL CHECK(LENGTH(trunc)=32),"
" value BYTEA NOT NULL,"
" path BYTEA DEFAULT NULL)"),
GNUNET_PQ_make_try_execute (
- "ALTER SEQUENCE gnu011dc_oid_seq OWNED BY gn011dc.oid"),
+ "ALTER SEQUENCE gnu011dc_oid_seq OWNED BY gn180dc.oid"),
GNUNET_PQ_make_try_execute (
- "CREATE INDEX IF NOT EXISTS idx_oid ON gn011dc (oid)"),
+ "CREATE INDEX IF NOT EXISTS idx_oid ON gn180dc (oid)"),
GNUNET_PQ_make_try_execute (
- "CREATE INDEX IF NOT EXISTS idx_key ON gn011dc (key)"),
+ "CREATE INDEX IF NOT EXISTS idx_key ON gn180dc (key)"),
GNUNET_PQ_make_try_execute (
- "CREATE INDEX IF NOT EXISTS idx_dt ON gn011dc (discard_time)"),
+ "CREATE INDEX IF NOT EXISTS idx_dt ON gn180dc (expiration_time)"),
GNUNET_PQ_make_execute (
- "ALTER TABLE gn011dc ALTER value SET STORAGE EXTERNAL"),
- GNUNET_PQ_make_execute ("ALTER TABLE gn011dc ALTER key SET STORAGE PLAIN"),
+ "ALTER TABLE gn180dc ALTER value SET STORAGE EXTERNAL"),
+ GNUNET_PQ_make_execute ("ALTER TABLE gn180dc ALTER key SET STORAGE PLAIN"),
GNUNET_PQ_EXECUTE_STATEMENT_END
};
struct GNUNET_PQ_PreparedStatement ps[] = {
GNUNET_PQ_make_prepare ("getkt",
- "SELECT discard_time,type,value,path FROM gn011dc "
- "WHERE key=$1 AND type=$2 AND discard_time >= $3",
+ "SELECT expiration_time,type,ro,value,trunc,path FROM gn180dc "
+ "WHERE key=$1 AND type=$2 AND expiration_time >= $3",
3),
GNUNET_PQ_make_prepare ("getk",
- "SELECT discard_time,type,value,path FROM gn011dc "
- "WHERE key=$1 AND discard_time >= $2",
+ "SELECT expiration_time,type,ro,value,trunc,path FROM gn180dc "
+ "WHERE key=$1 AND expiration_time >= $2",
2),
GNUNET_PQ_make_prepare ("getex",
- "SELECT length(value) AS len,oid,key FROM gn011dc"
- " WHERE discard_time < $1"
- " ORDER BY discard_time ASC LIMIT 1",
+ "SELECT LENGTH(value) AS len,oid,key FROM gn180dc"
+ " WHERE expiration_time < $1"
+ " ORDER BY expiration_time ASC LIMIT 1",
1),
GNUNET_PQ_make_prepare ("getm",
- "SELECT length(value) AS len,oid,key FROM gn011dc"
- " ORDER BY prox ASC, discard_time ASC LIMIT 1",
+ "SELECT LENGTH(value) AS len,oid,key FROM gn180dc"
+ " ORDER BY prox ASC, expiration_time ASC LIMIT 1",
0),
- GNUNET_PQ_make_prepare ("get_random",
- "SELECT discard_time,type,value,path,key FROM gn011dc"
- " WHERE discard_time >= $1"
- " ORDER BY key ASC LIMIT 1 OFFSET $2",
- 2),
GNUNET_PQ_make_prepare ("get_closest",
- "SELECT discard_time,type,value,path,key FROM gn011dc "
- "WHERE key>=$1 AND discard_time >= $2 ORDER BY key ASC LIMIT $3",
- 3),
+ "(SELECT expiration_time,type,ro,value,trunc,path,key FROM gn180dc"
+ " WHERE key >= $1"
+ " AND expiration_time >= $2"
+ " AND ( (type = $3) OR ( 0 = $3) )"
+ " ORDER BY key ASC"
+ " LIMIT $4)"
+ " UNION "
+ "(SELECT expiration_time,type,ro,value,trunc,path,key FROM gn180dc"
+ " WHERE key <= $1"
+ " AND expiration_time >= $2"
+ " AND ( (type = $3) OR ( 0 = $3) )"
+ " ORDER BY key DESC"
+ " LIMIT $4)",
+ 4),
GNUNET_PQ_make_prepare ("delrow",
- "DELETE FROM gn011dc WHERE oid=$1",
+ "DELETE FROM gn180dc WHERE oid=$1",
1),
GNUNET_PQ_make_prepare ("put",
- "INSERT INTO gn011dc (type, prox, discard_time, key, value, path) "
- "VALUES ($1, $2, $3, $4, $5, $6)",
- 6),
+ "INSERT INTO gn180dc"
+ " (type, ro, prox, expiration_time, key, value, trunc, path) "
+ "VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
+ 8),
GNUNET_PQ_PREPARED_STATEMENT_END
};
@@ -141,38 +151,30 @@ init_connection (struct Plugin *plugin)
* Store an item in the datastore.
*
* @param cls closure (our `struct Plugin`)
- * @param key key to store @a data under
* @param prox proximity of @a key to my PID
- * @param data_size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block data to store
* @return 0 if duplicate, -1 on error, number of bytes used otherwise
*/
static ssize_t
postgres_plugin_put (void *cls,
- const struct GNUNET_HashCode *key,
uint32_t prox,
- size_t data_size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute discard_time,
- unsigned int path_info_len,
- const struct GNUNET_PeerIdentity *path_info)
+ const struct GNUNET_DATACACHE_Block *block)
{
struct Plugin *plugin = cls;
- uint32_t type32 = (uint32_t) type;
+ uint32_t type32 = (uint32_t) block->type;
+ uint32_t ro32 = (uint32_t) block->type;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint32 (&type32),
+ GNUNET_PQ_query_param_uint32 (&ro32),
GNUNET_PQ_query_param_uint32 (&prox),
- GNUNET_PQ_query_param_absolute_time (&discard_time),
- GNUNET_PQ_query_param_auto_from_type (key),
- GNUNET_PQ_query_param_fixed_size (data, data_size),
- GNUNET_PQ_query_param_fixed_size (path_info,
- path_info_len * sizeof(struct
- GNUNET_PeerIdentity)),
+ GNUNET_PQ_query_param_absolute_time (&block->expiration_time),
+ GNUNET_PQ_query_param_auto_from_type (&block->key),
+ GNUNET_PQ_query_param_fixed_size (block->data,
+ block->data_size),
+ GNUNET_PQ_query_param_auto_from_type (&block->trunc_peer),
+ GNUNET_PQ_query_param_fixed_size (block->put_path,
+ block->put_path_length
+ * sizeof(struct GNUNET_DHT_PathElement)),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus ret;
@@ -183,7 +185,7 @@ postgres_plugin_put (void *cls,
if (0 > ret)
return -1;
plugin->num_items++;
- return data_size + OVERHEAD;
+ return block->data_size + OVERHEAD;
}
@@ -227,23 +229,27 @@ handle_results (void *cls,
for (unsigned int i = 0; i < num_results; i++)
{
- struct GNUNET_TIME_Absolute expiration_time;
- uint32_t type;
+ uint32_t type32;
+ uint32_t bro32;
void *data;
- size_t data_size;
- struct GNUNET_PeerIdentity *path;
- size_t path_len;
+ struct GNUNET_DATACACHE_Block block;
+ void *path;
+ size_t path_size;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_absolute_time ("discard_time",
- &expiration_time),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+ &block.expiration_time),
GNUNET_PQ_result_spec_uint32 ("type",
- &type),
+ &type32),
+ GNUNET_PQ_result_spec_uint32 ("ro",
+ &bro32),
GNUNET_PQ_result_spec_variable_size ("value",
&data,
- &data_size),
+ &block.data_size),
+ GNUNET_PQ_result_spec_auto_from_type ("trunc",
+ &block.trunc_peer),
GNUNET_PQ_result_spec_variable_size ("path",
- (void **) &path,
- &path_len),
+ &path,
+ &path_size),
GNUNET_PQ_result_spec_end
};
@@ -255,26 +261,27 @@ handle_results (void *cls,
GNUNET_break (0);
return;
}
- if (0 != (path_len % sizeof(struct GNUNET_PeerIdentity)))
+ if (0 != (path_size % sizeof(struct GNUNET_DHT_PathElement)))
{
GNUNET_break (0);
- path_len = 0;
+ path_size = 0;
+ path = NULL;
}
- path_len %= sizeof(struct GNUNET_PeerIdentity);
+ block.data = data;
+ block.put_path = path;
+ block.put_path_length
+ = path_size / sizeof (struct GNUNET_DHT_PathElement);
+ block.type = (enum GNUNET_BLOCK_Type) type32;
+ block.ro = (enum GNUNET_DHT_RouteOption) bro32;
+ block.key = *hrc->key;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Found result of size %u bytes and type %u in database\n",
- (unsigned int) data_size,
- (unsigned int) type);
- if ((NULL != hrc->iter) &&
- (GNUNET_SYSERR ==
- hrc->iter (hrc->iter_cls,
- hrc->key,
- data_size,
- data,
- (enum GNUNET_BLOCK_Type) type,
- expiration_time,
- path_len,
- path)))
+ (unsigned int) block.data_size,
+ (unsigned int) block.type);
+ if ( (NULL != hrc->iter) &&
+ (GNUNET_SYSERR ==
+ hrc->iter (hrc->iter_cls,
+ &block)) )
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Ending iteration (client error)\n");
@@ -343,7 +350,7 @@ postgres_plugin_get (void *cls,
* @param cls closure (our `struct Plugin`)
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
-static int
+static enum GNUNET_GenericReturnValue
postgres_plugin_del (void *cls)
{
struct Plugin *plugin = cls;
@@ -410,96 +417,6 @@ postgres_plugin_del (void *cls)
/**
- * Obtain a random key-value pair from the datacache.
- *
- * @param cls closure (our `struct Plugin`)
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found, zero (datacache empty) or one
- */
-static unsigned int
-postgres_plugin_get_random (void *cls,
- GNUNET_DATACACHE_Iterator iter,
- void *iter_cls)
-{
- struct Plugin *plugin = cls;
- uint32_t off;
- struct GNUNET_TIME_Absolute now = { 0 };
- struct GNUNET_TIME_Absolute expiration_time;
- size_t data_size;
- void *data;
- size_t path_len;
- struct GNUNET_PeerIdentity *path;
- struct GNUNET_HashCode key;
- uint32_t type;
- enum GNUNET_DB_QueryStatus res;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_uint32 (&off),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_absolute_time ("discard_time",
- &expiration_time),
- GNUNET_PQ_result_spec_uint32 ("type",
- &type),
- GNUNET_PQ_result_spec_variable_size ("value",
- &data,
- &data_size),
- GNUNET_PQ_result_spec_variable_size ("path",
- (void **) &path,
- &path_len),
- GNUNET_PQ_result_spec_auto_from_type ("key",
- &key),
- GNUNET_PQ_result_spec_end
- };
-
- if (0 == plugin->num_items)
- return 0;
- if (NULL == iter)
- return 1;
- now = GNUNET_TIME_absolute_get ();
- off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
- plugin->num_items);
- res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh,
- "get_random",
- params,
- rs);
- if (0 > res)
- {
- GNUNET_break (0);
- return 0;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
- {
- GNUNET_break (0);
- return 0;
- }
- if (0 != (path_len % sizeof(struct GNUNET_PeerIdentity)))
- {
- GNUNET_break (0);
- path_len = 0;
- }
- path_len %= sizeof(struct GNUNET_PeerIdentity);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Found random value with key %s of size %u bytes and type %u in database\n",
- GNUNET_h2s (&key),
- (unsigned int) data_size,
- (unsigned int) type);
- (void) iter (iter_cls,
- &key,
- data_size,
- data,
- (enum GNUNET_BLOCK_Type) type,
- expiration_time,
- path_len,
- path);
- GNUNET_PQ_cleanup_result (rs);
- return 1;
-}
-
-
-/**
* Closure for #extract_result_cb.
*/
struct ExtractResultContext
@@ -536,26 +453,29 @@ extract_result_cb (void *cls,
return;
for (unsigned int i = 0; i < num_results; i++)
{
- struct GNUNET_TIME_Absolute expiration_time;
- uint32_t type;
+ uint32_t type32;
+ uint32_t bro32;
+ struct GNUNET_DATACACHE_Block block;
void *data;
- size_t data_size;
- struct GNUNET_PeerIdentity *path;
- size_t path_len;
- struct GNUNET_HashCode key;
+ void *path;
+ size_t path_size;
struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_absolute_time ("",
- &expiration_time),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+ &block.expiration_time),
GNUNET_PQ_result_spec_uint32 ("type",
- &type),
+ &type32),
+ GNUNET_PQ_result_spec_uint32 ("ro",
+ &bro32),
GNUNET_PQ_result_spec_variable_size ("value",
&data,
- &data_size),
+ &block.data_size),
+ GNUNET_PQ_result_spec_auto_from_type ("trunc",
+ &block.trunc_peer),
GNUNET_PQ_result_spec_variable_size ("path",
- (void **) &path,
- &path_len),
+ &path,
+ &path_size),
GNUNET_PQ_result_spec_auto_from_type ("key",
- &key),
+ &block.key),
GNUNET_PQ_result_spec_end
};
@@ -567,25 +487,25 @@ extract_result_cb (void *cls,
GNUNET_break (0);
return;
}
- if (0 != (path_len % sizeof(struct GNUNET_PeerIdentity)))
+ if (0 != (path_size % sizeof(struct GNUNET_DHT_PathElement)))
{
GNUNET_break (0);
- path_len = 0;
+ path_size = 0;
+ path = NULL;
}
- path_len %= sizeof(struct GNUNET_PeerIdentity);
+ block.type = (enum GNUNET_BLOCK_Type) type32;
+ block.ro = (enum GNUNET_DHT_RouteOption) bro32;
+ block.data = data;
+ block.put_path = path;
+ block.put_path_length = path_size / sizeof (struct GNUNET_DHT_PathElement);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Found result of size %u bytes and type %u in database\n",
- (unsigned int) data_size,
- (unsigned int) type);
- if (GNUNET_SYSERR ==
- erc->iter (erc->iter_cls,
- &key,
- data_size,
- data,
- (enum GNUNET_BLOCK_Type) type,
- expiration_time,
- path_len,
- path))
+ (unsigned int) block.data_size,
+ (unsigned int) block.type);
+ if ( (NULL != erc->iter) &&
+ (GNUNET_SYSERR ==
+ erc->iter (erc->iter_cls,
+ &block)) )
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Ending iteration (client error)\n");
@@ -605,6 +525,7 @@ extract_result_cb (void *cls,
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -613,16 +534,19 @@ extract_result_cb (void *cls,
static unsigned int
postgres_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
struct Plugin *plugin = cls;
uint32_t num_results32 = (uint32_t) num_results;
+ uint32_t type32 = (uint32_t) type;
struct GNUNET_TIME_Absolute now;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (key),
GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_uint32 (&type32),
GNUNET_PQ_query_param_uint32 (&num_results32),
GNUNET_PQ_query_param_end
};
@@ -681,7 +605,6 @@ libgnunet_plugin_datacache_postgres_init (void *cls)
api->get = &postgres_plugin_get;
api->put = &postgres_plugin_put;
api->del = &postgres_plugin_del;
- api->get_random = &postgres_plugin_get_random;
api->get_closest = &postgres_plugin_get_closest;
LOG (GNUNET_ERROR_TYPE_INFO,
"Postgres datacache running\n");
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index 66ff9e82c..0753d87ce 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2006, 2009, 2015 GNUnet e.V.
+ Copyright (C) 2006, 2009, 2015, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -74,9 +74,19 @@ struct Plugin
/**
* Prepared statement for #sqlite_plugin_get.
*/
+ sqlite3_stmt *get_count_any_stmt;
+
+ /**
+ * Prepared statement for #sqlite_plugin_get.
+ */
sqlite3_stmt *get_stmt;
/**
+ * Prepared statement for #sqlite_plugin_get.
+ */
+ sqlite3_stmt *get_any_stmt;
+
+ /**
* Prepared statement for #sqlite_plugin_del.
*/
sqlite3_stmt *del_select_stmt;
@@ -92,11 +102,6 @@ struct Plugin
sqlite3_stmt *del_stmt;
/**
- * Prepared statement for #sqlite_plugin_get_random.
- */
- sqlite3_stmt *get_random_stmt;
-
- /**
* Prepared statement for #sqlite_plugin_get_closest.
*/
sqlite3_stmt *get_closest_stmt;
@@ -138,9 +143,10 @@ struct Plugin
do \
{ \
emsg = NULL; \
- if (SQLITE_OK != sqlite3_exec (db, cmd, NULL, NULL, &emsg)) \
+ if (SQLITE_OK != \
+ sqlite3_exec (db, cmd, NULL, NULL, &emsg)) \
{ \
- LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, \
+ LOG (GNUNET_ERROR_TYPE_ERROR, \
_ ("`%s' failed at %s:%d with error: %s\n"), \
"sqlite3_exec", \
__FILE__, \
@@ -178,67 +184,224 @@ sq_prepare (sqlite3 *dbh,
* Store an item in the datastore.
*
* @param cls closure (our `struct Plugin`)
- * @param key key to store @a data under
* @param xor_distance how close is @a key to our PID?
- * @param size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info array of peers that have processed the request
+ * @param block data to store
* @return 0 if duplicate, -1 on error, number of bytes used otherwise
*/
static ssize_t
sqlite_plugin_put (void *cls,
- const struct GNUNET_HashCode *key,
uint32_t xor_distance,
- size_t size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute discard_time,
- unsigned int path_info_len,
- const struct GNUNET_PeerIdentity *path_info)
+ const struct GNUNET_DATACACHE_Block *block)
{
struct Plugin *plugin = cls;
- uint32_t type32 = type;
- struct GNUNET_SQ_QueryParam params[] =
- { GNUNET_SQ_query_param_uint32 (&type32),
- GNUNET_SQ_query_param_absolute_time (&discard_time),
- GNUNET_SQ_query_param_auto_from_type (key),
+ uint32_t type32 = (uint32_t) block->type;
+ uint32_t ro32 = (uint32_t) block->ro;
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_uint32 (&type32),
+ GNUNET_SQ_query_param_uint32 (&ro32),
+ GNUNET_SQ_query_param_absolute_time (&block->expiration_time),
+ GNUNET_SQ_query_param_auto_from_type (&block->key),
GNUNET_SQ_query_param_uint32 (&xor_distance),
- GNUNET_SQ_query_param_fixed_size (data, size),
- GNUNET_SQ_query_param_fixed_size (path_info,
- path_info_len
- * sizeof(struct GNUNET_PeerIdentity)),
- GNUNET_SQ_query_param_end };
+ GNUNET_SQ_query_param_fixed_size (block->data,
+ block->data_size),
+ GNUNET_SQ_query_param_fixed_size (block->put_path,
+ block->put_path_length
+ * sizeof(struct GNUNET_DHT_PathElement)),
+ GNUNET_SQ_query_param_auto_from_type (&block->trunc_peer),
+ GNUNET_SQ_query_param_end
+ };
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing PUT of %u bytes with key `%s' and expiration %s\n",
- (unsigned int) size,
- GNUNET_h2s (key),
+ (unsigned int) block->data_size,
+ GNUNET_h2s (&block->key),
GNUNET_STRINGS_relative_time_to_string (
GNUNET_TIME_absolute_get_remaining (
- discard_time),
+ block->expiration_time),
GNUNET_YES));
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->insert_stmt, params))
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->insert_stmt,
+ params))
{
LOG_SQLITE (plugin->dbh,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_ERROR_TYPE_ERROR,
"sqlite3_bind_xxx");
- GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->insert_stmt);
return -1;
}
- if (SQLITE_DONE != sqlite3_step (plugin->insert_stmt))
+ if (SQLITE_DONE !=
+ sqlite3_step (plugin->insert_stmt))
{
LOG_SQLITE (plugin->dbh,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_ERROR_TYPE_ERROR,
"sqlite3_step");
- GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->insert_stmt);
return -1;
}
plugin->num_items++;
- GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt);
- return size + OVERHEAD;
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->insert_stmt);
+ return block->data_size + OVERHEAD;
+}
+
+
+/**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param cls closure (our `struct Plugin`)
+ * @param key
+ * @param iter maybe NULL (to just count)
+ * @param iter_cls closure for @a iter
+ * @return the number of results found
+ */
+static unsigned int
+get_any (void *cls,
+ const struct GNUNET_HashCode *key,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls)
+{
+ struct Plugin *plugin = cls;
+ struct GNUNET_TIME_Absolute now;
+ unsigned int cnt;
+ uint32_t off;
+ uint32_t btype32;
+ uint32_t bro32;
+ unsigned int total;
+ struct GNUNET_DATACACHE_Block block;
+ void *path;
+ void *data;
+ size_t path_size;
+ struct GNUNET_SQ_QueryParam params_count[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
+ GNUNET_SQ_query_param_absolute_time (&now),
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_QueryParam params_select[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
+ GNUNET_SQ_query_param_absolute_time (&now),
+ GNUNET_SQ_query_param_uint32 (&off),
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_variable_size (&data,
+ &block.data_size),
+ GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
+ GNUNET_SQ_result_spec_variable_size (&path,
+ &path_size),
+ GNUNET_SQ_result_spec_auto_from_type (&block.trunc_peer),
+ GNUNET_SQ_result_spec_uint32 (&btype32),
+ GNUNET_SQ_result_spec_uint32 (&bro32),
+ GNUNET_SQ_result_spec_end
+ };
+
+ now = GNUNET_TIME_absolute_get ();
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing GET for key `%s'\n",
+ GNUNET_h2s (key));
+
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_count_any_stmt,
+ params_count))
+ {
+ LOG_SQLITE (plugin->dbh,
+ GNUNET_ERROR_TYPE_ERROR,
+ "sqlite3_bind_xxx");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_count_any_stmt);
+ return 0;
+ }
+ if (SQLITE_ROW !=
+ sqlite3_step (plugin->get_count_any_stmt))
+ {
+ LOG_SQLITE (plugin->dbh,
+ GNUNET_ERROR_TYPE_ERROR,
+ "sqlite_step");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_count_any_stmt);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "No content found when processing GET for key `%s'\n",
+ GNUNET_h2s (key));
+ return 0;
+ }
+ total = sqlite3_column_int (plugin->get_count_any_stmt,
+ 0);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_count_any_stmt);
+ if ( (0 == total) ||
+ (NULL == iter) )
+ {
+ if (0 == total)
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "No content found when processing GET for key `%s'\n",
+ GNUNET_h2s (key));
+ return total;
+ }
+
+ cnt = 0;
+ block.key = *key;
+ off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ total);
+ while (cnt < total)
+ {
+ off = (off + 1) % total;
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_any_stmt,
+ params_select))
+ {
+ LOG_SQLITE (plugin->dbh,
+ GNUNET_ERROR_TYPE_ERROR,
+ "sqlite3_bind_xxx");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_any_stmt);
+ return cnt;
+ }
+ if (SQLITE_ROW !=
+ sqlite3_step (plugin->get_any_stmt))
+ break;
+ if (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->get_any_stmt,
+ rs))
+ {
+ GNUNET_break (0);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_any_stmt);
+ break;
+ }
+ if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
+ {
+ GNUNET_break (0);
+ path_size = 0;
+ path = NULL;
+ }
+ block.data = data;
+ block.put_path = path;
+ block.put_path_length = path_size / sizeof(struct GNUNET_DHT_PathElement);
+ block.type = (enum GNUNET_BLOCK_Type) btype32;
+ block.ro = (enum GNUNET_DHT_RouteOption) bro32;
+ cnt++;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found %u-byte result when processing GET for key `%s'\n",
+ (unsigned int) block.data_size,
+ GNUNET_h2s (&block.key));
+ if (GNUNET_OK !=
+ iter (iter_cls,
+ &block))
+ {
+ GNUNET_SQ_cleanup_result (rs);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_any_stmt);
+ break;
+ }
+ GNUNET_SQ_cleanup_result (rs);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_any_stmt);
+ }
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_any_stmt);
+ return cnt;
}
@@ -254,67 +417,82 @@ sqlite_plugin_put (void *cls,
* @return the number of results found
*/
static unsigned int
-sqlite_plugin_get (void *cls,
- const struct GNUNET_HashCode *key,
- enum GNUNET_BLOCK_Type type,
- GNUNET_DATACACHE_Iterator iter,
- void *iter_cls)
+get_typed (void *cls,
+ const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls)
{
struct Plugin *plugin = cls;
uint32_t type32 = type;
struct GNUNET_TIME_Absolute now;
- struct GNUNET_TIME_Absolute exp;
- size_t size;
- void *dat;
unsigned int cnt;
uint32_t off;
+ uint32_t bro32;
unsigned int total;
- size_t psize;
- struct GNUNET_PeerIdentity *path;
- struct GNUNET_SQ_QueryParam params_count[] =
- { GNUNET_SQ_query_param_auto_from_type (key),
+ struct GNUNET_DATACACHE_Block block;
+ void *path;
+ void *data;
+ size_t path_size;
+ struct GNUNET_SQ_QueryParam params_count[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
GNUNET_SQ_query_param_uint32 (&type32),
GNUNET_SQ_query_param_absolute_time (&now),
- GNUNET_SQ_query_param_end };
- struct GNUNET_SQ_QueryParam params_select[] =
- { GNUNET_SQ_query_param_auto_from_type (key),
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_QueryParam params_select[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
GNUNET_SQ_query_param_uint32 (&type32),
GNUNET_SQ_query_param_absolute_time (&now),
GNUNET_SQ_query_param_uint32 (&off),
- GNUNET_SQ_query_param_end };
- struct GNUNET_SQ_ResultSpec rs[] =
- { GNUNET_SQ_result_spec_variable_size (&dat, &size),
- GNUNET_SQ_result_spec_absolute_time (&exp),
- GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
- GNUNET_SQ_result_spec_end };
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_variable_size (&data,
+ &block.data_size),
+ GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
+ GNUNET_SQ_result_spec_variable_size (&path,
+ &path_size),
+ GNUNET_SQ_result_spec_auto_from_type (&block.trunc_peer),
+ GNUNET_SQ_result_spec_uint32 (&bro32),
+ GNUNET_SQ_result_spec_end
+ };
now = GNUNET_TIME_absolute_get ();
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing GET for key `%s'\n",
GNUNET_h2s (key));
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_count_stmt, params_count))
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_count_stmt,
+ params_count))
{
LOG_SQLITE (plugin->dbh,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_ERROR_TYPE_ERROR,
"sqlite3_bind_xxx");
- GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_count_stmt);
return 0;
}
- if (SQLITE_ROW != sqlite3_step (plugin->get_count_stmt))
+ if (SQLITE_ROW !=
+ sqlite3_step (plugin->get_count_stmt))
{
LOG_SQLITE (plugin->dbh,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_ERROR_TYPE_ERROR,
"sqlite_step");
- GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_count_stmt);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"No content found when processing GET for key `%s'\n",
GNUNET_h2s (key));
return 0;
}
- total = sqlite3_column_int (plugin->get_count_stmt, 0);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt);
- if ((0 == total) || (NULL == iter))
+ total = sqlite3_column_int (plugin->get_count_stmt,
+ 0);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_count_stmt);
+ if ( (0 == total) ||
+ (NULL == iter) )
{
if (0 == total)
LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -324,213 +502,211 @@ sqlite_plugin_get (void *cls,
}
cnt = 0;
- off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
+ block.key = *key;
+ off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ total);
while (cnt < total)
{
off = (off + 1) % total;
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_stmt, params_select))
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_stmt,
+ params_select))
{
LOG_SQLITE (plugin->dbh,
- GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_ERROR_TYPE_ERROR,
"sqlite3_bind_xxx");
- GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_stmt);
return cnt;
}
- if (SQLITE_ROW != sqlite3_step (plugin->get_stmt))
+ if (SQLITE_ROW !=
+ sqlite3_step (plugin->get_stmt))
break;
- if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_stmt, rs))
+ if (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->get_stmt,
+ rs))
{
GNUNET_break (0);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_stmt);
break;
}
- if (0 != psize % sizeof(struct GNUNET_PeerIdentity))
+ if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
{
GNUNET_break (0);
- psize = 0;
+ path_size = 0;
path = NULL;
}
- psize /= sizeof(struct GNUNET_PeerIdentity);
+ block.data = data;
+ block.put_path = path;
+ block.put_path_length = path_size / sizeof(struct GNUNET_DHT_PathElement);
+ block.type = type;
+ block.ro = (enum GNUNET_DHT_RouteOption) bro32;
cnt++;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Found %u-byte result when processing GET for key `%s'\n",
- (unsigned int) size,
- GNUNET_h2s (key));
- if (GNUNET_OK != iter (iter_cls, key, size, dat, type, exp, psize, path))
+ (unsigned int) block.data_size,
+ GNUNET_h2s (&block.key));
+ if ( (NULL != iter) &&
+ (GNUNET_OK !=
+ iter (iter_cls,
+ &block)) )
{
GNUNET_SQ_cleanup_result (rs);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_stmt);
break;
}
GNUNET_SQ_cleanup_result (rs);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_stmt);
}
- GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_stmt);
return cnt;
}
/**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param cls closure (our `struct Plugin`)
+ * @param key
+ * @param type entries of which type are relevant?
+ * @param iter maybe NULL (to just count)
+ * @param iter_cls closure for @a iter
+ * @return the number of results found
+ */
+static unsigned int
+sqlite_plugin_get (void *cls,
+ const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls)
+{
+ if (GNUNET_BLOCK_TYPE_ANY == type)
+ return get_any (cls,
+ key,
+ iter,
+ iter_cls);
+ return get_typed (cls,
+ key,
+ type,
+ iter,
+ iter_cls);
+}
+
+
+/**
* Delete the entry with the lowest expiration value
* from the datacache right now.
*
* @param cls closure (our `struct Plugin`)
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
-static int
+static enum GNUNET_GenericReturnValue
sqlite_plugin_del (void *cls)
{
struct Plugin *plugin = cls;
uint64_t rowid;
void *data;
- size_t dsize;
+ size_t data_size;
struct GNUNET_HashCode hc;
struct GNUNET_TIME_Absolute now;
- struct GNUNET_SQ_ResultSpec rs[] =
- { GNUNET_SQ_result_spec_uint64 (&rowid),
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_uint64 (&rowid),
GNUNET_SQ_result_spec_auto_from_type (&hc),
- GNUNET_SQ_result_spec_variable_size ((void **) &data, &dsize),
- GNUNET_SQ_result_spec_end };
- struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint64 (
- &rowid),
- GNUNET_SQ_query_param_end };
- struct GNUNET_SQ_QueryParam time_params[] =
- { GNUNET_SQ_query_param_absolute_time (&now), GNUNET_SQ_query_param_end };
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing DEL\n");
+ GNUNET_SQ_result_spec_variable_size (&data,
+ &data_size),
+ GNUNET_SQ_result_spec_end
+ };
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_uint64 (&rowid),
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_QueryParam time_params[] = {
+ GNUNET_SQ_query_param_absolute_time (&now),
+ GNUNET_SQ_query_param_end
+ };
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing DEL\n");
now = GNUNET_TIME_absolute_get ();
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_expired_stmt, time_params))
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->del_expired_stmt,
+ time_params))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sqlite3_bind");
- GNUNET_SQ_reset (plugin->dbh, plugin->del_expired_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_expired_stmt);
return GNUNET_SYSERR;
}
- if ((SQLITE_ROW != sqlite3_step (plugin->del_expired_stmt)) ||
- (GNUNET_OK != GNUNET_SQ_extract_result (plugin->del_expired_stmt, rs)))
+ if ( (SQLITE_ROW !=
+ sqlite3_step (plugin->del_expired_stmt)) ||
+ (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->del_expired_stmt,
+ rs)))
{
- GNUNET_SQ_reset (plugin->dbh, plugin->del_expired_stmt);
- if (SQLITE_ROW != sqlite3_step (plugin->del_select_stmt))
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_expired_stmt);
+ if (SQLITE_ROW !=
+ sqlite3_step (plugin->del_select_stmt))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sqlite3_step");
- GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_select_stmt);
return GNUNET_SYSERR;
}
- if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->del_select_stmt, rs))
+ if (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->del_select_stmt,
+ rs))
{
- GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_select_stmt);
GNUNET_break (0);
return GNUNET_SYSERR;
}
}
GNUNET_SQ_cleanup_result (rs);
- GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt);
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_stmt, params))
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_select_stmt);
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->del_stmt,
+ params))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sqlite3_bind");
- GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_stmt);
return GNUNET_SYSERR;
}
- if (SQLITE_DONE != sqlite3_step (plugin->del_stmt))
+ if (SQLITE_DONE !=
+ sqlite3_step (plugin->del_stmt))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sqlite3_step");
- GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_stmt);
return GNUNET_SYSERR;
}
plugin->num_items--;
- plugin->env->delete_notify (plugin->env->cls, &hc, dsize + OVERHEAD);
- GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt);
+ plugin->env->delete_notify (plugin->env->cls,
+ &hc,
+ data_size + OVERHEAD);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->del_stmt);
return GNUNET_OK;
}
/**
- * Obtain a random key-value pair from the datacache.
- *
- * @param cls closure (our `struct Plugin`)
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found, zero (datacache empty) or one
- */
-static unsigned int
-sqlite_plugin_get_random (void *cls,
- GNUNET_DATACACHE_Iterator iter,
- void *iter_cls)
-{
- struct Plugin *plugin = cls;
- struct GNUNET_TIME_Absolute exp;
- size_t size;
- void *dat;
- uint32_t off = 0;
- size_t psize;
- uint32_t type;
- struct GNUNET_PeerIdentity *path;
- struct GNUNET_HashCode key;
- struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint32 (&off),
- GNUNET_SQ_query_param_end };
- struct GNUNET_SQ_ResultSpec rs[] =
- { GNUNET_SQ_result_spec_variable_size (&dat, &size),
- GNUNET_SQ_result_spec_absolute_time (&exp),
- GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
- GNUNET_SQ_result_spec_auto_from_type (&key),
- GNUNET_SQ_result_spec_uint32 (&type),
- GNUNET_SQ_result_spec_end };
-
- if (0 == plugin->num_items)
- return 0;
- if (NULL == iter)
- return 1;
- off =
- GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, plugin->num_items);
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_random_stmt, params))
- {
- return 0;
- }
- if (SQLITE_ROW != sqlite3_step (plugin->get_random_stmt))
- {
- GNUNET_break (0);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_random_stmt);
- return 0;
- }
- if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_random_stmt, rs))
- {
- GNUNET_break (0);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_random_stmt);
- return 0;
- }
- if (0 != psize % sizeof(struct GNUNET_PeerIdentity))
- {
- GNUNET_break (0);
- psize = 0;
- path = NULL;
- }
- psize /= sizeof(struct GNUNET_PeerIdentity);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Found %u-byte result with key %s when processing GET-RANDOM\n",
- (unsigned int) size,
- GNUNET_h2s (&key));
- (void) iter (iter_cls,
- &key,
- size,
- dat,
- (enum GNUNET_BLOCK_Type) type,
- exp,
- psize,
- path);
- GNUNET_SQ_cleanup_result (rs);
- GNUNET_SQ_reset (plugin->dbh, plugin->get_random_stmt);
- return 1;
-}
-
-
-/**
* Iterate over the results that are "close" to a particular key in
* the datacache. "close" is defined as numerically larger than @a
* key (when interpreted as a circular address space), with small
@@ -538,6 +714,7 @@ sqlite_plugin_get_random (void *cls,
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -546,74 +723,97 @@ sqlite_plugin_get_random (void *cls,
static unsigned int
sqlite_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
struct Plugin *plugin = cls;
+ uint32_t type32 = type;
uint32_t num_results32 = num_results;
struct GNUNET_TIME_Absolute now;
- struct GNUNET_TIME_Absolute exp;
- size_t size;
- void *dat;
+ void *data;
+ void *path;
+ size_t path_size;
unsigned int cnt;
- size_t psize;
- uint32_t type;
- struct GNUNET_HashCode hc;
- struct GNUNET_PeerIdentity *path;
- struct GNUNET_SQ_QueryParam params[] =
- { GNUNET_SQ_query_param_auto_from_type (key),
+ uint32_t bro32;
+ struct GNUNET_DATACACHE_Block block;
+ uint32_t rtype32;
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
GNUNET_SQ_query_param_absolute_time (&now),
+ GNUNET_SQ_query_param_uint32 (&type32),
GNUNET_SQ_query_param_uint32 (&num_results32),
- GNUNET_SQ_query_param_end };
- struct GNUNET_SQ_ResultSpec rs[] =
- { GNUNET_SQ_result_spec_variable_size (&dat, &size),
- GNUNET_SQ_result_spec_absolute_time (&exp),
- GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
- GNUNET_SQ_result_spec_uint32 (&type),
- GNUNET_SQ_result_spec_auto_from_type (&hc),
- GNUNET_SQ_result_spec_end };
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_variable_size (&data,
+ &block.data_size),
+ GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
+ GNUNET_SQ_result_spec_variable_size (&path,
+ &path_size),
+ GNUNET_SQ_result_spec_auto_from_type (&block.trunc_peer),
+ GNUNET_SQ_result_spec_uint32 (&rtype32),
+ GNUNET_SQ_result_spec_uint32 (&bro32),
+ GNUNET_SQ_result_spec_auto_from_type (&block.key),
+ GNUNET_SQ_result_spec_end
+ };
now = GNUNET_TIME_absolute_get ();
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing GET_CLOSEST for key `%s'\n",
GNUNET_h2s (key));
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_closest_stmt, params))
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_closest_stmt,
+ params))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sqlite3_bind_xxx");
- GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_closest_stmt);
return 0;
}
cnt = 0;
- while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt))
+ while (SQLITE_ROW ==
+ sqlite3_step (plugin->get_closest_stmt))
{
- if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_closest_stmt, rs))
+ if (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->get_closest_stmt,
+ rs))
{
GNUNET_break (0);
break;
}
- if (0 != psize % sizeof(struct GNUNET_PeerIdentity))
+ if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
{
GNUNET_break (0);
- psize = 0;
+ path_size = 0;
path = NULL;
}
- psize /= sizeof(struct GNUNET_PeerIdentity);
+ block.put_path_length
+ = path_size / sizeof(struct GNUNET_DHT_PathElement);
+ block.put_path = path;
+ block.data = data;
+ block.type = (enum GNUNET_BLOCK_Type) rtype32;
+ block.ro = (enum GNUNET_DHT_RouteOption) bro32;
cnt++;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Found %u-byte result at %s when processing GET_CLOSE\n",
- (unsigned int) size,
- GNUNET_h2s (&hc));
- if (GNUNET_OK != iter (iter_cls, &hc, size, dat, type, exp, psize, path))
+ (unsigned int) block.data_size,
+ GNUNET_h2s (&block.key));
+
+ if (GNUNET_OK !=
+ iter (iter_cls,
+ &block))
{
GNUNET_SQ_cleanup_result (rs);
break;
}
GNUNET_SQ_cleanup_result (rs);
}
- GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_closest_stmt);
return cnt;
}
@@ -635,25 +835,30 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
sqlite3 *dbh;
char *emsg;
- if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
- "datacache-sqlite",
- "IN_MEMORY"))
+ if (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
+ "datacache-sqlite",
+ "IN_MEMORY"))
{
- if (SQLITE_OK != sqlite3_open (":memory:", &dbh))
+ if (SQLITE_OK !=
+ sqlite3_open (":memory:",
+ &dbh))
return NULL;
fn_utf8 = NULL;
}
else
{
fn = GNUNET_DISK_mktemp ("gnunet-datacache");
- if (fn == NULL)
+ if (NULL == fn)
{
GNUNET_break (0);
return NULL;
}
/* fn should be UTF-8-encoded. If it isn't, it's a bug. */
fn_utf8 = GNUNET_strdup (fn);
- if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))
+ if (SQLITE_OK !=
+ sqlite3_open (fn_utf8,
+ &dbh))
{
GNUNET_free (fn);
GNUNET_free (fn_utf8);
@@ -667,22 +872,31 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
SQLITE3_EXEC (dbh, "PRAGMA journal_mode=OFF");
SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
- if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
- "datacache-sqlite",
- "IN_MEMORY"))
+ if (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
+ "datacache-sqlite",
+ "IN_MEMORY"))
SQLITE3_EXEC (dbh, "PRAGMA sqlite_temp_store=3");
SQLITE3_EXEC (dbh,
- "CREATE TABLE ds091 ("
+ "CREATE TABLE ds180 ("
" type INTEGER NOT NULL DEFAULT 0,"
+ " ro INTEGER NOT NULL DEFAULT 0,"
" expire INTEGER NOT NULL,"
" key BLOB NOT NULL DEFAULT '',"
" prox INTEGER NOT NULL,"
" value BLOB NOT NULL,"
+ " trunc BLOB NOT NULL,"
" path BLOB DEFAULT '')");
- SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds091 (key,type,expire)");
- SQLITE3_EXEC (dbh, "CREATE INDEX idx_prox_expire ON ds091 (prox,expire)");
- SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire_only ON ds091 (expire)");
+ SQLITE3_EXEC (dbh,
+ "CREATE INDEX idx_hashidx"
+ " ON ds180 (key,type,expire)");
+ SQLITE3_EXEC (dbh,
+ "CREATE INDEX idx_prox_expire"
+ " ON ds180 (prox,expire)");
+ SQLITE3_EXEC (dbh,
+ "CREATE INDEX idx_expire_only"
+ " ON ds180 (expire)");
plugin = GNUNET_new (struct Plugin);
plugin->env = env;
plugin->dbh = dbh;
@@ -690,44 +904,78 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
if ((SQLITE_OK !=
sq_prepare (plugin->dbh,
- "INSERT INTO ds091 (type, expire, key, prox, value, path) "
- "VALUES (?, ?, ?, ?, ?, ?)",
+ "INSERT INTO ds180"
+ " (type, ro, expire, key, prox, value, path, trunc)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
&plugin->insert_stmt)) ||
- (SQLITE_OK != sq_prepare (plugin->dbh,
- "SELECT count(*) FROM ds091 "
- "WHERE key=? AND type=? AND expire >= ?",
- &plugin->get_count_stmt)) ||
(SQLITE_OK !=
sq_prepare (plugin->dbh,
- "SELECT value,expire,path FROM ds091"
- " WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?",
+ "SELECT COUNT(*) FROM ds180 "
+ "WHERE key=?"
+ " AND type=?"
+ " AND expire >= ?",
+ &plugin->get_count_stmt)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT COUNT(*) FROM ds180 "
+ "WHERE key=? AND expire >= ?",
+ &plugin->get_count_any_stmt)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT value,expire,path,trunc,ro"
+ " FROM ds180"
+ " WHERE key=?"
+ " AND type=?"
+ " AND expire >= ?"
+ " LIMIT 1 OFFSET ?",
&plugin->get_stmt)) ||
- (SQLITE_OK != sq_prepare (plugin->dbh,
- "SELECT _ROWID_,key,value FROM ds091"
- " WHERE expire < ?"
- " ORDER BY expire ASC LIMIT 1",
- &plugin->del_expired_stmt)) ||
- (SQLITE_OK != sq_prepare (plugin->dbh,
- "SELECT _ROWID_,key,value FROM ds091"
- " ORDER BY prox ASC, expire ASC LIMIT 1",
- &plugin->del_select_stmt)) ||
- (SQLITE_OK != sq_prepare (plugin->dbh,
- "DELETE FROM ds091 WHERE _ROWID_=?",
- &plugin->del_stmt)) ||
- (SQLITE_OK != sq_prepare (plugin->dbh,
- "SELECT value,expire,path,key,type FROM ds091 "
- "ORDER BY key LIMIT 1 OFFSET ?",
- &plugin->get_random_stmt)) ||
(SQLITE_OK !=
sq_prepare (plugin->dbh,
- "SELECT value,expire,path,type,key FROM ds091 "
- "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?",
+ "SELECT value,expire,path,trunc,type,ro"
+ " FROM ds180"
+ " WHERE key=?"
+ " AND expire >= ?"
+ " LIMIT 1 OFFSET ?",
+ &plugin->get_any_stmt)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT _ROWID_,key,value FROM ds180"
+ " WHERE expire < ?1"
+ " ORDER BY expire ASC LIMIT 1",
+ &plugin->del_expired_stmt)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT _ROWID_,key,value FROM ds180"
+ " ORDER BY prox ASC, expire ASC LIMIT 1",
+ &plugin->del_select_stmt)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "DELETE FROM ds180 WHERE _ROWID_=?",
+ &plugin->del_stmt)) ||
+ (SQLITE_OK !=
+ sq_prepare (plugin->dbh,
+ "SELECT * FROM ("
+ " SELECT value,expire,path,trunc,type,ro,key"
+ " FROM ds180 "
+ " WHERE key>=?1 "
+ " AND expire >= ?2"
+ " AND ( (type=?3) or (0 == ?3) )"
+ " ORDER BY KEY ASC LIMIT ?4)"
+ "UNION "
+ "SELECT * FROM ("
+ " SELECT value,expire,path,trunc,type,ro,key"
+ " FROM ds180 "
+ " WHERE key<=?1 "
+ " AND expire >= ?2"
+ " AND ( (type=?3) or (0 == ?3) )"
+ " ORDER BY KEY DESC LIMIT ?4)",
&plugin->get_closest_stmt)))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sq_prepare");
- GNUNET_break (SQLITE_OK == sqlite3_close (plugin->dbh));
+ GNUNET_break (SQLITE_OK ==
+ sqlite3_close (plugin->dbh));
GNUNET_free (plugin);
return NULL;
}
@@ -737,9 +985,9 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
api->get = &sqlite_plugin_get;
api->put = &sqlite_plugin_put;
api->del = &sqlite_plugin_del;
- api->get_random = &sqlite_plugin_get_random;
api->get_closest = &sqlite_plugin_get_closest;
- LOG (GNUNET_ERROR_TYPE_INFO, "Sqlite datacache running\n");
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ "Sqlite datacache running\n");
return api;
}
@@ -762,17 +1010,21 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
#endif
#if ! WINDOWS || defined(__CYGWIN__)
- if ((NULL != plugin->fn) && (0 != unlink (plugin->fn)))
- LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn);
+ if ( (NULL != plugin->fn) &&
+ (0 != unlink (plugin->fn)) )
+ LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
+ "unlink",
+ plugin->fn);
GNUNET_free (plugin->fn);
#endif
sqlite3_finalize (plugin->insert_stmt);
sqlite3_finalize (plugin->get_count_stmt);
+ sqlite3_finalize (plugin->get_count_any_stmt);
sqlite3_finalize (plugin->get_stmt);
+ sqlite3_finalize (plugin->get_any_stmt);
sqlite3_finalize (plugin->del_select_stmt);
sqlite3_finalize (plugin->del_expired_stmt);
sqlite3_finalize (plugin->del_stmt);
- sqlite3_finalize (plugin->get_random_stmt);
sqlite3_finalize (plugin->get_closest_stmt);
result = sqlite3_close (plugin->dbh);
#if SQLITE_VERSION_NUMBER >= 3007000
@@ -781,7 +1033,8 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
LOG (GNUNET_ERROR_TYPE_WARNING,
_ (
"Tried to close sqlite without finalizing all prepared statements.\n"));
- stmt = sqlite3_next_stmt (plugin->dbh, NULL);
+ stmt = sqlite3_next_stmt (plugin->dbh,
+ NULL);
while (NULL != stmt)
{
result = sqlite3_finalize (stmt);
@@ -790,13 +1043,16 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
"Failed to close statement %p: %d\n",
stmt,
result);
- stmt = sqlite3_next_stmt (plugin->dbh, NULL);
+ stmt = sqlite3_next_stmt (plugin->dbh,
+ NULL);
}
result = sqlite3_close (plugin->dbh);
}
#endif
if (SQLITE_OK != result)
- LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
+ LOG_SQLITE (plugin->dbh,
+ GNUNET_ERROR_TYPE_ERROR,
+ "sqlite3_close");
GNUNET_free (plugin);
GNUNET_free (api);
diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c
index 329bfd9a4..1bd712d39 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2006, 2009, 2015 GNUnet e.V.
+ Copyright (C) 2006, 2009, 2015, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -44,26 +44,14 @@ struct Plugin
* Store an item in the datastore.
*
* @param cls closure (our `struct Plugin`)
- * @param key key to store @a data under
* @param xor_distance distance of @a key to our PID
- * @param size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block data to store
* @return 0 if duplicate, -1 on error, number of bytes used otherwise
*/
static ssize_t
template_plugin_put (void *cls,
- const struct GNUNET_HashCode *key,
uint32_t xor_distance,
- size_t size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute discard_time,
- unsigned int path_info_len,
- const struct GNUNET_PeerIdentity *path_info)
+ const struct GNUNET_DATACACHE_Block *block)
{
GNUNET_break (0);
return -1;
@@ -100,7 +88,7 @@ template_plugin_get (void *cls,
* @param cls closure (our `struct Plugin`)
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
-static int
+static enum GNUNET_GenericReturnValue
template_plugin_del (void *cls)
{
GNUNET_break (0);
@@ -109,24 +97,6 @@ template_plugin_del (void *cls)
/**
- * Return a random value from the datastore.
- *
- * @param cls closure (internal context for the plugin)
- * @param iter maybe NULL (to just count)
- * @param iter_cls closure for @a iter
- * @return the number of results found (zero or one)
- */
-static unsigned int
-template_plugin_get_random (void *cls,
- GNUNET_DATACACHE_Iterator iter,
- void *iter_cls)
-{
- GNUNET_break (0);
- return 0;
-}
-
-
-/**
* Iterate over the results that are "close" to a particular key in
* the datacache. "close" is defined as numerically larger than @a
* key (when interpreted as a circular address space), with small
@@ -134,6 +104,7 @@ template_plugin_get_random (void *cls,
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -142,6 +113,7 @@ template_plugin_get_random (void *cls,
static unsigned int
template_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
@@ -171,7 +143,6 @@ libgnunet_plugin_datacache_template_init (void *cls)
api->get = &template_plugin_get;
api->put = &template_plugin_put;
api->del = &template_plugin_del;
- api->get_random = &template_plugin_get_random;
api->get_closest = &template_plugin_get_closest;
GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
"template",
diff --git a/src/datacache/test_datacache.c b/src/datacache/test_datacache.c
index 6f6e4eec1..fd5a5f54c 100644
--- a/src/datacache/test_datacache.c
+++ b/src/datacache/test_datacache.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2006, 2009, 2010 GNUnet e.V.
+ Copyright (C) 2006, 2009, 2010, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -39,26 +39,18 @@ static int ok;
static const char *plugin_name;
-static int
+static enum GNUNET_GenericReturnValue
checkIt (void *cls,
- const struct GNUNET_HashCode *key,
- size_t size, const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute exp,
- unsigned int path_len,
- const struct GNUNET_PeerIdentity *path)
+ const struct GNUNET_DATACACHE_Block *block)
{
- (void) key;
- (void) type;
- (void) exp;
- (void) path_len;
- (void) path;
- if (size != sizeof(struct GNUNET_HashCode))
+ if (block->data_size != sizeof(struct GNUNET_HashCode))
{
GNUNET_break (0);
ok = 2;
}
- if (0 != memcmp (data, cls, size))
+ if (0 != memcmp (block->data,
+ cls,
+ block->data_size))
{
GNUNET_break (0);
ok = 3;
@@ -74,9 +66,9 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_DATACACHE_Handle *h;
+ struct GNUNET_DATACACHE_Block block;
struct GNUNET_HashCode k;
struct GNUNET_HashCode n;
- struct GNUNET_TIME_Absolute exp;
(void) cls;
(void) args;
@@ -84,7 +76,7 @@ run (void *cls,
ok = 0;
h = GNUNET_DATACACHE_create (cfg,
"testcache");
- if (h == NULL)
+ if (NULL == h)
{
fprintf (stderr,
"%s",
@@ -92,19 +84,31 @@ run (void *cls,
ok = 77; /* mark test as skipped */
return;
}
- exp = GNUNET_TIME_absolute_get ();
- exp.abs_value_us += 5 * 60 * 1000 * 1000LL;
- memset (&k, 0, sizeof(struct GNUNET_HashCode));
+ block.expiration_time = GNUNET_TIME_absolute_get ();
+ block.expiration_time.abs_value_us += 5 * 60 * 1000 * 1000LL;
+ memset (&k,
+ 0,
+ sizeof(struct GNUNET_HashCode));
for (unsigned int i = 0; i < 100; i++)
{
- GNUNET_CRYPTO_hash (&k, sizeof(struct GNUNET_HashCode), &n);
+ GNUNET_CRYPTO_hash (&k,
+ sizeof(struct GNUNET_HashCode),
+ &n);
+ block.key = k;
+ block.data = &n;
+ block.data_size = sizeof (n);
+ memset (&block.trunc_peer,
+ 43,
+ sizeof (block.trunc_peer));
+ block.ro = 42;
+ block.type = (enum GNUNET_BLOCK_Type) (1 + i % 16);
+ block.put_path = NULL;
+ block.put_path_length = 0;
+ block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
ASSERT (GNUNET_OK ==
GNUNET_DATACACHE_put (h,
- &k,
- GNUNET_YES,
- sizeof(struct GNUNET_HashCode),
- (const char *) &n, 1 + i % 16, exp,
- 0, NULL));
+ 42,
+ &block));
k = n;
}
memset (&k,
@@ -117,7 +121,7 @@ run (void *cls,
&n);
ASSERT (1 == GNUNET_DATACACHE_get (h,
&k,
- 1 + i % 16,
+ (enum GNUNET_BLOCK_Type) (1 + i % 16),
&checkIt,
&n));
k = n;
@@ -129,16 +133,22 @@ run (void *cls,
GNUNET_CRYPTO_hash (&k,
sizeof(struct GNUNET_HashCode),
&n);
+ block.key = k;
+ block.data = &n;
+ block.data_size = sizeof (n);
+ block.ro = 42;
+ memset (&block.trunc_peer,
+ 44,
+ sizeof (block.trunc_peer));
+ block.type = (enum GNUNET_BLOCK_Type) 792;
+ block.put_path = NULL;
+ block.put_path_length = 0;
+ block.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS;
+ block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
ASSERT (GNUNET_OK ==
GNUNET_DATACACHE_put (h,
- &k,
- GNUNET_YES,
- sizeof(struct GNUNET_HashCode),
- (const char *) &n,
- 792,
- GNUNET_TIME_UNIT_FOREVER_ABS,
- 0,
- NULL));
+ 42,
+ &block));
ASSERT (0 != GNUNET_DATACACHE_get (h,
&k,
792,
diff --git a/src/datacache/test_datacache_data_postgres.conf b/src/datacache/test_datacache_data_postgres.conf
index 47c954b55..92313157c 100644
--- a/src/datacache/test_datacache_data_postgres.conf
+++ b/src/datacache/test_datacache_data_postgres.conf
@@ -4,6 +4,4 @@ QUOTA = 1 MB
DATABASE = postgres
[datacache-postgres]
-CONFIG = connect_timeout=10; dbname=gnunetcheck
-
-
+CONFIG = postgres:///gnunetcheck
diff --git a/src/datacache/test_datacache_quota.c b/src/datacache/test_datacache_quota.c
index 92807fbe2..994147a64 100644
--- a/src/datacache/test_datacache_quota.c
+++ b/src/datacache/test_datacache_quota.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2006, 2009, 2010 GNUnet e.V.
+ Copyright (C) 2006, 2009, 2010, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -53,8 +53,8 @@ run (void *cls,
struct GNUNET_DATACACHE_Handle *h;
struct GNUNET_HashCode k;
struct GNUNET_HashCode n;
+ struct GNUNET_DATACACHE_Block block;
char buf[3200];
- struct GNUNET_TIME_Absolute exp;
(void) cls;
(void) args;
@@ -70,9 +70,14 @@ run (void *cls,
"Failed to initialize datacache. Database likely not setup, skipping test.\n");
return;
}
- exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS);
- memset (buf, 1, sizeof(buf));
- memset (&k, 0, sizeof(struct GNUNET_HashCode));
+ block.expiration_time = GNUNET_TIME_relative_to_absolute (
+ GNUNET_TIME_UNIT_HOURS);
+ memset (buf,
+ 1,
+ sizeof(buf));
+ memset (&k,
+ 0,
+ sizeof(struct GNUNET_HashCode));
for (unsigned int i = 0; i < 10; i++)
{
fprintf (stderr,
@@ -83,35 +88,59 @@ run (void *cls,
&n);
for (unsigned int j = i; j < sizeof(buf); j += 10)
{
- exp.abs_value_us++;
buf[j] = i;
+ block.key = k;
+ block.data = buf;
+ block.data_size = j;
+ memset (&block.trunc_peer,
+ 43,
+ sizeof (block.trunc_peer));
+ block.ro = 42;
+ block.type = (enum GNUNET_BLOCK_Type) (1 + i);
+ block.put_path = NULL;
+ block.put_path_length = 0;
+ block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
+ block.expiration_time.abs_value_us++;
ASSERT (GNUNET_OK ==
GNUNET_DATACACHE_put (h,
- &k,
- GNUNET_YES,
- j,
- buf,
- 1 + i,
- exp,
- 0,
- NULL));
- ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
+ 42,
+ &block));
+ ASSERT (0 < GNUNET_DATACACHE_get (h,
+ &k,
+ 1 + i,
+ NULL,
+ NULL));
}
k = n;
}
fprintf (stderr, "%s", "\n");
- memset (&k, 0, sizeof(struct GNUNET_HashCode));
+ memset (&k,
+ 0,
+ sizeof(struct GNUNET_HashCode));
for (unsigned int i = 0; i < 10; i++)
{
fprintf (stderr, "%s", ".");
- GNUNET_CRYPTO_hash (&k, sizeof(struct GNUNET_HashCode), &n);
+ GNUNET_CRYPTO_hash (&k,
+ sizeof(struct GNUNET_HashCode),
+ &n);
if (i < 2)
- ASSERT (0 == GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
+ ASSERT (0 ==
+ GNUNET_DATACACHE_get (h,
+ &k,
+ 1 + i,
+ NULL,
+ NULL));
if (i == 9)
- ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
+ ASSERT (0 < GNUNET_DATACACHE_get (h,
+ &k,
+ 1 + i,
+ NULL,
+ NULL));
k = n;
}
- fprintf (stderr, "%s", "\n");
+ fprintf (stderr,
+ "%s",
+ "\n");
GNUNET_DATACACHE_destroy (h);
return;
FAILURE:
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)
* message happens, the insertion request could be blocked
* by less-important content from migration because it is
* larger than 1/8th of the overall available space, and
- * we only reserve 1/8th for "fresh" insertions */GNUNET_log (
+ * we only reserve 1/8th for "fresh" insertions */
+ GNUNET_log (
GNUNET_ERROR_TYPE_WARNING,
_ (
"The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"),
diff --git a/src/dht/.gitignore b/src/dht/.gitignore
index 25b1daf28..bd8af1217 100644
--- a/src/dht/.gitignore
+++ b/src/dht/.gitignore
@@ -10,3 +10,4 @@ test_dht_monitor
test_dht_multipeer
test_dht_tools.py
test_dht_twopeer
+gnunet-dht-hello
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 69e34000c..124f95a77 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -26,7 +26,7 @@ libgnunetdht_la_LIBADD = \
$(LTLIBINTL)
libgnunetdht_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) \
- -version-info 3:0:0
+ -version-info 4:0:0
plugin_LTLIBRARIES = \
@@ -50,7 +50,8 @@ libexec_PROGRAMS = \
bin_PROGRAMS = \
gnunet-dht-monitor \
gnunet-dht-get \
- gnunet-dht-put
+ gnunet-dht-put \
+ gnunet-dht-hello
noinst_PROGRAMS = \
gnunet-dht-profiler
@@ -58,11 +59,10 @@ noinst_PROGRAMS = \
gnunet_service_dht_SOURCES = \
gnunet-service-dht.c gnunet-service-dht.h \
gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \
- gnunet-service-dht_hello.c gnunet-service-dht_hello.h \
- gnunet-service-dht_nse.c gnunet-service-dht_nse.h \
gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \
gnunet-service-dht_routing.c gnunet-service-dht_routing.h
gnunet_service_dht_LDADD = \
+ libgnunetdht.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/core/libgnunetcore.la \
$(top_builddir)/src/nse/libgnunetnse.la \
@@ -71,6 +71,7 @@ gnunet_service_dht_LDADD = \
$(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
$(top_builddir)/src/hello/libgnunethello.la \
$(top_builddir)/src/block/libgnunetblock.la \
+ $(top_builddir)/src/block/libgnunetblockgroup.la \
$(top_builddir)/src/datacache/libgnunetdatacache.la \
$(top_builddir)/src/util/libgnunetutil.la \
-lm
@@ -81,16 +82,22 @@ gnunet_dht_get_SOURCES = \
gnunet-dht-get.c
gnunet_dht_get_LDADD = \
libgnunetdht.la \
- $(top_builddir)/src/core/libgnunetcore.la \
$(top_builddir)/src/util/libgnunetutil.la
gnunet_dht_get_LDFLAGS = \
$(GN_LIBINTL)
+gnunet_dht_hello_SOURCES = \
+ gnunet-dht-hello.c
+gnunet_dht_hello_LDADD = \
+ libgnunetdht.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+gnunet_dht_hello_LDFLAGS = \
+ $(GN_LIBINTL)
+
gnunet_dht_put_SOURCES = \
gnunet-dht-put.c
gnunet_dht_put_LDADD = \
libgnunetdht.la \
- $(top_builddir)/src/core/libgnunetcore.la \
$(top_builddir)/src/util/libgnunetutil.la
gnunet_dht_put_LDFLAGS = \
$(GN_LIBINTL)
@@ -99,7 +106,6 @@ gnunet_dht_monitor_SOURCES = \
gnunet-dht-monitor.c
gnunet_dht_monitor_LDADD = \
libgnunetdht.la \
- $(top_builddir)/src/core/libgnunetcore.la \
$(top_builddir)/src/util/libgnunetutil.la
gnunet_dht_monitor_LDFLAGS = \
$(GN_LIBINTL)
@@ -198,7 +204,6 @@ test_dht_monitor_LDADD = \
libgnunetdht.la
EXTRA_DIST = \
- $(check_SCRIPTS) \
gnunet-service-dht_clients.c \
test_dht_api_data.conf \
test_dht_api_peer1.conf \
@@ -208,7 +213,10 @@ EXTRA_DIST = \
test_dht_line.conf \
test_dht_tools.conf \
test_dht_tools.py.in \
- test_dht_multipeer_topology.dat
+ test_dht_multipeer_topology.dat \
+ dhtu_testbed_connect.sh \
+ dhtu_testbed_deploy.conf \
+ dhtu_testbed_deploy.sh
if HAVE_PYTHON
check_SCRIPTS = \
diff --git a/src/dht/dht.h b/src/dht/dht.h
index 86f1b9b49..6a137defe 100644
--- a/src/dht/dht.h
+++ b/src/dht/dht.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2001, 2002, 2003, 2004, 2009, 2011 GNUnet e.V.
+ Copyright (C) 2001, 2002, 2003, 2004, 2009, 2011, 2021 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -153,6 +153,16 @@ struct GNUNET_DHT_ClientResultMessage
uint32_t type GNUNET_PACKED;
/**
+ * Reserved, always 0.
+ */
+ uint32_t reserved GNUNET_PACKED;
+
+ /**
+ * Message options, actually an 'enum GNUNET_DHT_RouteOption' value.
+ */
+ uint32_t options GNUNET_PACKED;
+
+ /**
* Number of peers recorded in the outgoing path from source to the
* storgage location of this message.
*/
@@ -179,7 +189,7 @@ struct GNUNET_DHT_ClientResultMessage
*/
struct GNUNET_HashCode key GNUNET_PACKED;
- /* put path, get path and actual data are copied to end of this dealy do */
+ /* trunc_peer, put path, get path and actual data are copied to end of this dealy do */
};
@@ -348,10 +358,9 @@ struct GNUNET_DHT_MonitorGetMessage
uint32_t desired_replication_level GNUNET_PACKED;
/**
- * Number of peers recorded in the outgoing path from source to the
- * storage location of this message.
+ * Always zero.
*/
- uint32_t get_path_length GNUNET_PACKED;
+ uint32_t reserved GNUNET_PACKED;
/**
* The key to store the value under.
@@ -377,6 +386,16 @@ struct GNUNET_DHT_MonitorGetRespMessage
uint32_t type GNUNET_PACKED;
/**
+ * Reserved, always 0.
+ */
+ uint32_t reserved GNUNET_PACKED;
+
+ /**
+ * Message options, actually an 'enum GNUNET_DHT_RouteOption' value.
+ */
+ uint32_t options GNUNET_PACKED;
+
+ /**
* Length of the PUT path that follows (if tracked).
*/
uint32_t put_path_length GNUNET_PACKED;
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 96399cb5a..5fa8f759f 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009, 2010, 2011, 2012, 2016, 2018 GNUnet e.V.
+ Copyright (C) 2009-2012, 2016, 2018, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -28,6 +28,7 @@
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_constants.h"
+#include "gnunet_signatures.h"
#include "gnunet_arm_service.h"
#include "gnunet_hello_lib.h"
#include "gnunet_protocols.h"
@@ -196,6 +197,40 @@ struct GNUNET_DHT_MonitorHandle
/**
+ * Handle to get a HELLO URL from the DHT for manual bootstrapping.
+ */
+struct GNUNET_DHT_HelloGetHandle
+{
+
+ /**
+ * DLL.
+ */
+ struct GNUNET_DHT_HelloGetHandle *next;
+
+ /**
+ * DLL.
+ */
+ struct GNUNET_DHT_HelloGetHandle *prev;
+
+ /**
+ * Function to call with the result.
+ */
+ GNUNET_DHT_HelloGetCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Connection to the DHT service.
+ */
+ struct GNUNET_DHT_Handle *dht_handle;
+
+};
+
+
+/**
* Connection to the DHT service.
*/
struct GNUNET_DHT_Handle
@@ -231,6 +266,16 @@ struct GNUNET_DHT_Handle
struct GNUNET_DHT_PutHandle *put_tail;
/**
+ * DLL.
+ */
+ struct GNUNET_DHT_HelloGetHandle *hgh_head;
+
+ /**
+ * DLL.
+ */
+ struct GNUNET_DHT_HelloGetHandle *hgh_tail;
+
+ /**
* Hash map containing the current outstanding unique GET requests
* (values are of type `struct GNUNET_DHT_GetHandle`).
*/
@@ -260,7 +305,7 @@ struct GNUNET_DHT_Handle
* @param h DHT handle to reconnect
* @return #GNUNET_YES on success, #GNUNET_NO on failure.
*/
-static int
+static enum GNUNET_GenericReturnValue
try_connect (struct GNUNET_DHT_Handle *h);
@@ -344,7 +389,7 @@ send_get_known_results (struct GNUNET_DHT_GetHandle *gh,
* @param value the `struct GNUNET_DHT_GetHandle *`
* @return #GNUNET_YES (always)
*/
-static int
+static enum GNUNET_GenericReturnValue
add_get_request_to_pending (void *cls,
const struct GNUNET_HashCode *key,
void *value)
@@ -481,31 +526,6 @@ mq_error_handler (void *cls,
/**
- * Verify integrity of a get monitor message from the service.
- *
- * @param cls The DHT handle.
- * @param msg Monitor get message from the service.
- * @return #GNUNET_OK if everything went fine,
- * #GNUNET_SYSERR if the message is malformed.
- */
-static int
-check_monitor_get (void *cls,
- const struct GNUNET_DHT_MonitorGetMessage *msg)
-{
- uint32_t plen = ntohl (msg->get_path_length);
- uint16_t msize = ntohs (msg->header.size) - sizeof(*msg);
-
- if ((plen > UINT16_MAX) ||
- (plen * sizeof(struct GNUNET_PeerIdentity) != msize))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
* Process a get monitor message from the service.
*
* @param cls The DHT handle.
@@ -516,26 +536,28 @@ handle_monitor_get (void *cls,
const struct GNUNET_DHT_MonitorGetMessage *msg)
{
struct GNUNET_DHT_Handle *handle = cls;
- struct GNUNET_DHT_MonitorHandle *mh;
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (msg->options);
- for (mh = handle->monitor_head; NULL != mh; mh = mh->next)
+ for (struct GNUNET_DHT_MonitorHandle *mh = handle->monitor_head;
+ NULL != mh;
+ mh = mh->next)
{
if (NULL == mh->get_cb)
continue;
- if (((GNUNET_BLOCK_TYPE_ANY == mh->type) ||
- (mh->type == ntohl (msg->type))) &&
- ((NULL == mh->key) ||
- (0 == memcmp (mh->key,
- &msg->key,
- sizeof(struct GNUNET_HashCode)))))
- mh->get_cb (mh->cb_cls,
- ntohl (msg->options),
- (enum GNUNET_BLOCK_Type) ntohl (msg->type),
- ntohl (msg->hop_count),
- ntohl (msg->desired_replication_level),
- ntohl (msg->get_path_length),
- (struct GNUNET_PeerIdentity *) &msg[1],
- &msg->key);
+ if ( (GNUNET_BLOCK_TYPE_ANY != mh->type) &&
+ (mh->type != ntohl (msg->type)))
+ continue;
+ if ( (NULL != mh->key) &&
+ (0 != GNUNET_memcmp (mh->key,
+ &msg->key)) )
+ continue;
+ mh->get_cb (mh->cb_cls,
+ ro,
+ (enum GNUNET_BLOCK_Type) ntohl (msg->type),
+ ntohl (msg->hop_count),
+ ntohl (msg->desired_replication_level),
+ &msg->key);
}
}
@@ -548,16 +570,28 @@ handle_monitor_get (void *cls,
* @return #GNUNET_OK if everything went fine,
* #GNUNET_SYSERR if the message is malformed.
*/
-static int
+static enum GNUNET_GenericReturnValue
check_monitor_get_resp (void *cls,
const struct GNUNET_DHT_MonitorGetRespMessage *msg)
{
size_t msize = ntohs (msg->header.size) - sizeof(*msg);
uint32_t getl = ntohl (msg->get_path_length);
uint32_t putl = ntohl (msg->put_path_length);
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (msg->options);
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ if (truncated)
+ {
+ if (msize < sizeof (struct GNUNET_PeerIdentity))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ msize -= sizeof (struct GNUNET_PeerIdentity);
+ }
if ((getl + putl < getl) ||
- ((msize / sizeof(struct GNUNET_PeerIdentity)) < getl + putl))
+ ((msize / sizeof(struct GNUNET_DHT_PathElement)) < getl + putl))
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -578,33 +612,47 @@ handle_monitor_get_resp (void *cls,
{
struct GNUNET_DHT_Handle *handle = cls;
size_t msize = ntohs (msg->header.size) - sizeof(*msg);
- const struct GNUNET_PeerIdentity *path;
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (msg->options);
uint32_t getl = ntohl (msg->get_path_length);
uint32_t putl = ntohl (msg->put_path_length);
- struct GNUNET_DHT_MonitorHandle *mh;
-
- path = (const struct GNUNET_PeerIdentity *) &msg[1];
- for (mh = handle->monitor_head; NULL != mh; mh = mh->next)
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ const struct GNUNET_PeerIdentity *trunc_peer
+ = truncated
+ ? (const struct GNUNET_PeerIdentity *) &msg[1]
+ : NULL;
+ const struct GNUNET_DHT_PathElement *path
+ = truncated
+ ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
+ : (const struct GNUNET_DHT_PathElement *) &msg[1];
+
+ if (truncated)
+ msize -= sizeof (struct GNUNET_PeerIdentity);
+ msize -= sizeof(struct GNUNET_DHT_PathElement) * (putl + getl);
+ for (struct GNUNET_DHT_MonitorHandle *mh = handle->monitor_head;
+ NULL != mh;
+ mh = mh->next)
{
if (NULL == mh->get_resp_cb)
continue;
- if (((GNUNET_BLOCK_TYPE_ANY == mh->type) ||
- (mh->type == ntohl (msg->type))) &&
- ((NULL == mh->key) ||
- (0 == memcmp (mh->key,
- &msg->key,
- sizeof(struct GNUNET_HashCode)))))
- mh->get_resp_cb (mh->cb_cls,
- (enum GNUNET_BLOCK_Type) ntohl (msg->type),
- path,
- getl,
- &path[getl],
- putl,
- GNUNET_TIME_absolute_ntoh (msg->expiration_time),
- &msg->key,
- (const void *) &path[getl + putl],
- msize - sizeof(struct GNUNET_PeerIdentity) * (putl
- + getl));
+ if ( (GNUNET_BLOCK_TYPE_ANY != mh->type) &&
+ (mh->type != ntohl (msg->type)) )
+ continue;
+ if ( (NULL != mh->key) &&
+ (0 != GNUNET_memcmp (mh->key,
+ &msg->key)) )
+ continue;
+ mh->get_resp_cb (mh->cb_cls,
+ (enum GNUNET_BLOCK_Type) ntohl (msg->type),
+ trunc_peer,
+ &path[putl],
+ getl,
+ path,
+ putl,
+ GNUNET_TIME_absolute_ntoh (msg->expiration_time),
+ &msg->key,
+ (const void *) &path[getl + putl],
+ msize);
}
}
@@ -617,16 +665,26 @@ handle_monitor_get_resp (void *cls,
* @return #GNUNET_OK if everything went fine,
* #GNUNET_SYSERR if the message is malformed.
*/
-static int
+static enum GNUNET_GenericReturnValue
check_monitor_put (void *cls,
const struct GNUNET_DHT_MonitorPutMessage *msg)
{
- size_t msize;
- uint32_t putl;
+ size_t msize = ntohs (msg->header.size) - sizeof(*msg);
+ uint32_t putl = ntohl (msg->put_path_length);
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (msg->options);
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
- msize = ntohs (msg->header.size) - sizeof(*msg);
- putl = ntohl (msg->put_path_length);
- if ((msize / sizeof(struct GNUNET_PeerIdentity)) < putl)
+ if (truncated)
+ {
+ if (msize < sizeof (struct GNUNET_PeerIdentity))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ msize -= sizeof (struct GNUNET_PeerIdentity);
+ }
+ if ((msize / sizeof(struct GNUNET_DHT_PathElement)) < putl)
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -648,31 +706,46 @@ handle_monitor_put (void *cls,
struct GNUNET_DHT_Handle *handle = cls;
size_t msize = ntohs (msg->header.size) - sizeof(*msg);
uint32_t putl = ntohl (msg->put_path_length);
- const struct GNUNET_PeerIdentity *path;
- struct GNUNET_DHT_MonitorHandle *mh;
-
- path = (const struct GNUNET_PeerIdentity *) &msg[1];
- for (mh = handle->monitor_head; NULL != mh; mh = mh->next)
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (msg->options);
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ const struct GNUNET_PeerIdentity *trunc_peer
+ = truncated
+ ? (const struct GNUNET_PeerIdentity *) &msg[1]
+ : NULL;
+ const struct GNUNET_DHT_PathElement *path
+ = truncated
+ ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
+ : (const struct GNUNET_DHT_PathElement *) &msg[1];
+
+ if (truncated)
+ msize -= sizeof (struct GNUNET_PeerIdentity);
+ msize -= sizeof(struct GNUNET_DHT_PathElement) * putl;
+ for (struct GNUNET_DHT_MonitorHandle *mh = handle->monitor_head;
+ NULL != mh;
+ mh = mh->next)
{
if (NULL == mh->put_cb)
continue;
- if (((GNUNET_BLOCK_TYPE_ANY == mh->type) ||
- (mh->type == ntohl (msg->type))) &&
- ((NULL == mh->key) ||
- (0 == memcmp (mh->key,
- &msg->key,
- sizeof(struct GNUNET_HashCode)))))
- mh->put_cb (mh->cb_cls,
- ntohl (msg->options),
- (enum GNUNET_BLOCK_Type) ntohl (msg->type),
- ntohl (msg->hop_count),
- ntohl (msg->desired_replication_level),
- putl,
- path,
- GNUNET_TIME_absolute_ntoh (msg->expiration_time),
- &msg->key,
- (const void *) &path[putl],
- msize - sizeof(struct GNUNET_PeerIdentity) * putl);
+ if ( (GNUNET_BLOCK_TYPE_ANY != mh->type) &&
+ (mh->type != ntohl (msg->type)) )
+ continue;
+ if ( (NULL != mh->key) &&
+ (0 != GNUNET_memcmp (mh->key,
+ &msg->key)) )
+ continue;
+ mh->put_cb (mh->cb_cls,
+ ro,
+ (enum GNUNET_BLOCK_Type) ntohl (msg->type),
+ ntohl (msg->hop_count),
+ ntohl (msg->desired_replication_level),
+ trunc_peer,
+ putl,
+ path,
+ GNUNET_TIME_absolute_ntoh (msg->expiration_time),
+ &msg->key,
+ (const void *) &path[putl],
+ msize);
}
}
@@ -685,22 +758,32 @@ handle_monitor_put (void *cls,
* @return #GNUNET_OK if everything went fine,
* #GNUNET_SYSERR if the message is malformed.
*/
-static int
+static enum GNUNET_GenericReturnValue
check_client_result (void *cls,
const struct GNUNET_DHT_ClientResultMessage *msg)
{
size_t msize = ntohs (msg->header.size) - sizeof(*msg);
uint32_t put_path_length = ntohl (msg->put_path_length);
uint32_t get_path_length = ntohl (msg->get_path_length);
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (msg->options);
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
size_t meta_length;
- meta_length =
- sizeof(struct GNUNET_PeerIdentity) * (get_path_length + put_path_length);
- if ((msize < meta_length) ||
- (get_path_length >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
- (put_path_length >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
+ if (truncated)
+ {
+ if (msize < sizeof (struct GNUNET_PeerIdentity))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ msize -= sizeof (struct GNUNET_PeerIdentity);
+ }
+ meta_length = msize / sizeof(struct GNUNET_DHT_PathElement);
+ if ( (get_path_length + put_path_length >
+ meta_length) ||
+ (get_path_length + put_path_length <
+ get_path_length) )
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -717,7 +800,7 @@ check_client_result (void *cls,
* @param value the `struct GNUNET_DHT_GetHandle` of a request matching the same key
* @return #GNUNET_YES to continue to iterate over all results
*/
-static int
+static enum GNUNET_GenericReturnValue
process_client_result (void *cls,
const struct GNUNET_HashCode *key,
void *value)
@@ -725,15 +808,36 @@ process_client_result (void *cls,
const struct GNUNET_DHT_ClientResultMessage *crm = cls;
struct GNUNET_DHT_GetHandle *get_handle = value;
size_t msize = ntohs (crm->header.size) - sizeof(*crm);
- uint32_t put_path_length = ntohl (crm->put_path_length);
- uint32_t get_path_length = ntohl (crm->get_path_length);
- const struct GNUNET_PeerIdentity *put_path;
- const struct GNUNET_PeerIdentity *get_path;
+ uint16_t type = ntohl (crm->type);
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohl (crm->options);
+ bool truncated
+ = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ uint32_t put_path_length
+ = ntohl (crm->put_path_length);
+ uint32_t get_path_length
+ = ntohl (crm->get_path_length);
+ const struct GNUNET_PeerIdentity *trunc_peer
+ = truncated
+ ? (const struct GNUNET_PeerIdentity *) &crm[1]
+ : NULL;
+ const struct GNUNET_DHT_PathElement *put_path
+ = truncated
+ ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
+ : (const struct GNUNET_DHT_PathElement *) &crm[1];
+ const struct GNUNET_DHT_PathElement *get_path
+ = &put_path[put_path_length];
+ const void *data
+ = &get_path[get_path_length];
+ size_t meta_length
+ = sizeof(struct GNUNET_DHT_PathElement)
+ * (get_path_length + put_path_length);
+ size_t data_length
+ = msize - meta_length;
struct GNUNET_HashCode hc;
- size_t data_length;
- size_t meta_length;
- const void *data;
+ if (truncated)
+ data_length -= sizeof (struct GNUNET_PeerIdentity);
if (crm->unique_id != get_handle->unique_id)
{
/* UID mismatch */
@@ -744,20 +848,22 @@ process_client_result (void *cls,
(unsigned long long) get_handle->unique_id);
return GNUNET_YES;
}
- /* FIXME: might want to check that type matches */
- meta_length =
- sizeof(struct GNUNET_PeerIdentity) * (get_path_length + put_path_length);
- data_length = msize - meta_length;
- put_path = (const struct GNUNET_PeerIdentity *) &crm[1];
- get_path = &put_path[put_path_length];
+ if ( (get_handle->type != GNUNET_BLOCK_TYPE_ANY) &&
+ (get_handle->type != type) )
+ {
+ /* type mismatch */
+ GNUNET_break (0);
+ return GNUNET_YES;
+ }
+
{
char *pp;
char *gp;
- gp = GNUNET_STRINGS_pp2s (get_path,
- get_path_length);
- pp = GNUNET_STRINGS_pp2s (put_path,
- put_path_length);
+ gp = GNUNET_DHT_pp2s (get_path,
+ get_path_length);
+ pp = GNUNET_DHT_pp2s (put_path,
+ put_path_length);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Giving %u byte reply for %s to application (GP: %s, PP: %s)\n",
(unsigned int) data_length,
@@ -767,7 +873,6 @@ process_client_result (void *cls,
GNUNET_free (gp);
GNUNET_free (pp);
}
- data = &get_path[get_path_length];
/* remember that we've seen this result */
GNUNET_CRYPTO_hash (data,
data_length,
@@ -781,11 +886,12 @@ process_client_result (void *cls,
get_handle->iter (get_handle->iter_cls,
GNUNET_TIME_absolute_ntoh (crm->expiration),
key,
+ trunc_peer,
get_path,
get_path_length,
put_path,
put_path_length,
- ntohl (crm->type),
+ type,
data_length,
data);
return GNUNET_YES;
@@ -812,6 +918,53 @@ handle_client_result (void *cls,
/**
+ * Process a client HELLO message received from the service.
+ *
+ * @param cls The DHT handle.
+ * @param hdr HELLO URL message from the service.
+ * @return #GNUNET_OK if @a hdr is well-formed
+ */
+static enum GNUNET_GenericReturnValue
+check_client_hello (void *cls,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ uint16_t len = ntohs (hdr->size);
+ const char *buf = (const char *) &hdr[1];
+
+ (void) cls;
+ if ('\0' != buf[len - sizeof (*hdr) - 1])
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Process a client HELLO message received from the service.
+ *
+ * @param cls The DHT handle.
+ * @param hdr HELLO URL message from the service.
+ */
+static void
+handle_client_hello (void *cls,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ struct GNUNET_DHT_Handle *handle = cls;
+ const char *url = (const char *) &hdr[1];
+ struct GNUNET_DHT_HelloGetHandle *hgh;
+
+ while (NULL != (hgh = handle->hgh_head))
+ {
+ hgh->cb (hgh->cb_cls,
+ url);
+ GNUNET_DHT_hello_get_cancel (hgh);
+ }
+}
+
+
+/**
* Process a MQ PUT transmission notification.
*
* @param cls The DHT handle.
@@ -838,14 +991,14 @@ handle_put_cont (void *cls)
* @param h DHT handle to reconnect
* @return #GNUNET_YES on success, #GNUNET_NO on failure.
*/
-static int
+static enum GNUNET_GenericReturnValue
try_connect (struct GNUNET_DHT_Handle *h)
{
struct GNUNET_MQ_MessageHandler handlers[] = {
- GNUNET_MQ_hd_var_size (monitor_get,
- GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET,
- struct GNUNET_DHT_MonitorGetMessage,
- h),
+ GNUNET_MQ_hd_fixed_size (monitor_get,
+ GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET,
+ struct GNUNET_DHT_MonitorGetMessage,
+ h),
GNUNET_MQ_hd_var_size (monitor_get_resp,
GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP,
struct GNUNET_DHT_MonitorGetRespMessage,
@@ -858,6 +1011,10 @@ try_connect (struct GNUNET_DHT_Handle *h)
GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT,
struct GNUNET_DHT_ClientResultMessage,
h),
+ GNUNET_MQ_hd_var_size (client_hello,
+ GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL,
+ struct GNUNET_MessageHeader,
+ h),
GNUNET_MQ_handler_end ()
};
@@ -878,14 +1035,6 @@ try_connect (struct GNUNET_DHT_Handle *h)
}
-/**
- * Initialize the connection with the DHT service.
- *
- * @param cfg configuration to use
- * @param ht_len size of the internal hash table to use for
- * processing multiple GET/FIND requests in parallel
- * @return handle to the DHT service, or NULL on error
- */
struct GNUNET_DHT_Handle *
GNUNET_DHT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
unsigned int ht_len)
@@ -909,11 +1058,6 @@ GNUNET_DHT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
}
-/**
- * Shutdown connection with the DHT service.
- *
- * @param handle handle of the DHT connection to stop
- */
void
GNUNET_DHT_disconnect (struct GNUNET_DHT_Handle *handle)
{
@@ -942,26 +1086,6 @@ GNUNET_DHT_disconnect (struct GNUNET_DHT_Handle *handle)
}
-/**
- * Perform a PUT operation storing data in the DHT. FIXME: we should
- * change the protocol to get a confirmation for the PUT from the DHT
- * and call 'cont' only after getting the confirmation; otherwise, the
- * client has no good way of telling if the 'PUT' message actually got
- * to the DHT service!
- *
- * @param handle handle to DHT service
- * @param key the key to store under
- * @param desired_replication_level estimate of how many
- * nearest peers this request should reach
- * @param options routing options for this message
- * @param type type of the value
- * @param size number of bytes in data; must be less than 64k
- * @param data the data to store
- * @param exp desired expiration time for the value
- * @param cont continuation to call when done (transmitting request to service)
- * You must not call #GNUNET_DHT_disconnect in this continuation
- * @param cont_cls closure for @a cont
- */
struct GNUNET_DHT_PutHandle *
GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
const struct GNUNET_HashCode *key,
@@ -1020,17 +1144,6 @@ GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
}
-/**
- * Cancels a DHT PUT operation. Note that the PUT request may still
- * go out over the network (we can't stop that); However, if the PUT
- * has not yet been sent to the service, cancelling the PUT will stop
- * this from happening (but there is no way for the user of this API
- * to tell if that is the case). The only use for this API is to
- * prevent a later call to 'cont' from #GNUNET_DHT_put (e.g. because
- * the system is shutting down).
- *
- * @param ph put operation to cancel ('cont' will no longer be called)
- */
void
GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph)
{
@@ -1047,22 +1160,6 @@ GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph)
}
-/**
- * Perform an asynchronous GET operation on the DHT identified. See
- * also #GNUNET_BLOCK_evaluate.
- *
- * @param handle handle to the DHT service
- * @param type expected type of the response object
- * @param key the key to look up
- * @param desired_replication_level estimate of how many
- nearest peers this request should reach
- * @param options routing options for this message
- * @param xquery extended query data (can be NULL, depending on type)
- * @param xquery_size number of bytes in @a xquery
- * @param iter function to call on each result
- * @param iter_cls closure for @a iter
- * @return handle to stop the async get
- */
struct GNUNET_DHT_GetHandle *
GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle,
enum GNUNET_BLOCK_Type type,
@@ -1112,16 +1209,6 @@ GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle,
}
-/**
- * Tell the DHT not to return any of the following known results
- * to this client.
- *
- * @param get_handle get operation for which results should be filtered
- * @param num_results number of results to be blocked that are
- * provided in this call (size of the @a results array)
- * @param results array of hash codes over the 'data' of the results
- * to be blocked
- */
void
GNUNET_DHT_get_filter_known_results (struct GNUNET_DHT_GetHandle *get_handle,
unsigned int num_results,
@@ -1146,11 +1233,6 @@ GNUNET_DHT_get_filter_known_results (struct GNUNET_DHT_GetHandle *get_handle,
}
-/**
- * Stop async DHT-get.
- *
- * @param get_handle handle to the GET operation to stop
- */
void
GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle)
{
@@ -1184,18 +1266,6 @@ GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle)
}
-/**
- * Start monitoring the local DHT service.
- *
- * @param handle Handle to the DHT service.
- * @param type Type of blocks that are of interest.
- * @param key Key of data of interest, NULL for all.
- * @param get_cb Callback to process monitored get messages.
- * @param get_resp_cb Callback to process monitored get response messages.
- * @param put_cb Callback to process monitored put messages.
- * @param cb_cls Closure for callbacks.
- * @return Handle to stop monitoring.
- */
struct GNUNET_DHT_MonitorHandle *
GNUNET_DHT_monitor_start (struct GNUNET_DHT_Handle *handle,
enum GNUNET_BLOCK_Type type,
@@ -1228,13 +1298,6 @@ GNUNET_DHT_monitor_start (struct GNUNET_DHT_Handle *handle,
}
-/**
- * Stop monitoring.
- *
- * @param mh The handle to the monitor request returned by monitor_start.
- *
- * On return get_handle will no longer be valid, caller must not use again!!!
- */
void
GNUNET_DHT_monitor_stop (struct GNUNET_DHT_MonitorHandle *mh)
{
@@ -1263,4 +1326,179 @@ GNUNET_DHT_monitor_stop (struct GNUNET_DHT_MonitorHandle *mh)
}
+char *
+GNUNET_DHT_pp2s (const struct GNUNET_DHT_PathElement *path,
+ unsigned int path_len)
+{
+ char *buf;
+ size_t off;
+ size_t plen = path_len * 5 + 1;
+
+ GNUNET_assert (path_len < UINT32_MAX / 5);
+ off = 0;
+ buf = GNUNET_malloc (plen);
+ for (unsigned int i = 0; i < path_len; i++)
+ {
+ off += GNUNET_snprintf (&buf[off],
+ plen - off,
+ "%s%s",
+ GNUNET_i2s (&path[i].pred),
+ (i == path_len - 1) ? "" : "-");
+ }
+ return buf;
+}
+
+
+unsigned int
+GNUNET_DHT_verify_path (const void *data,
+ size_t data_size,
+ struct GNUNET_TIME_Absolute exp_time,
+ const struct GNUNET_PeerIdentity *bpid,
+ const struct GNUNET_DHT_PathElement *put_path,
+ unsigned int put_path_len,
+ const struct GNUNET_DHT_PathElement *get_path,
+ unsigned int get_path_len,
+ const struct GNUNET_PeerIdentity *me)
+{
+ static struct GNUNET_PeerIdentity zero;
+ struct GNUNET_DHT_HopSignature hs = {
+ .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP),
+ .purpose.size = htonl (sizeof (hs)),
+ .expiration_time = GNUNET_TIME_absolute_hton (exp_time)
+ };
+ unsigned int i;
+
+ if (0 == get_path_len + put_path_len)
+ return 0;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s is verifying signatures with GPL: %u PPL: %u!\n",
+ GNUNET_i2s (me),
+ get_path_len,
+ put_path_len);
+ for (unsigned int j = 0; j<put_path_len; j++)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "PP%u=%s\n",
+ j,
+ GNUNET_i2s (&put_path[j].pred));
+ for (unsigned int j = 0; j<get_path_len; j++)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GP%u=%s\n",
+ j,
+ GNUNET_i2s (&get_path[j].pred));
+
+ GNUNET_CRYPTO_hash (data,
+ data_size,
+ &hs.h_data);
+ i = put_path_len + get_path_len;
+ while (i > 0)
+ {
+ const struct GNUNET_PeerIdentity *pred;
+ const struct GNUNET_PeerIdentity *succ;
+ const struct GNUNET_DHT_PathElement *pe;
+
+ i--;
+ if (0 == i)
+ {
+ pred = (NULL == bpid) ? &zero : bpid;
+ }
+ else
+ {
+ unsigned int off = i - 1;
+
+ pred = (off >= put_path_len)
+ ? &get_path[off - put_path_len].pred
+ : &put_path[off].pred;
+ }
+ if (i == get_path_len + put_path_len - 1)
+ {
+ succ = me;
+ }
+ else
+ {
+ unsigned int off = i + 1;
+
+ succ = (off >= put_path_len)
+ ? &get_path[off - put_path_len].pred
+ : &put_path[off].pred;
+ }
+ hs.pred = *pred;
+ hs.succ = *succ;
+ pe = (i >= put_path_len)
+ ? &get_path[i - put_path_len]
+ : &put_path[i];
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (
+ GNUNET_SIGNATURE_PURPOSE_DHT_HOP,
+ &hs,
+ &pe->sig,
+ &pe->pred.public_key))
+ {
+ GNUNET_break_op (0);
+ return i + 1;
+ }
+ }
+ return i;
+}
+
+
+struct GNUNET_DHT_HelloGetHandle *
+GNUNET_DHT_hello_get (struct GNUNET_DHT_Handle *dht_handle,
+ GNUNET_DHT_HelloGetCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_DHT_HelloGetHandle *hgh;
+ struct GNUNET_MessageHeader *hdr;
+ struct GNUNET_MQ_Envelope *env;
+
+ hgh = GNUNET_new (struct GNUNET_DHT_HelloGetHandle);
+ hgh->cb = cb;
+ hgh->cb_cls = cb_cls;
+ hgh->dht_handle = dht_handle;
+ GNUNET_CONTAINER_DLL_insert (dht_handle->hgh_head,
+ dht_handle->hgh_tail,
+ hgh);
+ env = GNUNET_MQ_msg (hdr,
+ GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET);
+ GNUNET_MQ_send (dht_handle->mq,
+ env);
+ return hgh;
+}
+
+
+void
+GNUNET_DHT_hello_get_cancel (struct GNUNET_DHT_HelloGetHandle *hgh)
+{
+ struct GNUNET_DHT_Handle *dht_handle = hgh->dht_handle;
+
+ GNUNET_CONTAINER_DLL_remove (dht_handle->hgh_head,
+ dht_handle->hgh_tail,
+ hgh);
+ GNUNET_free (hgh);
+}
+
+
+void
+GNUNET_DHT_hello_offer (struct GNUNET_DHT_Handle *dht_handle,
+ const char *url,
+ GNUNET_SCHEDULER_TaskCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_MessageHeader *hdr;
+ size_t slen = strlen (url) + 1;
+ struct GNUNET_MQ_Envelope *env;
+
+ env = GNUNET_MQ_msg_extra (hdr,
+ slen,
+ GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL);
+ memcpy (&hdr[1],
+ url,
+ slen);
+ GNUNET_MQ_notify_sent (env,
+ cb,
+ cb_cls);
+ GNUNET_MQ_send (dht_handle->mq,
+ env);
+}
+
+
/* end of dht_api.c */
diff --git a/src/dht/dht_test_lib.c b/src/dht/dht_test_lib.c
index 0d382cd74..29c5088d1 100644
--- a/src/dht/dht_test_lib.c
+++ b/src/dht/dht_test_lib.c
@@ -138,11 +138,6 @@ dht_connect_cb (void *cls,
}
-/**
- * Clean up the testbed.
- *
- * @param ctx handle for the testbed
- */
void
GNUNET_DHT_TEST_cleanup (struct GNUNET_DHT_TEST_Context *ctx)
{
@@ -179,16 +174,6 @@ dht_test_run (void *cls,
}
-/**
- * Run a test using the given name, configuration file and number of
- * peers.
- *
- * @param testname name of the test (for logging)
- * @param cfgname name of the configuration file
- * @param num_peers number of peers to start
- * @param tmain main function to run once the testbed is ready
- * @param tmain_cls closure for 'tmain'
- */
void
GNUNET_DHT_TEST_run (const char *testname,
const char *cfgname,
diff --git a/src/dht/dhtu_testbed_connect.sh b/src/dht/dhtu_testbed_connect.sh
new file mode 100755
index 000000000..871e9eb1b
--- /dev/null
+++ b/src/dht/dhtu_testbed_connect.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This file is in the public domain.
+
+# Helper script for dhtu_testbed_deploy.sh.
+# Do not invoke directly.
+
+n=$1
+CFG="/tmp/deployment/${n}.conf"
+HELLO=`gnunet-dht-hello -c $CFG`
+
+# Create dense topology:
+#for OFF in `seq 1 $MAX`
+#do
+# TCFG="/tmp/deployment/${OFF}.conf"
+# gnunet-dht-hello -c $TCFG $HELLO
+#done
+#exit 0
+
+# Create sparse topology:
+R=1
+while test `expr $R \* $R \* $R` -lt $MAX
+do
+ END=`expr $R \* $R`
+ for M in `seq $R $R $END`
+ do
+ OFF=`expr \( $n + $M \) % $MAX`
+ TCFG="/tmp/deployment/${OFF}.conf"
+ gnunet-dht-hello -c $TCFG $HELLO
+ done
+ R=`expr $R + 1`
+done
diff --git a/src/dht/dhtu_testbed_deploy.conf b/src/dht/dhtu_testbed_deploy.conf
new file mode 100644
index 000000000..59d69894a
--- /dev/null
+++ b/src/dht/dhtu_testbed_deploy.conf
@@ -0,0 +1,26 @@
+# This file is in the public domain.
+
+# Simple configuration template to deploy a DHT testbed
+# with peers using the IP underlay.
+
+[paths]
+GNUNET_DATA_HOME=/tmp/%N%
+
+[dht]
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-dht-%N%.sock
+
+[dhtu-ip]
+ENABLED = YES
+NSE = 10
+UDP_PORT = %N%
+
+[dhtu-gnunet]
+ENABLED = NO
+
+[statistics]
+DISABLE = YES
+
+[dhtcache]
+DATABASE = heap
+QUOTA = 50 MB
+DISABLE_BF_RC = YES
diff --git a/src/dht/dhtu_testbed_deploy.sh b/src/dht/dhtu_testbed_deploy.sh
new file mode 100755
index 000000000..5a7fdde15
--- /dev/null
+++ b/src/dht/dhtu_testbed_deploy.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# This file is in the public domain.
+
+# We will use UDP ports above this number.
+MINPORT=10000
+
+# Cleanup to run whenever we exit
+function cleanup()
+{
+ for n in `jobs -p`
+ do
+ kill $n 2> /dev/null || true
+ done
+ wait
+}
+
+# Install cleanup handler (except for kill -9)
+trap cleanup EXIT
+
+if test -z "$1"
+then
+ echo "Call with the number of peers to launch."
+ exit 1
+fi
+
+if test ! -x `which parallel`
+then
+ echo "This script requires GNU parallel"
+ exit 1
+fi
+
+if test ! -x `which gnunet-service-dht`
+then
+ echo "This script requires gnunet-service-dht in \$PATH"
+ exit 1
+fi
+
+if test ! -x `which gnunet-dht-hello`
+then
+ echo "This script requires gnunet-dht-hello in \$PATH"
+ exit 1
+fi
+
+MAX=`expr $1 - 1`
+
+export GNUNET_FORCE_LOG="dht*;;;;DEBUG"
+
+echo -n "Starting $1 peers "
+mkdir -p /tmp/deployment
+for n in `seq 0 $MAX`
+do
+ PORT=`expr $MINPORT + $n`
+ CFG="/tmp/deployment/${n}.conf"
+ cat dhtu_testbed_deploy.conf | sed -e "s/%N%/$PORT/" > $CFG
+ gnunet-service-dht -c $CFG &> /tmp/deployment/$n.log &
+ echo -n "."
+done
+
+echo ""
+echo "$1 peers ready".
+
+unset GNUNET_FORCE_LOG
+
+function connect()
+{
+ n=$1
+}
+
+echo -n "Connecting peers ..."
+
+export MAX
+if test 0 != $MAX
+then
+ seq 0 $MAX | parallel ./dhtu_testbed_connect.sh :::
+fi
+
+
+echo ""
+echo "Network ready. Press ENTER to terminate the testbed!"
+echo "Interact with peers using '-c /tmp/deployment/\$N.conf'"
+
+read
+
+exit 0
diff --git a/src/dht/gnunet-dht-get.c b/src/dht/gnunet-dht-get.c
index c8a1cb735..806cafd0d 100644
--- a/src/dht/gnunet-dht-get.c
+++ b/src/dht/gnunet-dht-get.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
+ Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -58,6 +58,11 @@ static unsigned int verbose;
static int demultixplex_everywhere;
/**
+ * Use #GNUNET_DHT_RO_RECORD_ROUTE.
+ */
+static int record_route;
+
+/**
* Handle to the DHT
*/
static struct GNUNET_DHT_Handle *dht_handle;
@@ -134,6 +139,7 @@ timeout_task (void *cls)
* @param cls closure
* @param exp when will this value expire
* @param key key of the result
+ * @param trunc_peer peer at which the path was truncated, or NULL if not
* @param get_path peers on reply path (or NULL if not recorded)
* @param get_path_length number of entries in get_path
* @param put_path peers on the PUT path (or NULL if not recorded)
@@ -146,30 +152,45 @@ static void
get_result_iterator (void *cls,
struct GNUNET_TIME_Absolute exp,
const struct GNUNET_HashCode *key,
- const struct GNUNET_PeerIdentity *get_path,
+ const struct GNUNET_PeerIdentity *trunc_peer,
+ const struct GNUNET_DHT_PathElement *get_path,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
+ const struct GNUNET_DHT_PathElement *put_path,
unsigned int put_path_length,
enum GNUNET_BLOCK_Type type,
size_t size,
const void *data)
{
fprintf (stdout,
- (GNUNET_BLOCK_TYPE_TEST == type) ? _ ("Result %d, type %d:\n%.*s\n")
+ (GNUNET_BLOCK_TYPE_TEST == type)
+ ? _ ("Result %d, type %d:\n%.*s\n")
: _ ("Result %d, type %d:\n"),
result_count,
type,
- (unsigned int) size,
+ (int) size,
(char *) data);
- if (verbose)
+ if (record_route && verbose)
{
- fprintf (stdout, " GET path: ");
+ fprintf (stdout,
+ " GET path: ");
for (unsigned int i = 0; i < get_path_length; i++)
- fprintf (stdout, "%s%s", (0 == i) ? "" : "-", GNUNET_i2s (&get_path[i]));
- fprintf (stdout, "\n PUT path: ");
+ fprintf (stdout,
+ "%s%s",
+ (0 == i) ? "" : "-",
+ GNUNET_i2s (&get_path[i].pred));
+ fprintf (stdout,
+ "\n PUT path: ");
for (unsigned int i = 0; i < put_path_length; i++)
- fprintf (stdout, "%s%s", (0 == i) ? "" : "-", GNUNET_i2s (&put_path[i]));
- fprintf (stdout, "\n");
+ fprintf (stdout,
+ "%s%s",
+ (0 == i) ? "" : "-",
+ GNUNET_i2s (&put_path[i].pred));
+ if (NULL != trunc_peer)
+ fprintf (stdout,
+ "T%s",
+ GNUNET_i2s (trunc_peer));
+ fprintf (stdout,
+ "\n");
}
result_count++;
}
@@ -190,17 +211,22 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *c)
{
struct GNUNET_HashCode key;
+ enum GNUNET_DHT_RouteOption ro;
cfg = c;
if (NULL == query_key)
{
- fprintf (stderr, "%s", _ ("Must provide key for DHT GET!\n"));
+ fprintf (stderr,
+ "%s",
+ _ ("Must provide key for DHT GET!\n"));
ret = 1;
return;
}
if (NULL == (dht_handle = GNUNET_DHT_connect (cfg, 1)))
{
- fprintf (stderr, "%s", _ ("Failed to connect to DHT service!\n"));
+ fprintf (stderr,
+ "%s",
+ _ ("Failed to connect to DHT service!\n"));
ret = 1;
return;
}
@@ -214,13 +240,16 @@ run (void *cls,
GNUNET_h2s_full (&key));
GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
tt = GNUNET_SCHEDULER_add_delayed (timeout_request, &timeout_task, NULL);
+ ro = GNUNET_DHT_RO_NONE;
+ if (demultixplex_everywhere)
+ ro |= GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE;
+ if (record_route)
+ ro |= GNUNET_DHT_RO_RECORD_ROUTE;
get_handle = GNUNET_DHT_get_start (dht_handle,
query_type,
&key,
replication,
- (demultixplex_everywhere)
- ? GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
- : GNUNET_DHT_RO_NONE,
+ ro,
NULL,
0,
&get_result_iterator,
@@ -238,39 +267,50 @@ run (void *cls,
int
main (int argc, char *const *argv)
{
- struct GNUNET_GETOPT_CommandLineOption options[] =
- { GNUNET_GETOPT_option_string ('k',
- "key",
- "KEY",
- gettext_noop ("the query key"),
- &query_key),
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_string (
+ 'k',
+ "key",
+ "KEY",
+ gettext_noop ("the query key"),
+ &query_key),
GNUNET_GETOPT_option_uint (
'r',
"replication",
"LEVEL",
gettext_noop ("how many parallel requests (replicas) to create"),
&replication),
- GNUNET_GETOPT_option_uint ('t',
- "type",
- "TYPE",
- gettext_noop ("the type of data to look for"),
- &query_type),
+ GNUNET_GETOPT_option_flag (
+ 'R',
+ "record",
+ gettext_noop ("use DHT's record route option"),
+ &record_route),
+ GNUNET_GETOPT_option_uint (
+ 't',
+ "type",
+ "TYPE",
+ gettext_noop ("the type of data to look for"),
+ &query_type),
GNUNET_GETOPT_option_relative_time (
'T',
"timeout",
"TIMEOUT",
gettext_noop ("how long to execute this query before giving up?"),
&timeout_request),
- GNUNET_GETOPT_option_flag ('x',
- "demultiplex",
- gettext_noop (
- "use DHT's demultiplex everywhere option"),
- &demultixplex_everywhere),
+ GNUNET_GETOPT_option_flag (
+ 'x',
+ "demultiplex",
+ gettext_noop (
+ "use DHT's demultiplex everywhere option"),
+ &demultixplex_everywhere),
GNUNET_GETOPT_option_verbose (&verbose),
- GNUNET_GETOPT_OPTION_END };
+ GNUNET_GETOPT_OPTION_END
+ };
- if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_get_utf8_args (argc, argv,
+ &argc, &argv))
return 2;
return (GNUNET_OK ==
GNUNET_PROGRAM_run (
diff --git a/src/dht/gnunet-dht-hello.c b/src/dht/gnunet-dht-hello.c
new file mode 100644
index 000000000..369ed5643
--- /dev/null
+++ b/src/dht/gnunet-dht-hello.c
@@ -0,0 +1,178 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2022 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file dht/gnunet-dht-hello.c
+ * @brief Obtain HELLO from DHT for bootstrapping
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_dht_service.h"
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "dht-clients", __VA_ARGS__)
+
+/**
+ * Handle to the DHT
+ */
+static struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * Handle to the DHT hello get operation.
+ */
+static struct GNUNET_DHT_HelloGetHandle *get_hello_handle;
+
+/**
+ * Global status value
+ */
+static int global_ret;
+
+
+/**
+ * Task run to clean up on shutdown.
+ *
+ * @param cls unused
+ */
+static void
+cleanup_task (void *cls)
+{
+ if (NULL != get_hello_handle)
+ {
+ GNUNET_DHT_hello_get_cancel (get_hello_handle);
+ get_hello_handle = NULL;
+ }
+ if (NULL != dht_handle)
+ {
+ GNUNET_DHT_disconnect (dht_handle);
+ dht_handle = NULL;
+ }
+}
+
+
+/**
+ * Task run when we are finished. Triggers shutdown.
+ *
+ * @param cls unused
+ */
+static void
+hello_done_cb (void *cls)
+{
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Function called on our HELLO.
+ *
+ * @param cls closure
+ * @param url the HELLO URL
+ */
+static void
+hello_result_cb (void *cls,
+ const char *url)
+{
+ get_hello_handle = NULL;
+ fprintf (stdout,
+ "%s\n",
+ url);
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure, NULL
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ (void) cls;
+ (void) cfgfile;
+ GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
+ NULL);
+ if (NULL == (dht_handle = GNUNET_DHT_connect (cfg,
+ 1)))
+ {
+ fprintf (stderr,
+ _ ("Failed to connect to DHT service!\n"));
+ global_ret = EXIT_NOTCONFIGURED;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (NULL == args[0])
+ {
+ get_hello_handle = GNUNET_DHT_hello_get (dht_handle,
+ &hello_result_cb,
+ NULL);
+ GNUNET_break (NULL != get_hello_handle);
+ }
+ else
+ {
+ GNUNET_DHT_hello_offer (dht_handle,
+ args[0],
+ &hello_done_cb,
+ NULL);
+ }
+}
+
+
+/**
+ * Entry point for gnunet-dht-hello
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc,
+ char *const *argv)
+{
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ enum GNUNET_GenericReturnValue iret;
+
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_get_utf8_args (argc, argv,
+ &argc, &argv))
+ return 2;
+ iret = GNUNET_PROGRAM_run (
+ argc,
+ argv,
+ "gnunet-dht-hello [URL]",
+ gettext_noop (
+ "Obtain HELLO from DHT or provide HELLO to DHT for bootstrapping"),
+ options,
+ &run,
+ NULL);
+ if (GNUNET_SYSERR == iret)
+ return EXIT_FAILURE;
+ if (GNUNET_NO == iret)
+ return EXIT_SUCCESS;
+ return global_ret;
+}
+
+
+/* end of gnunet-dht-hello.c */
diff --git a/src/dht/gnunet-dht-monitor.c b/src/dht/gnunet-dht-monitor.c
index 8dc14e223..93ea1284a 100644
--- a/src/dht/gnunet-dht-monitor.c
+++ b/src/dht/gnunet-dht-monitor.c
@@ -125,8 +125,6 @@ timeout_task (void *cls)
* @param options Options, for instance RecordRoute, DemultiplexEverywhere.
* @param type The type of data in the request.
* @param hop_count Hop count so far.
- * @param path_length number of entries in path (or 0 if not recorded).
- * @param path peers on the GET path (or NULL if not recorded).
* @param desired_replication_level Desired replication level.
* @param key Key of the requested data.
*/
@@ -136,8 +134,6 @@ get_callback (void *cls,
enum GNUNET_BLOCK_Type type,
uint32_t hop_count,
uint32_t desired_replication_level,
- unsigned int path_length,
- const struct GNUNET_PeerIdentity *path,
const struct GNUNET_HashCode *key)
{
fprintf (stdout,
@@ -154,6 +150,7 @@ get_callback (void *cls,
*
* @param cls Closure.
* @param type The type of data in the result.
+ * @param trunc_peer peer where the path was truncated, or NULL if the path is complete
* @param get_path Peers on GET path (or NULL if not recorded).
* @param get_path_length number of entries in get_path.
* @param put_path peers on the PUT path (or NULL if not recorded).
@@ -166,9 +163,10 @@ get_callback (void *cls,
static void
get_resp_callback (void *cls,
enum GNUNET_BLOCK_Type type,
- const struct GNUNET_PeerIdentity *get_path,
+ const struct GNUNET_PeerIdentity *trunc_peer,
+ const struct GNUNET_DHT_PathElement *get_path,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
+ const struct GNUNET_DHT_PathElement *put_path,
unsigned int put_path_length,
struct GNUNET_TIME_Absolute exp,
const struct GNUNET_HashCode *key,
@@ -196,6 +194,7 @@ get_resp_callback (void *cls,
* @param options Options, for instance RecordRoute, DemultiplexEverywhere.
* @param type The type of data in the request.
* @param hop_count Hop count so far.
+ * @param trunc_peer peer where the path was truncated, or NULL if the path is complete
* @param path_length number of entries in path (or 0 if not recorded).
* @param path peers on the PUT path (or NULL if not recorded).
* @param desired_replication_level Desired replication level.
@@ -210,8 +209,9 @@ put_callback (void *cls,
enum GNUNET_BLOCK_Type type,
uint32_t hop_count,
uint32_t desired_replication_level,
+ const struct GNUNET_PeerIdentity *trunc_peer,
unsigned int path_length,
- const struct GNUNET_PeerIdentity *path,
+ const struct GNUNET_DHT_PathElement *path,
struct GNUNET_TIME_Absolute exp,
const struct GNUNET_HashCode *key,
const void *data,
diff --git a/src/dht/gnunet-dht-put.c b/src/dht/gnunet-dht-put.c
index 7ee4ec185..531107ef2 100644
--- a/src/dht/gnunet-dht-put.c
+++ b/src/dht/gnunet-dht-put.c
@@ -179,48 +179,57 @@ run (void *cls,
int
main (int argc, char *const *argv)
{
- struct GNUNET_GETOPT_CommandLineOption options[] =
- { GNUNET_GETOPT_option_string ('d',
- "data",
- "DATA",
- gettext_noop (
- "the data to insert under the key"),
- &data),
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_string (
+ 'd',
+ "data",
+ "DATA",
+ gettext_noop (
+ "the data to insert under the key"),
+ &data),
GNUNET_GETOPT_option_relative_time (
'e',
"expiration",
"EXPIRATION",
gettext_noop ("how long to store this entry in the dht (in seconds)"),
&expiration),
- GNUNET_GETOPT_option_string ('k',
- "key",
- "KEY",
- gettext_noop ("the query key"),
- &query_key),
- GNUNET_GETOPT_option_flag ('x',
- "demultiplex",
- gettext_noop (
- "use DHT's demultiplex everywhere option"),
- &demultixplex_everywhere),
- GNUNET_GETOPT_option_uint ('r',
- "replication",
- "LEVEL",
- gettext_noop ("how many replicas to create"),
- &replication),
- GNUNET_GETOPT_option_flag ('R',
- "record",
- gettext_noop ("use DHT's record route option"),
- &record_route),
- GNUNET_GETOPT_option_uint ('t',
- "type",
- "TYPE",
- gettext_noop ("the type to insert data as"),
- &query_type),
+ GNUNET_GETOPT_option_string (
+ 'k',
+ "key",
+ "KEY",
+ gettext_noop ("the query key"),
+ &query_key),
+ GNUNET_GETOPT_option_flag (
+ 'x',
+ "demultiplex",
+ gettext_noop (
+ "use DHT's demultiplex everywhere option"),
+ &demultixplex_everywhere),
+ GNUNET_GETOPT_option_uint (
+ 'r',
+ "replication",
+ "LEVEL",
+ gettext_noop ("how many replicas to create"),
+ &replication),
+ GNUNET_GETOPT_option_flag (
+ 'R',
+ "record",
+ gettext_noop ("use DHT's record route option"),
+ &record_route),
+ GNUNET_GETOPT_option_uint (
+ 't',
+ "type",
+ "TYPE",
+ gettext_noop ("the type to insert data as"),
+ &query_type),
GNUNET_GETOPT_option_verbose (&verbose),
- GNUNET_GETOPT_OPTION_END };
+ GNUNET_GETOPT_OPTION_END
+ };
- if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_get_utf8_args (argc, argv,
+ &argc, &argv))
return 2;
expiration = GNUNET_TIME_UNIT_HOURS;
return (GNUNET_OK ==
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index da46dcfee..39433791d 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -27,53 +27,335 @@
#include "platform.h"
#include "gnunet_block_lib.h"
#include "gnunet_util_lib.h"
-#include "gnunet_transport_service.h"
-#include "gnunet_transport_hello_service.h"
#include "gnunet_hello_lib.h"
+#include "gnunet_hello_uri_lib.h"
#include "gnunet_dht_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet-service-dht.h"
#include "gnunet-service-dht_datacache.h"
-#include "gnunet-service-dht_hello.h"
#include "gnunet-service-dht_neighbours.h"
-#include "gnunet-service-dht_nse.h"
#include "gnunet-service-dht_routing.h"
/**
+ * How often do we broadcast our HELLO to neighbours if
+ * nothing special happens?
+ */
+#define HELLO_FREQUENCY GNUNET_TIME_UNIT_HOURS
+
+
+/**
+ * Information we keep per underlay.
+ */
+struct GDS_Underlay
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct GDS_Underlay *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct GDS_Underlay *prev;
+
+ /**
+ * Environment for this underlay.
+ */
+ struct GNUNET_DHTU_PluginEnvironment env;
+
+ /**
+ * Underlay API handle.
+ */
+ struct GNUNET_DHTU_PluginFunctions *dhtu;
+
+ /**
+ * current network size estimate for this underlay.
+ */
+ double network_size_estimate;
+
+ /**
+ * Name of the underlay (i.e. "gnunet" or "ip").
+ */
+ char *name;
+
+ /**
+ * Name of the library providing the underlay.
+ */
+ char *libname;
+};
+
+
+/**
+ * An address of this peer.
+ */
+struct MyAddress
+{
+ /**
+ * Kept in a DLL.
+ */
+ struct MyAddress *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct MyAddress *prev;
+
+ /**
+ * Underlay handle for the address.
+ */
+ struct GNUNET_DHTU_Source *source;
+
+ /**
+ * Textual representation of the address.
+ */
+ char *url;
+
+ /**
+ * Underlay of this address.
+ */
+ struct GDS_Underlay *u;
+};
+
+
+/**
* Our HELLO
*/
-struct GNUNET_MessageHeader *GDS_my_hello;
+struct GNUNET_HELLO_Builder *GDS_my_hello;
/**
- * Handle to get our current HELLO.
+ * Identity of this peer.
*/
-static struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
+struct GNUNET_PeerIdentity GDS_my_identity;
/**
- * Hello address expiration
+ * Hash of the identity of this peer.
*/
-struct GNUNET_TIME_Relative hello_expiration;
+struct GNUNET_HashCode GDS_my_identity_hash;
+
+/**
+ * Our private key.
+ */
+struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
+
+/**
+ * Task broadcasting our HELLO.
+ */
+static struct GNUNET_SCHEDULER_Task *hello_task;
+
+/**
+ * Handles for the DHT underlays.
+ */
+static struct GDS_Underlay *u_head;
+
+/**
+ * Handles for the DHT underlays.
+ */
+static struct GDS_Underlay *u_tail;
+
+/**
+ * Head of addresses of this peer.
+ */
+static struct MyAddress *a_head;
+
+/**
+ * Tail of addresses of this peer.
+ */
+static struct MyAddress *a_tail;
+
+/**
+ * log of the current network size estimate, used as the point where
+ * we switch between random and deterministic routing.
+ */
+static double log_of_network_size_estimate;
+
+
+/**
+ * Callback that is called when network size estimate is updated.
+ *
+ * @param cls a `struct GDS_Underlay`
+ * @param timestamp time when the estimate was received from the server (or created by the server)
+ * @param logestimate the log(Base 2) value of the current network size estimate
+ * @param std_dev standard deviation for the estimate
+ *
+ */
+static void
+update_network_size_estimate (void *cls,
+ struct GNUNET_TIME_Absolute timestamp,
+ double logestimate,
+ double std_dev)
+{
+ struct GDS_Underlay *u = cls;
+ double sum = 0.0;
+
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# Network size estimates received",
+ 1,
+ GNUNET_NO);
+ /* do not allow estimates < 0.5 */
+ u->network_size_estimate = pow (2.0,
+ GNUNET_MAX (0.5,
+ logestimate));
+ for (struct GDS_Underlay *p = u_head; NULL != p; p = p->next)
+ sum += p->network_size_estimate;
+ if (sum <= 2.0)
+ log_of_network_size_estimate = 0.5;
+ else
+ log_of_network_size_estimate = log2 (sum);
+}
+
+
+/**
+ * Return the current NSE
+ *
+ * @return the current NSE as a logarithm
+ */
+double
+GDS_NSE_get (void)
+{
+ return log_of_network_size_estimate;
+}
#include "gnunet-service-dht_clients.c"
/**
- * Receive the HELLO from transport service, free current and replace
- * if necessary.
+ * Task run periodically to broadcast our HELLO.
*
* @param cls NULL
- * @param message HELLO message of peer
*/
static void
-process_hello (void *cls,
- const struct GNUNET_MessageHeader *message)
+broadcast_hello (void *cls)
{
- GNUNET_free (GDS_my_hello);
- GDS_my_hello = GNUNET_malloc (ntohs (message->size));
- GNUNET_memcpy (GDS_my_hello,
- message,
- ntohs (message->size));
+ struct GNUNET_MessageHeader *hello;
+
+ (void) cls;
+ /* TODO: randomize! */
+ hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_FREQUENCY,
+ &broadcast_hello,
+ NULL);
+ hello = GNUNET_HELLO_builder_to_dht_hello_msg (GDS_my_hello,
+ &GDS_my_private_key);
+ if (NULL == hello)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GDS_NEIGHBOURS_broadcast (hello);
+ GNUNET_free (hello);
+}
+
+
+/**
+ * Function to call with new addresses of this peer.
+ *
+ * @param cls the closure
+ * @param address address under which we are likely reachable,
+ * pointer will remain valid until @e address_del_cb is called; to be used for HELLOs. Example: "ip+udp://$PID/1.1.1.1:2086/"
+ * @param source handle for sending from this address, NULL if we can only receive
+ * @param[out] ctx storage space for DHT to use in association with this address
+ */
+static void
+u_address_add (void *cls,
+ const char *address,
+ struct GNUNET_DHTU_Source *source,
+ void **ctx)
+{
+ struct GDS_Underlay *u = cls;
+ struct MyAddress *a;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Underlay adds address %s for this peer\n",
+ address);
+ a = GNUNET_new (struct MyAddress);
+ a->source = source;
+ a->url = GNUNET_strdup (address);
+ a->u = u;
+ GNUNET_CONTAINER_DLL_insert (a_head,
+ a_tail,
+ a);
+ *ctx = a;
+ GNUNET_HELLO_builder_add_address (GDS_my_hello,
+ address);
+ if (NULL != hello_task)
+ GNUNET_SCHEDULER_cancel (hello_task);
+ hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
+ NULL);
+}
+
+
+/**
+ * Function to call with expired addresses of this peer.
+ *
+ * @param[in] ctx storage space used by the DHT in association with this address
+ */
+static void
+u_address_del (void *ctx)
+{
+ struct MyAddress *a = ctx;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Underlay deletes address %s for this peer\n",
+ a->url);
+ GNUNET_HELLO_builder_del_address (GDS_my_hello,
+ a->url);
+ GNUNET_CONTAINER_DLL_remove (a_head,
+ a_tail,
+ a);
+ GNUNET_free (a->url);
+ GNUNET_free (a);
+ if (NULL != hello_task)
+ GNUNET_SCHEDULER_cancel (hello_task);
+ hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
+ NULL);
+}
+
+
+void
+GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
+ const char *address)
+{
+ for (struct GDS_Underlay *u = u_head;
+ NULL != u;
+ u = u->next)
+ u->dhtu->try_connect (u->dhtu->cls,
+ pid,
+ address);
+}
+
+
+void
+GDS_u_send (struct GDS_Underlay *u,
+ struct GNUNET_DHTU_Target *target,
+ const void *msg,
+ size_t msg_size,
+ GNUNET_SCHEDULER_TaskCallback finished_cb,
+ void *finished_cb_cls)
+{
+ u->dhtu->send (u->dhtu->cls,
+ target,
+ msg,
+ msg_size,
+ finished_cb,
+ finished_cb_cls);
+}
+
+
+void
+GDS_u_drop (struct GDS_Underlay *u,
+ struct GNUNET_DHTU_PreferenceHandle *ph)
+{
+ u->dhtu->drop (ph);
+}
+
+
+struct GNUNET_DHTU_PreferenceHandle *
+GDS_u_hold (struct GDS_Underlay *u,
+ struct GNUNET_DHTU_Target *target)
+{
+ return u->dhtu->hold (u->dhtu->cls,
+ target);
}
@@ -85,30 +367,97 @@ process_hello (void *cls,
static void
shutdown_task (void *cls)
{
- if (NULL != ghh)
+ struct GDS_Underlay *u;
+
+ while (NULL != (u = u_head))
{
- GNUNET_TRANSPORT_hello_get_cancel (ghh);
- ghh = NULL;
+ GNUNET_PLUGIN_unload (u->libname,
+ u->dhtu);
+ GNUNET_CONTAINER_DLL_remove (u_head,
+ u_tail,
+ u);
+ GNUNET_free (u->name);
+ GNUNET_free (u->libname);
+ GNUNET_free (u);
}
GDS_NEIGHBOURS_done ();
GDS_DATACACHE_done ();
GDS_ROUTING_done ();
- GDS_HELLO_done ();
- GDS_NSE_done ();
if (NULL != GDS_block_context)
{
GNUNET_BLOCK_context_destroy (GDS_block_context);
GDS_block_context = NULL;
}
+ GDS_CLIENTS_stop ();
if (NULL != GDS_stats)
{
GNUNET_STATISTICS_destroy (GDS_stats,
GNUNET_YES);
GDS_stats = NULL;
}
- GNUNET_free (GDS_my_hello);
- GDS_my_hello = NULL;
- GDS_CLIENTS_stop ();
+ if (NULL != GDS_my_hello)
+ {
+ GNUNET_HELLO_builder_free (GDS_my_hello);
+ GDS_my_hello = NULL;
+ }
+ if (NULL != hello_task)
+ {
+ GNUNET_SCHEDULER_cancel (hello_task);
+ hello_task = NULL;
+ }
+}
+
+
+/**
+ * Function iterating over all configuration sections.
+ * Loads plugins for enabled DHT underlays.
+ *
+ * @param cls NULL
+ * @param section configuration section to inspect
+ */
+static void
+load_underlay (void *cls,
+ const char *section)
+{
+ struct GDS_Underlay *u;
+ char *libname;
+
+ (void) cls;
+ if (0 != strncasecmp (section,
+ "dhtu-",
+ strlen ("dhtu-")))
+ return;
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg,
+ section,
+ "ENABLED"))
+ return;
+ section += strlen ("dhtu-");
+ u = GNUNET_new (struct GDS_Underlay);
+ u->env.cls = u;
+ u->env.cfg = GDS_cfg;
+ u->env.address_add_cb = &u_address_add;
+ u->env.address_del_cb = &u_address_del;
+ u->env.network_size_cb = &update_network_size_estimate;
+ u->env.connect_cb = &GDS_u_connect;
+ u->env.disconnect_cb = &GDS_u_disconnect;
+ u->env.receive_cb = &GDS_u_receive;
+ GNUNET_asprintf (&libname,
+ "libgnunet_plugin_dhtu_%s",
+ section);
+ u->dhtu = GNUNET_PLUGIN_load (libname,
+ &u->env);
+ if (NULL == u->dhtu)
+ {
+ GNUNET_free (libname);
+ GNUNET_free (u);
+ return;
+ }
+ u->libname = libname;
+ u->name = GNUNET_strdup (section);
+ GNUNET_CONTAINER_DLL_insert (u_head,
+ u_tail,
+ u);
}
@@ -126,34 +475,64 @@ run (void *cls,
{
GDS_cfg = c;
GDS_service = service;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c,
- "transport",
- "HELLO_EXPIRATION",
- &hello_expiration))
{
- hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
+ char *keyfile;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
+ "PEER",
+ "PRIVATE_KEY",
+ &keyfile))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "PEER",
+ "PRIVATE_KEY");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_SYSERR ==
+ GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
+ GNUNET_YES,
+ &GDS_my_private_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to setup peer's private key\n");
+ GNUNET_free (keyfile);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_free (keyfile);
}
+ GNUNET_CRYPTO_eddsa_key_get_public (&GDS_my_private_key,
+ &GDS_my_identity.public_key);
+ GDS_my_hello = GNUNET_HELLO_builder_new (&GDS_my_identity);
+ GNUNET_CRYPTO_hash (&GDS_my_identity,
+ sizeof(struct GNUNET_PeerIdentity),
+ &GDS_my_identity_hash);
GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
GDS_stats = GNUNET_STATISTICS_create ("dht",
GDS_cfg);
- GNUNET_SERVICE_suspend (GDS_service);
GDS_CLIENTS_init ();
GDS_ROUTING_init ();
- GDS_NSE_init ();
GDS_DATACACHE_init ();
- GDS_HELLO_init ();
- if (GNUNET_OK != GDS_NEIGHBOURS_init ())
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
+ if (GNUNET_OK !=
+ GDS_NEIGHBOURS_init ())
{
- shutdown_task (NULL);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_CONFIGURATION_iterate_sections (GDS_cfg,
+ &load_underlay,
+ NULL);
+ if (NULL == u_head)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No DHT underlays configured!\n");
+ GNUNET_SCHEDULER_shutdown ();
return;
}
- GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
- NULL);
- ghh = GNUNET_TRANSPORT_hello_get (GDS_cfg,
- GNUNET_TRANSPORT_AC_GLOBAL,
- &process_hello,
- NULL);
}
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index 6741efb4e..ecb79fa50 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -26,14 +26,20 @@
#ifndef GNUNET_SERVICE_DHT_H
#define GNUNET_SERVICE_DHT_H
-#include "gnunet_util_lib.h"
+#include "gnunet-service-dht_datacache.h"
+#include "gnunet-service-dht_neighbours.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
-#include "gnunet_block_lib.h"
+
#define DEBUG_DHT GNUNET_EXTRA_LOGGING
/**
+ * Information we keep per underlay.
+ */
+struct GDS_Underlay;
+
+/**
* Configuration we use.
*/
extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg;
@@ -54,9 +60,81 @@ extern struct GNUNET_BLOCK_Context *GDS_block_context;
extern struct GNUNET_STATISTICS_Handle *GDS_stats;
/**
- * Our HELLO
+ * Our HELLO builder.
+ */
+extern struct GNUNET_HELLO_Builder *GDS_my_hello;
+
+/**
+ * Identity of this peer.
+ */
+extern struct GNUNET_PeerIdentity GDS_my_identity;
+
+/**
+ * Hash of the identity of this peer.
+ */
+extern struct GNUNET_HashCode GDS_my_identity_hash;
+
+/**
+ * Our private key.
+ */
+extern struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
+
+
+/**
+ * Ask all underlays to connect to peer @a pid at @a address.
+ *
+ * @param pid identity of the peer we would connect to
+ * @param address an address of @a pid
+ */
+void
+GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
+ const char *address);
+
+
+/**
+ * Send message to some other participant over the network. Note that
+ * sending is not guaranteeing that the other peer actually received the
+ * message. For any given @a target, the DHT must wait for the @a
+ * finished_cb to be called before calling send() again.
+ *
+ * @param u underlay to use for transmission
+ * @param target receiver identification
+ * @param msg message
+ * @param msg_size number of bytes in @a msg
+ * @param finished_cb function called once transmission is done
+ * (not called if @a target disconnects, then only the
+ * disconnect_cb is called).
+ * @param finished_cb_cls closure for @a finished_cb
+ */
+void
+GDS_u_send (struct GDS_Underlay *u,
+ struct GNUNET_DHTU_Target *target,
+ const void *msg,
+ size_t msg_size,
+ GNUNET_SCHEDULER_TaskCallback finished_cb,
+ void *finished_cb_cls);
+
+
+/**
+ * Drop a hold @a ph from underlay @a u.
+ *
+ * @param u the underlay controlling the hold
+ * @param ph the preference handle
*/
-extern struct GNUNET_MessageHeader *GDS_my_hello;
+void
+GDS_u_drop (struct GDS_Underlay *u,
+ struct GNUNET_DHTU_PreferenceHandle *ph);
+
+
+/**
+ * Create a hold on @a target at underlay @a u.
+ *
+ * @param u the underlay controlling the target
+ * @param target the peer to hold the connection to
+ */
+struct GNUNET_DHTU_PreferenceHandle *
+GDS_u_hold (struct GDS_Underlay *u,
+ struct GNUNET_DHTU_Target *target);
/**
@@ -64,26 +142,18 @@ extern struct GNUNET_MessageHeader *GDS_my_hello;
* matches any of our pending queries, forward it to the respective
* client(s).
*
- * @param expiration when will the reply expire
- * @param key the query this reply is for
- * @param get_path_length number of peers in @a get_path
- * @param get_path path the reply took on get
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
- * @param type type of the reply
- * @param data_size number of bytes in @a data
- * @param data application payload data
+ * @param bd block details
+ * @param query_hash hash of the original query, might not match key in @a bd
+ * @param trunc_peer peer at which the path was truncated, or NULL if path starts at the origin
+ * @param get_path_length number of entries in @a get_path
+ * @param get_path path the reply has taken
+ * @return true on success, false on failures
*/
-void
-GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
- const struct GNUNET_HashCode *key,
+bool
+GDS_CLIENTS_handle_reply (const struct GNUNET_DATACACHE_Block *bd,
+ const struct GNUNET_HashCode *query_hash,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- enum GNUNET_BLOCK_Type type,
- size_t data_size,
- const void *data);
+ const struct GNUNET_DHT_PathElement *get_path);
/**
@@ -93,18 +163,14 @@ GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
* @param options Options, for instance RecordRoute, DemultiplexEverywhere.
* @param type The type of data in the request.
* @param hop_count Hop count so far.
- * @param path_length number of entries in path (or 0 if not recorded).
- * @param path peers on the GET path (or NULL if not recorded).
* @param desired_replication_level Desired replication level.
* @param key Key of the requested data.
*/
void
-GDS_CLIENTS_process_get (uint32_t options,
+GDS_CLIENTS_process_get (enum GNUNET_DHT_RouteOption options,
enum GNUNET_BLOCK_Type type,
uint32_t hop_count,
uint32_t desired_replication_level,
- unsigned int path_length,
- const struct GNUNET_PeerIdentity *path,
const struct GNUNET_HashCode *key);
@@ -112,53 +178,36 @@ GDS_CLIENTS_process_get (uint32_t options,
* Check if some client is monitoring GET RESP messages and notify
* them in that case.
*
- * @param type The type of data in the result.
+ * @param bd block details
* @param get_path Peers on GET path (or NULL if not recorded).
* @param get_path_length number of entries in @a get_path.
- * @param put_path peers on the PUT path (or NULL if not recorded).
- * @param put_path_length number of entries in @a get_path.
- * @param exp Expiration time of the data.
- * @param key Key of the @a data.
- * @param data Pointer to the result data.
- * @param size Number of bytes in @a data.
*/
void
-GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length,
- struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode *key,
- const void *data,
- size_t size);
+GDS_CLIENTS_process_get_resp (const struct GNUNET_DATACACHE_Block *bd,
+ const struct GNUNET_DHT_PathElement *get_path,
+ unsigned int get_path_length);
/**
* Check if some client is monitoring PUT messages and notify
- * them in that case.
+ * them in that case. The @a path should include our own
+ * peer ID (if recorded).
*
- * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
- * @param type The type of data in the request.
+ * @param bd details about the block
* @param hop_count Hop count so far.
- * @param path_length number of entries in path (or 0 if not recorded).
- * @param path peers on the PUT path (or NULL if not recorded).
* @param desired_replication_level Desired replication level.
- * @param exp Expiration time of the data.
- * @param key Key under which data is to be stored.
- * @param data Pointer to the data carried.
- * @param size Number of bytes in data.
*/
void
-GDS_CLIENTS_process_put (uint32_t options,
- enum GNUNET_BLOCK_Type type,
+GDS_CLIENTS_process_put (const struct GNUNET_DATACACHE_Block *bd,
uint32_t hop_count,
- uint32_t desired_replication_level,
- unsigned int path_length,
- const struct GNUNET_PeerIdentity *path,
- struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode *key,
- const void *data,
- size_t size);
+ uint32_t desired_replication_level);
+
+/**
+ * Return the current NSE
+ *
+ * @return the current NSE as a logarithm
+ */
+double
+GDS_NSE_get (void);
#endif
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index cfcb25336..fdcc31f13 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009, 2010, 2011, 2016, 2017 GNUnet e.V.
+ Copyright (C) 2009, 2010, 2011, 2016, 2017, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -24,7 +24,6 @@
* @author Christian Grothoff
* @author Nathan Evans
*/
-
#include "platform.h"
#include "gnunet_constants.h"
#include "gnunet_protocols.h"
@@ -36,6 +35,14 @@
/**
+ * Enable slow sanity checks to debug issues.
+ * 0: do not check
+ * 1: check all external inputs
+ * 2: check internal computations as well
+ */
+#define SANITY_CHECKS 2
+
+/**
* Should routing details be logged to stderr (for debugging)?
*/
#define LOG_TRAFFIC(kind, ...) GNUNET_log_from (kind, "dht-traffic", \
@@ -83,7 +90,7 @@ struct ClientQueryRecord
const void *xquery;
/**
- * Replies we have already seen for this request.
+ * Array of (hashes of) replies we have already seen for this request.
*/
struct GNUNET_HashCode *seen_replies;
@@ -114,7 +121,7 @@ struct ClientQueryRecord
size_t xquery_size;
/**
- * Number of entries in 'seen_replies'.
+ * Number of entries in @e seen_replies.
*/
unsigned int seen_replies_count;
@@ -126,7 +133,7 @@ struct ClientQueryRecord
/**
* Any message options for this request
*/
- uint32_t msg_options;
+ enum GNUNET_DHT_RouteOption msg_options;
/**
* The type for the data for the GET request.
@@ -151,14 +158,19 @@ struct ClientMonitorRecord
struct ClientMonitorRecord *prev;
/**
- * Type of blocks that are of interest
+ * Client to notify of these requests.
*/
- enum GNUNET_BLOCK_Type type;
+ struct ClientHandle *ch;
+
+ /**
+ * Key of data of interest. All bits zero for 'all'.
+ */
+ struct GNUNET_HashCode key;
/**
- * Key of data of interest, NULL for all.
+ * Type of blocks that are of interest
*/
- struct GNUNET_HashCode *key;
+ enum GNUNET_BLOCK_Type type;
/**
* Flag whether to notify about GET messages.
@@ -175,10 +187,6 @@ struct ClientMonitorRecord
*/
uint16_t put;
- /**
- * Client to notify of these requests.
- */
- struct ClientHandle *ch;
};
@@ -210,6 +218,7 @@ struct ClientHandle
struct GNUNET_MQ_Handle *mq;
};
+
/**
* Our handle to the BLOCK library.
*/
@@ -262,7 +271,7 @@ static struct GNUNET_SCHEDULER_Task *retry_task;
* @param record record to remove
*/
static void
-remove_client_record (struct ClientQueryRecord *record)
+remove_client_query_record (struct ClientQueryRecord *record)
{
struct ClientHandle *ch = record->ch;
@@ -298,6 +307,7 @@ client_connect_cb (void *cls,
{
struct ClientHandle *ch;
+ (void) cls;
ch = GNUNET_new (struct ClientHandle);
ch->client = client;
ch->mq = mq;
@@ -319,34 +329,35 @@ client_disconnect_cb (void *cls,
void *app_ctx)
{
struct ClientHandle *ch = app_ctx;
- struct ClientQueryRecord *cqr;
- struct ClientMonitorRecord *monitor;
+ (void) cls;
+ (void) client;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Local client %p disconnects\n",
ch);
- monitor = monitor_head;
- while (NULL != monitor)
{
- if (monitor->ch == ch)
- {
- struct ClientMonitorRecord *next;
+ struct ClientMonitorRecord *next;
+ for (struct ClientMonitorRecord *monitor = monitor_head;
+ NULL != monitor;
+ monitor = next)
+ {
next = monitor->next;
- GNUNET_free (monitor->key);
+ if (monitor->ch != ch)
+ continue;
GNUNET_CONTAINER_DLL_remove (monitor_head,
monitor_tail,
monitor);
GNUNET_free (monitor);
- monitor = next;
- }
- else
- {
- monitor = monitor->next;
}
}
- while (NULL != (cqr = ch->cqr_head))
- remove_client_record (cqr);
+
+ {
+ struct ClientQueryRecord *cqr;
+
+ while (NULL != (cqr = ch->cqr_head))
+ remove_client_query_record (cqr);
+ }
GNUNET_free (ch);
}
@@ -355,6 +366,8 @@ client_disconnect_cb (void *cls,
* Route the given request via the DHT. This includes updating
* the bloom filter and retransmission times, building the P2P
* message and initiating the routing operation.
+ *
+ * @param cqr request to transmit
*/
static void
transmit_request (struct ClientQueryRecord *cqr)
@@ -363,17 +376,13 @@ transmit_request (struct ClientQueryRecord *cqr)
struct GNUNET_CONTAINER_BloomFilter *peer_bf;
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# GET requests from clients injected"),
+ "# GET requests from clients injected",
1,
GNUNET_NO);
bg = GNUNET_BLOCK_group_create (GDS_block_context,
cqr->type,
- GNUNET_CRYPTO_random_u32 (
- GNUNET_CRYPTO_QUALITY_WEAK,
- UINT32_MAX),
- NULL,
- 0,
+ NULL, /* raw data */
+ 0, /* raw data size */
"seen-set-size",
cqr->seen_replies_count,
NULL);
@@ -401,8 +410,8 @@ transmit_request (struct ClientQueryRecord *cqr)
GNUNET_BLOCK_group_destroy (bg);
GNUNET_CONTAINER_bloomfilter_free (peer_bf);
- /* exponential back-off for retries.
- * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */
+ /* Exponential back-off for retries.
+ * max. is #GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */
cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency);
cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency);
}
@@ -419,14 +428,13 @@ static void
transmit_next_request_task (void *cls)
{
struct ClientQueryRecord *cqr;
- struct GNUNET_TIME_Relative delay;
+ (void) cls;
retry_task = NULL;
while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap)))
{
cqr->hnode = NULL;
- delay = GNUNET_TIME_absolute_get_remaining (cqr->retry_time);
- if (delay.rel_value_us > 0)
+ if (! GNUNET_TIME_absolute_is_past (cqr->retry_time))
{
cqr->hnode
= GNUNET_CONTAINER_heap_insert (retry_heap,
@@ -454,11 +462,18 @@ transmit_next_request_task (void *cls)
* @param dht_msg the actual message received
* @return #GNUNET_OK (always)
*/
-static int
+static enum GNUNET_GenericReturnValue
check_dht_local_put (void *cls,
const struct GNUNET_DHT_ClientPutMessage *dht_msg)
{
- /* always well-formed */
+ uint32_t replication_level = ntohl (dht_msg->desired_replication_level);
+
+ (void) cls;
+ if (replication_level > GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
return GNUNET_OK;
}
@@ -474,125 +489,116 @@ handle_dht_local_put (void *cls,
const struct GNUNET_DHT_ClientPutMessage *dht_msg)
{
struct ClientHandle *ch = cls;
- struct GNUNET_CONTAINER_BloomFilter *peer_bf;
- uint16_t size;
+ uint16_t size = ntohs (dht_msg->header.size);
+ uint32_t replication_level
+ = ntohl (dht_msg->desired_replication_level);
+ struct GNUNET_DATACACHE_Block bd = {
+ .key = dht_msg->key,
+ .expiration_time = GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
+ .data = &dht_msg[1],
+ .data_size = size - sizeof (*dht_msg),
+ .type = ntohl (dht_msg->type),
+ .ro = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options)
+ };
- size = ntohs (dht_msg->header.size);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Handling local PUT of %lu-bytes for query %s of type %u\n",
+ (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
+ GNUNET_h2s (&dht_msg->key),
+ (unsigned int) bd.type);
+ if (GNUNET_OK !=
+ GNUNET_BLOCK_check_block (GDS_block_context,
+ bd.type,
+ bd.data,
+ bd.data_size))
+ {
+ GNUNET_break (0);
+ return;
+ }
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# PUT requests received from clients"),
+ "# PUT requests received from clients",
1,
GNUNET_NO);
LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
"CLIENT-PUT %s\n",
GNUNET_h2s_full (&dht_msg->key));
/* give to local clients */
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Handling local PUT of %lu-bytes for query %s\n",
- (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
- GNUNET_h2s (&dht_msg->key));
- GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
- &dht_msg->key,
- 0,
- NULL,
- 0,
- NULL,
- ntohl (dht_msg->type),
- size - sizeof(struct GNUNET_DHT_ClientPutMessage),
- &dht_msg[1]);
- /* store locally */
- GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
- &dht_msg->key,
- 0,
- NULL,
- ntohl (dht_msg->type),
- size - sizeof(struct GNUNET_DHT_ClientPutMessage),
- &dht_msg[1]);
- /* route to other peers */
- peer_bf
- = GNUNET_CONTAINER_bloomfilter_init (NULL,
- DHT_BLOOM_SIZE,
- GNUNET_CONSTANTS_BLOOMFILTER_K);
- GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type),
- ntohl (dht_msg->options),
- ntohl (dht_msg->desired_replication_level),
- GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
- 0 /* hop count */,
- peer_bf,
- &dht_msg->key,
- 0,
- NULL,
- &dht_msg[1],
- size - sizeof(struct GNUNET_DHT_ClientPutMessage));
- GDS_CLIENTS_process_put (ntohl (dht_msg->options),
- ntohl (dht_msg->type),
- 0,
- ntohl (dht_msg->desired_replication_level),
- 1,
- GDS_NEIGHBOURS_get_id (),
- GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
- &dht_msg->key,
- &dht_msg[1],
- size - sizeof(struct GNUNET_DHT_ClientPutMessage));
- GNUNET_CONTAINER_bloomfilter_free (peer_bf);
+ GNUNET_break (GDS_CLIENTS_handle_reply (&bd,
+ &bd.key,
+ 0, NULL /* get path */));
+
+ {
+ struct GNUNET_CONTAINER_BloomFilter *peer_bf;
+
+ peer_bf
+ = GNUNET_CONTAINER_bloomfilter_init (NULL,
+ DHT_BLOOM_SIZE,
+ GNUNET_CONSTANTS_BLOOMFILTER_K);
+ /* store locally */
+ if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+ (GDS_am_closest_peer (&dht_msg->key,
+ peer_bf)))
+ GDS_DATACACHE_handle_put (&bd);
+ /* route to other peers */
+ if (GNUNET_OK !=
+ GDS_NEIGHBOURS_handle_put (&bd,
+ replication_level,
+ 0 /* hop count */,
+ peer_bf))
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# Local PUT requests not routed",
+ 1,
+ GNUNET_NO);
+ }
+ GNUNET_CONTAINER_bloomfilter_free (peer_bf);
+ }
+ GDS_CLIENTS_process_put (
+ &bd,
+ 0, /* hop count */
+ replication_level);
GNUNET_SERVICE_client_continue (ch->client);
}
/**
+ * Handle a result from local datacache for a GET operation.
+ *
+ * @param cls the `struct ClientHandle` of the client doing the query
+ * @param bd details about the block that was found
+ */
+static void
+handle_local_result (void *cls,
+ const struct GNUNET_DATACACHE_Block *bd)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Datacache provided result for query key %s\n",
+ GNUNET_h2s (&bd->key));
+ GNUNET_break (GDS_CLIENTS_handle_reply (bd,
+ &bd->key,
+ 0, NULL /* get_path */));
+}
+
+
+/**
* Check DHT GET messages from the client.
*
* @param cls the client we received this message from
* @param message the actual message received
* @return #GNUNET_OK (always)
*/
-static int
+static enum GNUNET_GenericReturnValue
check_dht_local_get (void *cls,
const struct GNUNET_DHT_ClientGetMessage *get)
{
+ (void) cls;
+ (void) get;
/* always well-formed */
return GNUNET_OK;
}
/**
- * Handle a result from local datacache for a GET operation.
- *
- * @param cls the `struct ClientHandle` of the client doing the query
- * @param type type of the block
- * @param expiration_time when does the content expire
- * @param key key for the content
- * @param put_path_length number of entries in @a put_path
- * @param put_path peers the original PUT traversed (if tracked)
- * @param get_path_length number of entries in @a get_path
- * @param get_path peers this reply has traversed so far (if tracked)
- * @param data payload of the reply
- * @param data_size number of bytes in @a data
- */
-static void
-handle_local_result (void *cls,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute expiration_time,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- const void *data,
- size_t data_size)
-{
- // FIXME: this needs some clean up: inline the function,
- // possibly avoid even looking up the client!
- GDS_CLIENTS_handle_reply (expiration_time,
- key,
- 0, NULL,
- put_path_length, put_path,
- type,
- data_size, data);
-}
-
-
-/**
* Handler for DHT GET messages from the client.
*
* @param cls the client we received this message from
@@ -604,23 +610,20 @@ handle_dht_local_get (void *cls,
{
struct ClientHandle *ch = cls;
struct ClientQueryRecord *cqr;
- size_t xquery_size;
- const char *xquery;
- uint16_t size;
+ uint16_t size = ntohs (get->header.size);
+ const char *xquery = (const char *) &get[1];
+ size_t xquery_size = size - sizeof(struct GNUNET_DHT_ClientGetMessage);
- size = ntohs (get->header.size);
- xquery_size = size - sizeof(struct GNUNET_DHT_ClientGetMessage);
- xquery = (const char *) &get[1];
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- ("# GET requests received from clients"), 1,
- GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received GET request for %s from local client %p, xq: %.*s\n",
GNUNET_h2s (&get->key),
ch->client,
(int) xquery_size,
xquery);
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# GET requests received from clients",
+ 1,
+ GNUNET_NO);
LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
"CLIENT-GET %s\n",
GNUNET_h2s_full (&get->key));
@@ -628,15 +631,19 @@ handle_dht_local_get (void *cls,
cqr = GNUNET_malloc (sizeof(struct ClientQueryRecord) + xquery_size);
cqr->key = get->key;
cqr->ch = ch;
- cqr->xquery = (void *) &cqr[1];
- GNUNET_memcpy (&cqr[1], xquery, xquery_size);
- cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0);
+ cqr->xquery = (const void *) &cqr[1];
+ GNUNET_memcpy (&cqr[1],
+ xquery,
+ xquery_size);
+ cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap,
+ cqr,
+ 0);
cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS;
cqr->retry_time = GNUNET_TIME_absolute_get ();
cqr->unique_id = get->unique_id;
cqr->xquery_size = xquery_size;
cqr->replication = ntohl (get->desired_replication_level);
- cqr->msg_options = ntohl (get->options);
+ cqr->msg_options = (enum GNUNET_DHT_RouteOption) ntohl (get->options);
cqr->type = ntohl (get->type);
GNUNET_CONTAINER_DLL_insert (ch->cqr_head,
ch->cqr_tail,
@@ -645,12 +652,10 @@ handle_dht_local_get (void *cls,
&cqr->key,
cqr,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- GDS_CLIENTS_process_get (ntohl (get->options),
- ntohl (get->type),
- 0,
- ntohl (get->desired_replication_level),
- 1,
- GDS_NEIGHBOURS_get_id (),
+ GDS_CLIENTS_process_get (cqr->msg_options,
+ cqr->type,
+ 0, /* hop count */
+ cqr->replication,
&get->key);
/* start remote requests */
if (NULL != retry_task)
@@ -679,6 +684,9 @@ struct FindByUniqueIdContext
*/
struct ClientQueryRecord *cqr;
+ /**
+ * Unique ID to look for.
+ */
uint64_t unique_id;
};
@@ -693,7 +701,7 @@ struct FindByUniqueIdContext
* @param value the `struct ClientQueryRecord`
* @return #GNUNET_YES to continue iteration (result not yet found)
*/
-static int
+static enum GNUNET_GenericReturnValue
find_by_unique_id (void *cls,
const struct GNUNET_HashCode *key,
void *value)
@@ -715,19 +723,17 @@ find_by_unique_id (void *cls,
* @param message the actual message received
* @return #GNUNET_OK if @a seen is well-formed
*/
-static int
-check_dht_local_get_result_seen (void *cls,
- const struct
- GNUNET_DHT_ClientGetResultSeenMessage *seen)
+static enum GNUNET_GenericReturnValue
+check_dht_local_get_result_seen (
+ void *cls,
+ const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
{
- uint16_t size;
- unsigned int hash_count;
-
- size = ntohs (seen->header.size);
- hash_count = (size - sizeof(struct GNUNET_DHT_ClientGetResultSeenMessage))
- / sizeof(struct GNUNET_HashCode);
- if (size != sizeof(struct GNUNET_DHT_ClientGetResultSeenMessage)
- + hash_count * sizeof(struct GNUNET_HashCode))
+ uint16_t size = ntohs (seen->header.size);
+ unsigned int hash_count =
+ (size - sizeof(*seen))
+ / sizeof(struct GNUNET_HashCode);
+
+ if (size != sizeof(*seen) + hash_count * sizeof(struct GNUNET_HashCode))
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -743,24 +749,21 @@ check_dht_local_get_result_seen (void *cls,
* @param message the actual message received
*/
static void
-handle_dht_local_get_result_seen (void *cls,
- const struct
- GNUNET_DHT_ClientGetResultSeenMessage *seen)
+handle_dht_local_get_result_seen (
+ void *cls,
+ const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
{
struct ClientHandle *ch = cls;
- uint16_t size;
- unsigned int hash_count;
+ uint16_t size = ntohs (seen->header.size);
+ unsigned int hash_count = (size - sizeof(*seen))
+ / sizeof(struct GNUNET_HashCode);
+ const struct GNUNET_HashCode *hc = (const struct GNUNET_HashCode*) &seen[1];
+ struct FindByUniqueIdContext fui_ctx = {
+ .unique_id = seen->unique_id
+ };
unsigned int old_count;
- const struct GNUNET_HashCode *hc;
- struct FindByUniqueIdContext fui_ctx;
struct ClientQueryRecord *cqr;
- size = ntohs (seen->header.size);
- hash_count = (size - sizeof(struct GNUNET_DHT_ClientGetResultSeenMessage))
- / sizeof(struct GNUNET_HashCode);
- hc = (const struct GNUNET_HashCode*) &seen[1];
- fui_ctx.unique_id = seen->unique_id;
- fui_ctx.cqr = NULL;
GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
&seen->key,
&find_by_unique_id,
@@ -808,7 +811,7 @@ struct RemoveByUniqueIdContext
* @param value value in the hash map, a ClientQueryRecord
* @return #GNUNET_YES (we should continue to iterate)
*/
-static int
+static enum GNUNET_GenericReturnValue
remove_by_unique_id (void *cls,
const struct GNUNET_HashCode *key,
void *value)
@@ -822,7 +825,7 @@ remove_by_unique_id (void *cls,
"Removing client %p's record for key %s (by unique id)\n",
ctx->ch->client,
GNUNET_h2s (key));
- remove_client_record (cqr);
+ remove_client_query_record (cqr);
return GNUNET_YES;
}
@@ -836,16 +839,16 @@ remove_by_unique_id (void *cls,
*
*/
static void
-handle_dht_local_get_stop (void *cls,
- const struct
- GNUNET_DHT_ClientGetStopMessage *dht_stop_msg)
+handle_dht_local_get_stop (
+ void *cls,
+ const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg)
{
struct ClientHandle *ch = cls;
struct RemoveByUniqueIdContext ctx;
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- ("# GET STOP requests received from clients"), 1,
+ "# GET STOP requests received from clients",
+ 1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received GET STOP request for %s from local client %p\n",
@@ -862,134 +865,25 @@ handle_dht_local_get_stop (void *cls,
/**
- * Handler for monitor start messages
- *
- * @param cls the client we received this message from
- * @param msg the actual message received
- *
- */
-static void
-handle_dht_local_monitor (void *cls,
- const struct GNUNET_DHT_MonitorStartStopMessage *msg)
-{
- struct ClientHandle *ch = cls;
- struct ClientMonitorRecord *r;
-
- r = GNUNET_new (struct ClientMonitorRecord);
- r->ch = ch;
- r->type = ntohl (msg->type);
- r->get = ntohs (msg->get);
- r->get_resp = ntohs (msg->get_resp);
- r->put = ntohs (msg->put);
- if (0 == ntohs (msg->filter_key))
- {
- r->key = NULL;
- }
- else
- {
- r->key = GNUNET_new (struct GNUNET_HashCode);
- GNUNET_memcpy (r->key,
- &msg->key,
- sizeof(struct GNUNET_HashCode));
- }
- GNUNET_CONTAINER_DLL_insert (monitor_head,
- monitor_tail,
- r);
- GNUNET_SERVICE_client_continue (ch->client);
-}
-
-
-/**
- * Handler for monitor stop messages
- *
- * @param cls the client we received this message from
- * @param msg the actual message received
- */
-static void
-handle_dht_local_monitor_stop (void *cls,
- const struct
- GNUNET_DHT_MonitorStartStopMessage *msg)
-{
- struct ClientHandle *ch = cls;
- struct ClientMonitorRecord *r;
- int keys_match;
-
- GNUNET_SERVICE_client_continue (ch->client);
- for (r = monitor_head; NULL != r; r = r->next)
- {
- if (NULL == r->key)
- {
- keys_match = (0 == ntohs (msg->filter_key));
- }
- else
- {
- keys_match = ((0 != ntohs (msg->filter_key)) &&
- (! memcmp (r->key,
- &msg->key,
- sizeof(struct GNUNET_HashCode))));
- }
- if ((ch == r->ch) &&
- (ntohl (msg->type) == r->type) &&
- (r->get == msg->get) &&
- (r->get_resp == msg->get_resp) &&
- (r->put == msg->put) &&
- keys_match)
- {
- GNUNET_CONTAINER_DLL_remove (monitor_head,
- monitor_tail,
- r);
- GNUNET_free (r->key);
- GNUNET_free (r);
- return; /* Delete only ONE entry */
- }
- }
-}
-
-
-/**
* Closure for #forward_reply()
*/
struct ForwardReplyContext
{
/**
- * Expiration time of the reply.
+ * Block details.
*/
- struct GNUNET_TIME_Absolute expiration;
+ const struct GNUNET_DATACACHE_Block *bd;
/**
* GET path taken.
*/
- const struct GNUNET_PeerIdentity *get_path;
-
- /**
- * PUT path taken.
- */
- const struct GNUNET_PeerIdentity *put_path;
-
- /**
- * Embedded payload.
- */
- const void *data;
-
- /**
- * Number of bytes in data.
- */
- size_t data_size;
+ const struct GNUNET_DHT_PathElement *get_path;
/**
* Number of entries in @e get_path.
*/
unsigned int get_path_length;
- /**
- * Number of entries in @e put_path.
- */
- unsigned int put_path_length;
-
- /**
- * Type of the data.
- */
- enum GNUNET_BLOCK_Type type;
};
@@ -998,464 +892,716 @@ struct ForwardReplyContext
* each of the matching clients. With some tricky recycling
* of the buffer.
*
- * @param cls the 'struct ForwardReplyContext'
- * @param key current key
+ * @param cls the `struct ForwardReplyContext`
+ * @param query_hash hash of the query for which this may be a reply
* @param value value in the hash map, a ClientQueryRecord
* @return #GNUNET_YES (we should continue to iterate),
* if the result is mal-formed, #GNUNET_NO
*/
-static int
+static enum GNUNET_GenericReturnValue
forward_reply (void *cls,
- const struct GNUNET_HashCode *key,
+ const struct GNUNET_HashCode *query_hash,
void *value)
{
struct ForwardReplyContext *frc = cls;
struct ClientQueryRecord *record = value;
+ const struct GNUNET_DATACACHE_Block *bd = frc->bd;
struct GNUNET_MQ_Envelope *env;
struct GNUNET_DHT_ClientResultMessage *reply;
- enum GNUNET_BLOCK_EvaluationResult eval;
- int do_free;
+ enum GNUNET_BLOCK_ReplyEvaluationResult eval;
+ bool do_free;
struct GNUNET_HashCode ch;
- struct GNUNET_PeerIdentity *paths;
+ struct GNUNET_DHT_PathElement *paths;
+ bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
+ size_t xsize = bd->data_size;
LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
"CLIENT-RESULT %s\n",
- GNUNET_h2s_full (key));
- if ((record->type != GNUNET_BLOCK_TYPE_ANY) &&
- (record->type != frc->type))
+ GNUNET_h2s_full (&frc->bd->key));
+ if ( (record->type != GNUNET_BLOCK_TYPE_ANY) &&
+ (record->type != frc->bd->type) )
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Record type mismatch, not passing request for key %s to local client\n",
- GNUNET_h2s (key));
+ GNUNET_h2s (&frc->bd->key));
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- (
- "# Key match, type mismatches in REPLY to CLIENT"),
- 1, GNUNET_NO);
+ "# Key match, type mismatches in REPLY to CLIENT",
+ 1,
+ GNUNET_NO);
return GNUNET_YES; /* type mismatch */
}
- GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch);
+ if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
+ (0 != GNUNET_memcmp (&frc->bd->key,
+ query_hash)) )
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# Inexact key match, but exact match required",
+ 1,
+ GNUNET_NO);
+ return GNUNET_YES; /* type mismatch */
+ }
+ GNUNET_CRYPTO_hash (frc->bd->data,
+ frc->bd->data_size,
+ &ch);
for (unsigned int i = 0; i < record->seen_replies_count; i++)
- if (0 == memcmp (&record->seen_replies[i],
- &ch,
- sizeof(struct GNUNET_HashCode)))
+ if (0 ==
+ GNUNET_memcmp (&record->seen_replies[i],
+ &ch))
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Duplicate reply, not passing request for key %s to local client\n",
- GNUNET_h2s (key));
+ GNUNET_h2s (&frc->bd->key));
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- (
- "# Duplicate REPLIES to CLIENT request dropped"),
- 1, GNUNET_NO);
+ "# Duplicate REPLIES to CLIENT request dropped",
+ 1,
+ GNUNET_NO);
return GNUNET_YES; /* duplicate */
}
eval
- = GNUNET_BLOCK_evaluate (GDS_block_context,
- record->type,
- NULL,
- GNUNET_BLOCK_EO_NONE,
- key,
- record->xquery,
- record->xquery_size,
- frc->data,
- frc->data_size);
+ = GNUNET_BLOCK_check_reply (GDS_block_context,
+ record->type,
+ NULL,
+ &frc->bd->key,
+ record->xquery,
+ record->xquery_size,
+ frc->bd->data,
+ frc->bd->data_size);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Evaluation result is %d for key %s for local client's query\n",
(int) eval,
- GNUNET_h2s (key));
+ GNUNET_h2s (&frc->bd->key));
switch (eval)
{
- case GNUNET_BLOCK_EVALUATION_OK_LAST:
- do_free = GNUNET_YES;
+ case GNUNET_BLOCK_REPLY_OK_LAST:
+ do_free = true;
break;
-
- case GNUNET_BLOCK_EVALUATION_OK_MORE:
+ case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
+ case GNUNET_BLOCK_REPLY_OK_MORE:
GNUNET_array_append (record->seen_replies,
record->seen_replies_count,
ch);
- do_free = GNUNET_NO;
+ do_free = false;
break;
-
- case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
+ case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
/* should be impossible to encounter here */
GNUNET_break (0);
return GNUNET_YES;
-
- case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
- GNUNET_break_op (0);
- return GNUNET_NO;
-
- case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
- GNUNET_break (0);
- return GNUNET_NO;
-
- case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
- GNUNET_break (0);
- return GNUNET_NO;
-
- case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
+ case GNUNET_BLOCK_REPLY_IRRELEVANT:
return GNUNET_YES;
-
- case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _ ("Unsupported block type (%u) in request!\n"), record->type);
- return GNUNET_NO;
-
default:
GNUNET_break (0);
return GNUNET_NO;
}
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# RESULTS queued for clients"),
+ "# RESULTS queued for clients",
1,
GNUNET_NO);
+ xsize += (frc->get_path_length + frc->bd->put_path_length)
+ * sizeof(struct GNUNET_DHT_PathElement);
+ if (truncated)
+ xsize += sizeof (struct GNUNET_PeerIdentity);
env = GNUNET_MQ_msg_extra (reply,
- frc->data_size
- + (frc->get_path_length + frc->put_path_length)
- * sizeof(struct GNUNET_PeerIdentity),
+ xsize,
GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT);
- reply->type = htonl (frc->type);
+ reply->type = htonl (frc->bd->type);
+ reply->options = htonl (bd->ro);
reply->get_path_length = htonl (frc->get_path_length);
- reply->put_path_length = htonl (frc->put_path_length);
+ reply->put_path_length = htonl (frc->bd->put_path_length);
reply->unique_id = record->unique_id;
- reply->expiration = GNUNET_TIME_absolute_hton (frc->expiration);
- reply->key = *key;
- paths = (struct GNUNET_PeerIdentity *) &reply[1];
+ reply->expiration = GNUNET_TIME_absolute_hton (frc->bd->expiration_time);
+ reply->key = *query_hash;
+ if (truncated)
+ {
+ void *tgt = &reply[1];
+
+ GNUNET_memcpy (tgt,
+ &bd->trunc_peer,
+ sizeof (struct GNUNET_PeerIdentity));
+ paths = (struct GNUNET_DHT_PathElement *)
+ (tgt + sizeof (struct GNUNET_PeerIdentity));
+ }
+ else
+ {
+ paths = (struct GNUNET_DHT_PathElement *) &reply[1];
+ }
GNUNET_memcpy (paths,
- frc->put_path,
- sizeof(struct GNUNET_PeerIdentity) * frc->put_path_length);
- GNUNET_memcpy (&paths[frc->put_path_length],
+ frc->bd->put_path,
+ sizeof(struct GNUNET_DHT_PathElement)
+ * frc->bd->put_path_length);
+ GNUNET_memcpy (&paths[frc->bd->put_path_length],
frc->get_path,
- sizeof(struct GNUNET_PeerIdentity) * frc->get_path_length);
- GNUNET_memcpy (&paths[frc->get_path_length + frc->put_path_length],
- frc->data,
- frc->data_size);
+ sizeof(struct GNUNET_DHT_PathElement)
+ * frc->get_path_length);
+ GNUNET_memcpy (&paths[frc->get_path_length + frc->bd->put_path_length],
+ frc->bd->data,
+ frc->bd->data_size);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Sending reply to query %s for client %p\n",
- GNUNET_h2s (key),
+ GNUNET_h2s (query_hash),
record->ch->client);
GNUNET_MQ_send (record->ch->mq,
env);
if (GNUNET_YES == do_free)
- remove_client_record (record);
+ remove_client_query_record (record);
return GNUNET_YES;
}
-/**
- * Handle a reply we've received from another peer. If the reply
- * matches any of our pending queries, forward it to the respective
- * client(s).
- *
- * @param expiration when will the reply expire
- * @param key the query this reply is for
- * @param get_path_length number of peers in @a get_path
- * @param get_path path the reply took on get
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
- * @param type type of the reply
- * @param data_size number of bytes in @a data
- * @param data application payload data
- */
-void
-GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
- const struct GNUNET_HashCode *key,
+bool
+GDS_CLIENTS_handle_reply (const struct GNUNET_DATACACHE_Block *bd,
+ const struct GNUNET_HashCode *query_hash,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- enum GNUNET_BLOCK_Type type,
- size_t data_size,
- const void *data)
+ const struct GNUNET_DHT_PathElement *get_path)
{
struct ForwardReplyContext frc;
- size_t msize;
+ size_t msize = sizeof (struct GNUNET_DHT_ClientResultMessage)
+ + bd->data_size
+ + (get_path_length + bd->put_path_length)
+ * sizeof(struct GNUNET_DHT_PathElement);
+ bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
- msize = sizeof(struct GNUNET_DHT_ClientResultMessage) + data_size
- + (get_path_length + put_path_length) * sizeof(struct
- GNUNET_PeerIdentity);
if (msize >= GNUNET_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
- return;
+ return false;
+ }
+#if SANITY_CHECKS > 1
+ if (0 !=
+ GNUNET_DHT_verify_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ truncated
+ ? &bd->trunc_peer
+ : NULL,
+ bd->put_path,
+ bd->put_path_length,
+ get_path,
+ get_path_length,
+ &GDS_my_identity))
+ {
+ GNUNET_break (0);
+ return false;
}
- if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map,
- key))
+#endif
+ frc.bd = bd;
+ frc.get_path = get_path;
+ frc.get_path_length = get_path_length;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Forwarding reply for query hash %s with GPL %u and PPL %u to client\n",
+ GNUNET_h2s (query_hash),
+ get_path_length,
+ bd->put_path_length);
+ if (0 ==
+ GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
+ query_hash,
+ &forward_reply,
+ &frc))
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "No matching client for reply for key %s\n",
- GNUNET_h2s (key));
+ "No matching client for reply for query %s\n",
+ GNUNET_h2s (query_hash));
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# REPLIES ignored for CLIENTS (no match)"),
+ "# REPLIES ignored for CLIENTS (no match)",
1,
GNUNET_NO);
- return; /* no matching request, fast exit! */
}
- frc.expiration = expiration;
- frc.get_path = get_path;
- frc.put_path = put_path;
- frc.data = data;
- frc.data_size = data_size;
- frc.get_path_length = get_path_length;
- frc.put_path_length = put_path_length;
- frc.type = type;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Forwarding reply for key %s to client\n",
- GNUNET_h2s (key));
- GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
- key,
- &forward_reply,
- &frc);
+ return true;
}
+/* **************** HELLO logic ***************** */
+
/**
- * Check if some client is monitoring GET messages and notify
- * them in that case.
+ * Handler for HELLO GET message. Reply to client
+ * with a URL of our HELLO.
+ *
+ * @param cls the client we received this message from
+ * @param msg the actual message received
*
- * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
- * @param type The type of data in the request.
- * @param hop_count Hop count so far.
- * @param path_length number of entries in path (or 0 if not recorded).
- * @param path peers on the GET path (or NULL if not recorded).
- * @param desired_replication_level Desired replication level.
- * @param key Key of the requested data.
*/
-void
-GDS_CLIENTS_process_get (uint32_t options,
- enum GNUNET_BLOCK_Type type,
- uint32_t hop_count,
- uint32_t desired_replication_level,
- unsigned int path_length,
- const struct GNUNET_PeerIdentity *path,
- const struct GNUNET_HashCode *key)
+static void
+handle_dht_local_hello_get (void *cls,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct ClientHandle *ch = cls;
+ char *url = GNUNET_HELLO_builder_to_url (GDS_my_hello,
+ &GDS_my_private_key);
+ size_t slen = strlen (url) + 1;
+ struct GNUNET_MessageHeader *hdr;
+ struct GNUNET_MQ_Envelope *env;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Handling request from local client for my HELLO\n");
+ env = GNUNET_MQ_msg_extra (hdr,
+ slen,
+ GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL);
+ memcpy (&hdr[1],
+ url,
+ slen);
+ GNUNET_free (url);
+ GNUNET_MQ_send (ch->mq,
+ env);
+ GNUNET_SERVICE_client_continue (ch->client);
+}
+
+
+/**
+ * Process a client HELLO message received from the service.
+ *
+ * @param cls the client we received this message from
+ * @param hdr HELLO URL message from the service.
+ * @return #GNUNET_OK if @a hdr is well-formed
+ */
+static enum GNUNET_GenericReturnValue
+check_dht_local_hello_offer (void *cls,
+ const struct GNUNET_MessageHeader *hdr)
{
- struct ClientMonitorRecord *m;
- struct ClientHandle **cl;
- unsigned int cl_size;
+ uint16_t len = ntohs (hdr->size);
+ const char *buf = (const char *) &hdr[1];
- cl = NULL;
- cl_size = 0;
- for (m = monitor_head; NULL != m; m = m->next)
+ (void) cls;
+ if ('\0' != buf[len - sizeof (*hdr) - 1])
{
- if (((GNUNET_BLOCK_TYPE_ANY == m->type) ||
- (m->type == type)) &&
- ((NULL == m->key) ||
- (0 == memcmp (key,
- m->key,
- sizeof(struct GNUNET_HashCode)))))
- {
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_DHT_MonitorGetMessage *mmsg;
- struct GNUNET_PeerIdentity *msg_path;
- size_t msize;
- unsigned int i;
-
- /* Don't send duplicates */
- for (i = 0; i < cl_size; i++)
- if (cl[i] == m->ch)
- break;
- if (i < cl_size)
- continue;
- GNUNET_array_append (cl,
- cl_size,
- m->ch);
-
- msize = path_length * sizeof(struct GNUNET_PeerIdentity);
- env = GNUNET_MQ_msg_extra (mmsg,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET);
- mmsg->options = htonl (options);
- mmsg->type = htonl (type);
- mmsg->hop_count = htonl (hop_count);
- mmsg->desired_replication_level = htonl (desired_replication_level);
- mmsg->get_path_length = htonl (path_length);
- mmsg->key = *key;
- msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
- GNUNET_memcpy (msg_path,
- path,
- path_length * sizeof(struct GNUNET_PeerIdentity));
- GNUNET_MQ_send (m->ch->mq,
- env);
- }
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
}
- GNUNET_free (cl);
+ return GNUNET_OK;
}
/**
- * Check if some client is monitoring GET RESP messages and notify
- * them in that case.
+ * Handler for HELLO OFFER message. Try to use the
+ * HELLO to connect to another peer.
*
- * @param type The type of data in the result.
- * @param get_path Peers on GET path (or NULL if not recorded).
- * @param get_path_length number of entries in get_path.
- * @param put_path peers on the PUT path (or NULL if not recorded).
- * @param put_path_length number of entries in get_path.
- * @param exp Expiration time of the data.
- * @param key Key of the data.
- * @param data Pointer to the result data.
- * @param size Number of bytes in @a data.
+ * @param cls the client we received this message from
+ * @param msg the actual message received
*/
-void
-GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length,
- struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode *key,
- const void *data,
- size_t size)
+static void
+handle_dht_local_hello_offer (void *cls,
+ const struct GNUNET_MessageHeader *msg)
{
- struct ClientMonitorRecord *m;
- struct ClientHandle **cl;
- unsigned int cl_size;
+ struct ClientHandle *ch = cls;
+ const char *url = (const char *) &msg[1];
+ struct GNUNET_HELLO_Builder *b;
+ struct GNUNET_PeerIdentity pid;
- cl = NULL;
- cl_size = 0;
- for (m = monitor_head; NULL != m; m = m->next)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Local client provided HELLO URL %s\n",
+ url);
+ b = GNUNET_HELLO_builder_from_url (url);
+ if (NULL == b)
{
- if (((GNUNET_BLOCK_TYPE_ANY == m->type) || (m->type == type) ) &&
- ((NULL == m->key) ||
- (memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0) ))
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (ch->client);
+ return;
+ }
+ GNUNET_SERVICE_client_continue (ch->client);
+ GNUNET_HELLO_builder_iterate (b,
+ &pid,
+ &GDS_try_connect,
+ &pid);
+ GNUNET_HELLO_builder_free (b);
+}
+
+
+/* ************* logic for monitors ************** */
+
+
+/**
+ * Handler for monitor start messages
+ *
+ * @param cls the client we received this message from
+ * @param msg the actual message received
+ *
+ */
+static void
+handle_dht_local_monitor (void *cls,
+ const struct GNUNET_DHT_MonitorStartStopMessage *msg)
+{
+ struct ClientHandle *ch = cls;
+ struct ClientMonitorRecord *r;
+
+ r = GNUNET_new (struct ClientMonitorRecord);
+ r->ch = ch;
+ r->type = ntohl (msg->type);
+ r->get = ntohs (msg->get);
+ r->get_resp = ntohs (msg->get_resp);
+ r->put = ntohs (msg->put);
+ if (0 != ntohs (msg->filter_key))
+ r->key = msg->key;
+ GNUNET_CONTAINER_DLL_insert (monitor_head,
+ monitor_tail,
+ r);
+ GNUNET_SERVICE_client_continue (ch->client);
+}
+
+
+/**
+ * Handler for monitor stop messages
+ *
+ * @param cls the client we received this message from
+ * @param msg the actual message received
+ */
+static void
+handle_dht_local_monitor_stop (
+ void *cls,
+ const struct GNUNET_DHT_MonitorStartStopMessage *msg)
+{
+ struct ClientHandle *ch = cls;
+
+ GNUNET_SERVICE_client_continue (ch->client);
+ for (struct ClientMonitorRecord *r = monitor_head;
+ NULL != r;
+ r = r->next)
+ {
+ bool keys_match;
+
+ keys_match =
+ (GNUNET_is_zero (&r->key))
+ ? (0 == ntohs (msg->filter_key))
+ : ( (0 != ntohs (msg->filter_key)) &&
+ (! GNUNET_memcmp (&r->key,
+ &msg->key)) );
+ if ( (ch == r->ch) &&
+ (ntohl (msg->type) == r->type) &&
+ (r->get == msg->get) &&
+ (r->get_resp == msg->get_resp) &&
+ (r->put == msg->put) &&
+ keys_match)
{
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_DHT_MonitorGetRespMessage *mmsg;
- struct GNUNET_PeerIdentity *path;
- size_t msize;
- unsigned int i;
-
- /* Don't send duplicates */
- for (i = 0; i < cl_size; i++)
- if (cl[i] == m->ch)
- break;
- if (i < cl_size)
- continue;
- GNUNET_array_append (cl,
- cl_size,
- m->ch);
-
- msize = size;
- msize += (get_path_length + put_path_length)
- * sizeof(struct GNUNET_PeerIdentity);
- env = GNUNET_MQ_msg_extra (mmsg,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP);
- mmsg->type = htonl (type);
- mmsg->put_path_length = htonl (put_path_length);
- mmsg->get_path_length = htonl (get_path_length);
- mmsg->expiration_time = GNUNET_TIME_absolute_hton (exp);
- mmsg->key = *key;
- path = (struct GNUNET_PeerIdentity *) &mmsg[1];
- GNUNET_memcpy (path,
- put_path,
- put_path_length * sizeof(struct GNUNET_PeerIdentity));
- GNUNET_memcpy (path,
- get_path,
- get_path_length * sizeof(struct GNUNET_PeerIdentity));
- GNUNET_memcpy (&path[get_path_length],
- data,
- size);
- GNUNET_MQ_send (m->ch->mq,
- env);
+ GNUNET_CONTAINER_DLL_remove (monitor_head,
+ monitor_tail,
+ r);
+ GNUNET_free (r);
+ return; /* Delete only ONE entry */
}
}
+}
+
+
+/**
+ * Function to call by #for_matching_monitors().
+ *
+ * @param cls closure
+ * @param m a matching monitor
+ */
+typedef void
+(*MonitorAction)(void *cls,
+ struct ClientMonitorRecord *m);
+
+
+/**
+ * Call @a cb on all monitors that watch for blocks of @a type
+ * and key @a key.
+ *
+ * @param type the type to match
+ * @param key the key to match
+ * @param cb function to call
+ * @param cb_cls closure for @a cb
+ */
+static void
+for_matching_monitors (enum GNUNET_BLOCK_Type type,
+ const struct GNUNET_HashCode *key,
+ MonitorAction cb,
+ void *cb_cls)
+{
+ struct ClientHandle **cl = NULL;
+ unsigned int cl_size = 0;
+
+ for (struct ClientMonitorRecord *m = monitor_head;
+ NULL != m;
+ m = m->next)
+ {
+ bool found = false;
+
+ if ( (GNUNET_BLOCK_TYPE_ANY != m->type) &&
+ (m->type != type) )
+ continue;
+ if ( (! GNUNET_is_zero (&m->key)) &&
+ (0 ==
+ GNUNET_memcmp (key,
+ &m->key)) )
+ continue;
+ /* Don't send duplicates */
+ for (unsigned i = 0; i < cl_size; i++)
+ if (cl[i] == m->ch)
+ {
+ found = true;
+ break;
+ }
+ if (found)
+ continue;
+ GNUNET_array_append (cl,
+ cl_size,
+ m->ch);
+ cb (cb_cls,
+ m);
+ }
GNUNET_free (cl);
}
/**
- * Check if some client is monitoring PUT messages and notify
- * them in that case.
+ * Closure for #get_action();
+ */
+struct GetActionContext
+{
+ enum GNUNET_DHT_RouteOption options;
+ enum GNUNET_BLOCK_Type type;
+ uint32_t hop_count;
+ uint32_t desired_replication_level;
+ struct GNUNET_PeerIdentity trunc_peer;
+ const struct GNUNET_HashCode *key;
+};
+
+
+/**
+ * Function called on monitors that match a GET.
+ * Sends the GET notification to the monitor.
+ *
+ * @param cls a `struct GetActionContext`
+ * @param m a matching monitor
+ */
+static void
+get_action (void *cls,
+ struct ClientMonitorRecord *m)
+{
+ struct GetActionContext *gac = cls;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_DHT_MonitorGetMessage *mmsg;
+
+ env = GNUNET_MQ_msg (mmsg,
+ GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET);
+ mmsg->options = htonl (gac->options);
+ mmsg->type = htonl (gac->type);
+ mmsg->hop_count = htonl (gac->hop_count);
+ mmsg->desired_replication_level = htonl (gac->desired_replication_level);
+ mmsg->key = *gac->key;
+ GNUNET_MQ_send (m->ch->mq,
+ env);
+}
+
+
+/**
+ * Check if some client is monitoring GET messages and notify
+ * them in that case. If tracked, @a path should include the local peer.
*
* @param options Options, for instance RecordRoute, DemultiplexEverywhere.
* @param type The type of data in the request.
* @param hop_count Hop count so far.
- * @param path_length number of entries in path (or 0 if not recorded).
- * @param path peers on the PUT path (or NULL if not recorded).
* @param desired_replication_level Desired replication level.
- * @param exp Expiration time of the data.
- * @param key Key under which data is to be stored.
- * @param data Pointer to the data carried.
- * @param size Number of bytes in data.
+ * @param key Key of the requested data.
*/
void
-GDS_CLIENTS_process_put (uint32_t options,
+GDS_CLIENTS_process_get (enum GNUNET_DHT_RouteOption options,
enum GNUNET_BLOCK_Type type,
uint32_t hop_count,
uint32_t desired_replication_level,
- unsigned int path_length,
- const struct GNUNET_PeerIdentity *path,
- struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode *key,
- const void *data,
- size_t size)
+ const struct GNUNET_HashCode *key)
+{
+ struct GetActionContext gac = {
+ .options = options,
+ .type = type,
+ .hop_count = hop_count,
+ .desired_replication_level = desired_replication_level,
+ .key = key
+ };
+
+ for_matching_monitors (type,
+ key,
+ &get_action,
+ &gac);
+}
+
+
+/**
+ * Closure for response_action().
+ */
+struct ResponseActionContext
{
- struct ClientMonitorRecord *m;
- struct ClientHandle **cl;
- unsigned int cl_size;
+ const struct GNUNET_DATACACHE_Block *bd;
+ const struct GNUNET_DHT_PathElement *get_path;
+ unsigned int get_path_length;
+};
- cl = NULL;
- cl_size = 0;
- for (m = monitor_head; NULL != m; m = m->next)
+
+/**
+ * Function called on monitors that match a response.
+ * Sends the response notification to the monitor.
+ *
+ * @param cls a `struct ResponseActionContext`
+ * @param m a matching monitor
+ */
+static void
+response_action (void *cls,
+ struct ClientMonitorRecord *m)
+{
+ const struct ResponseActionContext *resp_ctx = cls;
+ const struct GNUNET_DATACACHE_Block *bd = resp_ctx->bd;
+ bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_DHT_MonitorGetRespMessage *mmsg;
+ struct GNUNET_DHT_PathElement *path;
+ size_t msize;
+
+ msize = bd->data_size;
+ msize += (resp_ctx->get_path_length + bd->put_path_length)
+ * sizeof(struct GNUNET_DHT_PathElement);
+ if (truncated)
+ msize += sizeof (struct GNUNET_PeerIdentity);
+ env = GNUNET_MQ_msg_extra (mmsg,
+ msize,
+ GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP);
+ mmsg->type = htonl (bd->type);
+ mmsg->put_path_length = htonl (bd->put_path_length);
+ mmsg->get_path_length = htonl (resp_ctx->get_path_length);
+ mmsg->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
+ mmsg->key = bd->key;
+ if (truncated)
{
- if (((GNUNET_BLOCK_TYPE_ANY == m->type) || (m->type == type) ) &&
- ((NULL == m->key) ||
- (memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0) ))
- {
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_DHT_MonitorPutMessage *mmsg;
- struct GNUNET_PeerIdentity *msg_path;
- size_t msize;
- unsigned int i;
-
- /* Don't send duplicates */
- for (i = 0; i < cl_size; i++)
- if (cl[i] == m->ch)
- break;
- if (i < cl_size)
- continue;
- GNUNET_array_append (cl,
- cl_size,
- m->ch);
-
- msize = size;
- msize += path_length * sizeof(struct GNUNET_PeerIdentity);
- env = GNUNET_MQ_msg_extra (mmsg,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
- mmsg->options = htonl (options);
- mmsg->type = htonl (type);
- mmsg->hop_count = htonl (hop_count);
- mmsg->desired_replication_level = htonl (desired_replication_level);
- mmsg->put_path_length = htonl (path_length);
- mmsg->key = *key;
- mmsg->expiration_time = GNUNET_TIME_absolute_hton (exp);
- msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
- GNUNET_memcpy (msg_path,
- path,
- path_length * sizeof(struct GNUNET_PeerIdentity));
- GNUNET_memcpy (&msg_path[path_length],
- data,
- size);
- GNUNET_MQ_send (m->ch->mq,
- env);
- }
+ void *tgt = &mmsg[1];
+
+ GNUNET_memcpy (tgt,
+ &bd->trunc_peer,
+ sizeof (struct GNUNET_PeerIdentity));
+ path = (struct GNUNET_DHT_PathElement *)
+ (tgt + sizeof (struct GNUNET_PeerIdentity));
}
- GNUNET_free (cl);
+ else
+ {
+ path = (struct GNUNET_DHT_PathElement *) &mmsg[1];
+ }
+ GNUNET_memcpy (path,
+ bd->put_path,
+ bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
+ GNUNET_memcpy (path,
+ resp_ctx->get_path,
+ resp_ctx->get_path_length
+ * sizeof(struct GNUNET_DHT_PathElement));
+ GNUNET_memcpy (&path[resp_ctx->get_path_length],
+ bd->data,
+ bd->data_size);
+ GNUNET_MQ_send (m->ch->mq,
+ env);
+}
+
+
+void
+GDS_CLIENTS_process_get_resp (const struct GNUNET_DATACACHE_Block *bd,
+ const struct GNUNET_DHT_PathElement *get_path,
+ unsigned int get_path_length)
+{
+ struct ResponseActionContext rac = {
+ .bd = bd,
+ .get_path = get_path,
+ .get_path_length = get_path_length
+ };
+
+ for_matching_monitors (bd->type,
+ &bd->key,
+ &response_action,
+ &rac);
}
/**
+ * Closure for put_action().
+ */
+struct PutActionContext
+{
+ const struct GNUNET_DATACACHE_Block *bd;
+ uint32_t hop_count;
+ uint32_t desired_replication_level;
+};
+
+
+/**
+ * Function called on monitors that match a PUT.
+ * Sends the PUT notification to the monitor.
+ *
+ * @param cls a `struct PutActionContext`
+ * @param m a matching monitor
+ */
+static void
+put_action (void *cls,
+ struct ClientMonitorRecord *m)
+{
+ const struct PutActionContext *put_ctx = cls;
+ const struct GNUNET_DATACACHE_Block *bd = put_ctx->bd;
+ bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_DHT_MonitorPutMessage *mmsg;
+ struct GNUNET_DHT_PathElement *msg_path;
+ size_t msize;
+
+ msize = bd->data_size
+ + bd->put_path_length
+ * sizeof(struct GNUNET_DHT_PathElement);
+ if (truncated)
+ msize += sizeof (struct GNUNET_PeerIdentity);
+ env = GNUNET_MQ_msg_extra (mmsg,
+ msize,
+ GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
+ mmsg->options = htonl (bd->ro);
+ mmsg->type = htonl (bd->type);
+ mmsg->hop_count = htonl (put_ctx->hop_count);
+ mmsg->desired_replication_level = htonl (put_ctx->desired_replication_level);
+ mmsg->put_path_length = htonl (bd->put_path_length);
+ mmsg->key = bd->key;
+ mmsg->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
+ if (truncated)
+ {
+ void *tgt = &mmsg[1];
+
+ GNUNET_memcpy (tgt,
+ &bd->trunc_peer,
+ sizeof (struct GNUNET_PeerIdentity));
+ msg_path = (struct GNUNET_DHT_PathElement *)
+ (tgt + sizeof (struct GNUNET_PeerIdentity));
+ }
+ else
+ {
+ msg_path = (struct GNUNET_DHT_PathElement *) &mmsg[1];
+ }
+ GNUNET_memcpy (msg_path,
+ bd->put_path,
+ bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
+ GNUNET_memcpy (&msg_path[bd->put_path_length],
+ bd->data,
+ bd->data_size);
+ GNUNET_MQ_send (m->ch->mq,
+ env);
+}
+
+
+void
+GDS_CLIENTS_process_put (const struct GNUNET_DATACACHE_Block *bd,
+ uint32_t hop_count,
+ uint32_t desired_replication_level)
+{
+ struct PutActionContext put_ctx = {
+ .bd = bd,
+ .hop_count = hop_count,
+ .desired_replication_level = desired_replication_level
+ };
+
+ for_matching_monitors (bd->type,
+ &bd->key,
+ &put_action,
+ &put_ctx);
+}
+
+
+/* ********************** Initialization logic ***************** */
+
+
+/**
* Initialize client subsystem.
*
* @param server the initialized server
*/
static void
-GDS_CLIENTS_init ()
+GDS_CLIENTS_init (void)
{
forward_map
= GNUNET_CONTAINER_multihashmap_create (1024,
@@ -1469,7 +1615,7 @@ GDS_CLIENTS_init ()
* Shutdown client subsystem.
*/
static void
-GDS_CLIENTS_stop ()
+GDS_CLIENTS_stop (void)
{
if (NULL != retry_task)
{
@@ -1517,6 +1663,14 @@ GDS_CLIENTS_stop ()
GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, \
struct GNUNET_DHT_ClientGetResultSeenMessage, \
NULL), \
+ GNUNET_MQ_hd_fixed_size (dht_local_hello_get, \
+ GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET, \
+ struct GNUNET_MessageHeader, \
+ NULL), \
+ GNUNET_MQ_hd_var_size (dht_local_hello_offer, \
+ GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL, \
+ struct GNUNET_MessageHeader, \
+ NULL), \
GNUNET_MQ_handler_end ())
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
index 7eded2152..dcb6308a9 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009, 2010, 2011, 2015, 2017 GNUnet e.V.
+ Copyright (C) 2009, 2010, 2011, 2015, 2017, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -36,7 +36,8 @@
* How many "closest" results to we return for migration when
* asked (at most)?
*/
-#define NUM_CLOSEST 42
+#define NUM_CLOSEST 4
+
/**
* Handle to the datacache service (for inserting/retrieving data)
@@ -44,61 +45,40 @@
static struct GNUNET_DATACACHE_Handle *datacache;
-/**
- * Handle a datum we've received from another peer. Cache if
- * possible.
- *
- * @param expiration when will the reply expire
- * @param key the query this reply is for
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
- * @param type type of the reply
- * @param data_size number of bytes in @a data
- * @param data application payload data
- */
void
-GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- enum GNUNET_BLOCK_Type type,
- size_t data_size,
- const void *data)
+GDS_DATACACHE_handle_put (const struct GNUNET_DATACACHE_Block *bd)
{
- int r;
+ struct GNUNET_HashCode xor;
+ enum GNUNET_GenericReturnValue r;
if (NULL == datacache)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _ ("%s request received, but have no datacache!\n"), "PUT");
+ "PUT request received, but have no datacache!\n");
return;
}
- if (data_size >= GNUNET_MAX_MESSAGE_SIZE)
+ if (bd->data_size >= GNUNET_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
return;
}
/* Put size is actual data size plus struct overhead plus path length (if any) */
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# ITEMS stored in datacache"),
+ "# ITEMS stored in datacache",
1,
GNUNET_NO);
+ GNUNET_CRYPTO_hash_xor (&bd->key,
+ &GDS_my_identity_hash,
+ &xor);
r = GNUNET_DATACACHE_put (datacache,
- key,
- GNUNET_CRYPTO_hash_matching_bits (key,
- &my_identity_hash),
- data_size,
- data,
- type,
- expiration,
- put_path_length,
- put_path);
+ GNUNET_CRYPTO_hash_count_leading_zeros (&xor),
+ bd);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n",
- GNUNET_h2s (key),
- (unsigned long) data_size,
+ GNUNET_h2s (&bd->key),
+ (unsigned long) bd->data_size,
r,
- put_path_length);
+ bd->put_path_length);
}
@@ -140,7 +120,7 @@ struct GetRequestContext
/**
* Return value to give back.
*/
- enum GNUNET_BLOCK_EvaluationResult eval;
+ enum GNUNET_BLOCK_ReplyEvaluationResult eval;
};
@@ -148,132 +128,67 @@ struct GetRequestContext
* Iterator for local get request results,
*
* @param cls closure for iterator, a `struct GetRequestContext`
- * @param exp when does this value expire?
- * @param key the key this data is stored under
- * @param data_size the size of the data identified by key
- * @param data the actual data
- * @param type the type of the @a data
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
+ * @param bd block data
* @return #GNUNET_OK to continue iteration, anything else
* to stop iteration.
*/
-static int
+static enum GNUNET_GenericReturnValue
datacache_get_iterator (void *cls,
- const struct GNUNET_HashCode *key,
- size_t data_size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute exp,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path)
+ const struct GNUNET_DATACACHE_Block *bd)
{
- static char non_null;
struct GetRequestContext *ctx = cls;
- enum GNUNET_BLOCK_EvaluationResult eval;
+ enum GNUNET_BLOCK_ReplyEvaluationResult eval;
- if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
+ if (GNUNET_TIME_absolute_is_past (bd->expiration_time))
{
GNUNET_break (0); /* why does datacache return expired values? */
return GNUNET_OK; /* skip expired record */
}
- if ((NULL == data) &&
- (0 == data_size))
- data = &non_null; /* point anywhere, but not to NULL */
-
eval
- = GNUNET_BLOCK_evaluate (GDS_block_context,
- type,
- ctx->bg,
- GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO,
- key,
- ctx->xquery,
- ctx->xquery_size,
- data,
- data_size);
+ = GNUNET_BLOCK_check_reply (GDS_block_context,
+ bd->type,
+ ctx->bg,
+ &bd->key,
+ ctx->xquery,
+ ctx->xquery_size,
+ bd->data,
+ bd->data_size);
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Found reply for query %s in datacache, evaluation result is %d\n",
- GNUNET_h2s (key),
+ "Evaluated reply for query %s in datacache, result is %d\n",
+ GNUNET_h2s (&bd->key),
(int) eval);
ctx->eval = eval;
switch (eval)
{
- case GNUNET_BLOCK_EVALUATION_OK_MORE:
- case GNUNET_BLOCK_EVALUATION_OK_LAST:
- /* forward to local clients */
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- ("# Good RESULTS found in datacache"), 1,
- GNUNET_NO);
- ctx->gc (ctx->gc_cls,
- type,
- exp,
- key,
- put_path_length, put_path,
- 0, NULL,
- data, data_size);
- break;
-
- case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
+ case GNUNET_BLOCK_REPLY_OK_MORE:
+ case GNUNET_BLOCK_REPLY_OK_LAST:
+ case GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED:
+ /* forward to initiator */
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# Duplicate RESULTS found in datacache"),
+ "# Good RESULTS found in datacache",
1,
GNUNET_NO);
+ ctx->gc (ctx->gc_cls,
+ bd);
break;
-
- case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
+ case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# Invalid RESULTS found in datacache"),
+ "# Duplicate RESULTS found in datacache",
1,
GNUNET_NO);
break;
-
- case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
+ case GNUNET_BLOCK_REPLY_IRRELEVANT:
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# Irrelevant RESULTS found in datacache"),
+ "# Irrelevant RESULTS found in datacache",
1,
GNUNET_NO);
break;
-
- case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
- GNUNET_break (0);
- break;
-
- case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
-
- case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# Unsupported RESULTS found in datacache"),
- 1,
- GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _ ("Unsupported block type (%u) in local response!\n"),
- type);
- break;
}
- return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK;
+ return (eval == GNUNET_BLOCK_REPLY_OK_LAST) ? GNUNET_NO : GNUNET_OK;
}
-/**
- * Handle a GET request we've received from another peer.
- *
- * @param key the query
- * @param type requested data type
- * @param xquery extended query
- * @param xquery_size number of bytes in @a xquery
- * @param bg block group to use for reply evaluation
- * @param gc function to call on the results
- * @param gc_cls closure for @a gc
- * @return evaluation result for the local replies
- */
-enum GNUNET_BLOCK_EvaluationResult
+enum GNUNET_BLOCK_ReplyEvaluationResult
GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
enum GNUNET_BLOCK_Type type,
const void *xquery,
@@ -282,22 +197,23 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
GDS_DATACACHE_GetCallback gc,
void *gc_cls)
{
- struct GetRequestContext ctx;
+ struct GetRequestContext ctx = {
+ .eval = GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
+ .key = *key,
+ .xquery = xquery,
+ .xquery_size = xquery_size,
+ .bg = bg,
+ .gc = gc,
+ .gc_cls = gc_cls
+ };
unsigned int r;
if (NULL == datacache)
- return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
+ return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# GET requests given to datacache"),
+ "# GET requests given to datacache",
1,
GNUNET_NO);
- ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
- ctx.key = *key;
- ctx.xquery = xquery;
- ctx.xquery_size = xquery_size;
- ctx.bg = bg;
- ctx.gc = gc;
- ctx.gc_cls = gc_cls;
r = GNUNET_DATACACHE_get (datacache,
key,
type,
@@ -312,159 +228,55 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
}
-/**
- * Function called with a random element from the datacache.
- * Stores the key in the closure.
- *
- * @param cls a `struct GNUNET_HashCode *`, where to store the @a key
- * @param key key for the content
- * @param data_size number of bytes in @a data
- * @param data content stored
- * @param type type of the content
- * @param exp when will the content expire?
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
- * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
- */
-static int
-datacache_random_iterator (void *cls,
- const struct GNUNET_HashCode *key,
- size_t data_size,
- const char *data,
+enum GNUNET_BLOCK_ReplyEvaluationResult
+GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute exp,
- unsigned int path_info_len,
- const struct GNUNET_PeerIdentity *path_info)
-{
- struct GNUNET_HashCode *dest = cls;
-
- *dest = *key;
- return GNUNET_OK; /* should actually not matter which we return */
-}
-
-
-/**
- * Obtain a random key from the datacache.
- * Used by Whanau for load-balancing.
- *
- * @param[out] key where to store the key of a random element,
- * randomized by PRNG if datacache is empty
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
- */
-int
-GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key)
-{
- if (0 ==
- GNUNET_DATACACHE_get_random (datacache,
- &datacache_random_iterator,
- key))
- {
- /* randomize key in this case */
- GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
- key);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Closure for #datacache_get_successors_iterator().
- */
-struct SuccContext
-{
- /**
- * Function to call on the result
- */
- GDS_DATACACHE_SuccessorCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-};
-
-
-/**
- * Iterator for local get request results,
- *
- * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
- * @param key the key this data is stored under
- * @param size the size of the data identified by key
- * @param data the actual data
- * @param type the type of the data
- * @param exp when does this value expire?
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
- * @return #GNUNET_OK to continue iteration, anything else
- * to stop iteration.
- */
-static int
-datacache_get_successors_iterator (void *cls,
- const struct GNUNET_HashCode *key,
- size_t size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute exp,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path)
+ const void *xquery,
+ size_t xquery_size,
+ struct GNUNET_BLOCK_Group *bg,
+ GDS_DATACACHE_GetCallback cb,
+ void *cb_cls)
{
- const struct SuccContext *sc = cls;
-
- /* NOTE: The datacache currently does not store the RO from
- the original 'put', so we don't know the 'correct' option
- at this point anymore. Thus, we conservatively assume
- that recording is desired (for now). */
- sc->cb (sc->cb_cls,
- GNUNET_DHT_RO_RECORD_ROUTE,
- key,
- type,
- put_path_length, put_path,
- exp,
- data,
- size);
- return GNUNET_OK;
-}
-
+ struct GetRequestContext ctx = {
+ .eval = GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
+ .key = *key,
+ .xquery = xquery,
+ .xquery_size = xquery_size,
+ .bg = bg,
+ .gc = cb,
+ .gc_cls = cb_cls
+ };
+ unsigned int r;
-/**
- * Handle a request for data close to a key that we have received from
- * another peer.
- *
- * @param key the location at which the peer is looking for data that is close
- * @param cb function to call with the result
- * @param cb_cls closure for @a cb
- */
-void
-GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key,
- GDS_DATACACHE_SuccessorCallback cb,
- void *cb_cls)
-{
- struct SuccContext sc;
-
- sc.cb = cb;
- sc.cb_cls = cb_cls;
- (void) GNUNET_DATACACHE_get_closest (datacache,
- key,
- NUM_CLOSEST,
- &datacache_get_successors_iterator,
- &sc);
+ if (NULL == datacache)
+ return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# GET closest requests given to datacache",
+ 1,
+ GNUNET_NO);
+ r = GNUNET_DATACACHE_get_closest (datacache,
+ key,
+ type,
+ NUM_CLOSEST,
+ &datacache_get_iterator,
+ &ctx);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "DATACACHE approximate GET for key %s completed (%d). %u results found.\n",
+ GNUNET_h2s (key),
+ ctx.eval,
+ r);
+ return ctx.eval;
}
-/**
- * Initialize datacache subsystem.
- */
void
GDS_DATACACHE_init ()
{
- datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache");
+ datacache = GNUNET_DATACACHE_create (GDS_cfg,
+ "dhtcache");
}
-/**
- * Shutdown datacache subsystem.
- */
void
GDS_DATACACHE_done ()
{
diff --git a/src/dht/gnunet-service-dht_datacache.h b/src/dht/gnunet-service-dht_datacache.h
index 5be59c90e..b15e5378f 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009, 2010, 2011 GNUnet e.V.
+ Copyright (C) 2009, 2010, 2011, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -30,54 +30,28 @@
#include "gnunet_util_lib.h"
#include "gnunet_block_lib.h"
#include "gnunet_dht_service.h"
+#include "gnunet_datacache_lib.h"
+
/**
* Handle a datum we've received from another peer. Cache if
* possible.
*
- * @param expiration when will the reply expire
- * @param key the query this reply is for
- * @param put_path_length number of peers in 'put_path'
- * @param put_path path the reply took on put
- * @param type type of the reply
- * @param data_size number of bytes in 'data'
- * @param data application payload data
+ * @param bd block data to cache
*/
void
-GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- enum GNUNET_BLOCK_Type type,
- size_t data_size,
- const void *data);
+GDS_DATACACHE_handle_put (const struct GNUNET_DATACACHE_Block *bd);
/**
* Handle a result for a GET operation.
*
* @param cls closure
- * @param type type of the block
- * @param expiration_time when does the content expire
- * @param key key for the content
- * @param put_path_length number of entries in @a put_path
- * @param put_path peers the original PUT traversed (if tracked)
- * @param get_path_length number of entries in @a get_path
- * @param get_path peers this reply has traversed so far (if tracked)
- * @param data payload of the reply
- * @param data_size number of bytes in @a data
+ * @param bd block details
*/
typedef void
(*GDS_DATACACHE_GetCallback)(void *cls,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute expiration_time,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- const void *data,
- size_t data_size);
+ const struct GNUNET_DATACACHE_Block *bd);
/**
@@ -92,7 +66,7 @@ typedef void
* @param gc_cls closure for @a gc
* @return evaluation result for the local replies
*/
-enum GNUNET_BLOCK_EvaluationResult
+enum GNUNET_BLOCK_ReplyEvaluationResult
GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
enum GNUNET_BLOCK_Type type,
const void *xquery,
@@ -103,54 +77,26 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
/**
- * Obtain a random key from the datacache.
- * Used by Whanau for load-balancing.
- *
- * @param[out] key where to store the key of a random element,
- * randomized by PRNG if datacache is empty
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
- */
-int
-GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key);
-
-
-/**
- * Send the get result to requesting client.
- *
- * @param cls closure
- * @param options routing options (from GET request)
- * @param key key of the requested data.
- * @param type block type
- * @param put_path_length number of peers in @a put_path
- * @param put_path path taken to put the data at its stored location.
- * @param expiration when will this result expire?
- * @param data payload to store
- * @param data_size size of the @a data
- */
-typedef void
-(*GDS_DATACACHE_SuccessorCallback)(void *cls,
- enum GNUNET_DHT_RouteOption options,
- const struct GNUNET_HashCode *key,
- enum GNUNET_BLOCK_Type type,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- struct GNUNET_TIME_Absolute expiration,
- const void *data,
- size_t data_size);
-
-
-/**
* Handle a request for data close to a key that we have received from
* another peer.
*
* @param key the location at which the peer is looking for data that is close
+ * @param type requested data type
+ * @param xquery extended query
+ * @param xquery_size number of bytes in xquery
+ * @param bg block group to use for evaluation of replies
* @param cb function to call with the result
* @param cb_cls closure for @a cb
+ * @return evaluation result for the local replies
*/
-void
-GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key,
- GDS_DATACACHE_SuccessorCallback cb,
- void *cb_cls);
+enum GNUNET_BLOCK_ReplyEvaluationResult
+GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
+ const void *xquery,
+ size_t xquery_size,
+ struct GNUNET_BLOCK_Group *bg,
+ GDS_DATACACHE_GetCallback cb,
+ void *cb_cls);
/**
diff --git a/src/dht/gnunet-service-dht_hello.c b/src/dht/gnunet-service-dht_hello.c
deleted file mode 100644
index 906391334..000000000
--- a/src/dht/gnunet-service-dht_hello.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2011 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-
-/**
- * @file dht/gnunet-service-dht_hello.c
- * @brief GNUnet DHT integration with peerinfo
- * @author Christian Grothoff
- *
- * TODO:
- * - consider adding mechanism to remove expired HELLOs
- */
-#include "platform.h"
-#include "gnunet-service-dht.h"
-#include "gnunet-service-dht_hello.h"
-#include "gnunet_peerinfo_service.h"
-
-
-/**
- * Handle for peerinfo notifications.
- */
-static struct GNUNET_PEERINFO_NotifyContext *pnc;
-
-/**
- * Hash map of peers to HELLOs.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
-
-
-/**
- * Obtain a peer's HELLO if available
- *
- * @param peer peer to look for a HELLO from
- * @return HELLO for the given peer
- */
-const struct GNUNET_HELLO_Message *
-GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
-{
- if (NULL == peer_to_hello)
- return NULL;
- return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer);
-}
-
-
-/**
- * Function called for each HELLO known to PEERINFO.
- *
- * @param cls closure
- * @param peer id of the peer, NULL for last call
- * @param hello hello message for the peer (can be NULL)
- * @param err_msg error message (not used)
- *
- * FIXME this is called once per address. Merge instead of replacing?
- */
-static void
-process_hello (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Message *hello,
- const char *err_msg)
-{
- struct GNUNET_TIME_Absolute ex;
- struct GNUNET_HELLO_Message *hm;
-
- if (NULL == hello)
- return;
- ex = GNUNET_HELLO_get_last_expiration (hello);
- if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
- return;
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# HELLOs obtained from peerinfo"), 1,
- GNUNET_NO);
- hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer);
- GNUNET_free (hm);
- hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
- GNUNET_memcpy (hm, hello, GNUNET_HELLO_size (hello));
- GNUNET_assert (GNUNET_SYSERR !=
- GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
- peer, hm,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
-}
-
-
-/**
- * Initialize HELLO subsystem.
- */
-void
-GDS_HELLO_init ()
-{
- pnc = GNUNET_PEERINFO_notify (GDS_cfg,
- GNUNET_NO,
- &process_hello,
- NULL);
- peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
- GNUNET_NO);
-}
-
-
-/**
- * Free memory occopied by the HELLO.
- */
-static int
-free_hello (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *hello)
-{
- GNUNET_free (hello);
- return GNUNET_OK;
-}
-
-
-/**
- * Shutdown HELLO subsystem.
- */
-void
-GDS_HELLO_done ()
-{
- if (NULL != pnc)
- {
- GNUNET_PEERINFO_notify_cancel (pnc);
- pnc = NULL;
- }
- if (NULL != peer_to_hello)
- {
- GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
- &free_hello,
- NULL);
- GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
- }
-}
-
-
-/* end of gnunet-service-dht_hello.c */
diff --git a/src/dht/gnunet-service-dht_hello.h b/src/dht/gnunet-service-dht_hello.h
deleted file mode 100644
index f8b90862d..000000000
--- a/src/dht/gnunet-service-dht_hello.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2011 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-
-/**
- * @file dht/gnunet-service-dht_hello.h
- * @brief GNUnet DHT integration with peerinfo
- * @author Christian Grothoff
- */
-#ifndef GNUNET_SERVICE_DHT_HELLO_H
-#define GNUNET_SERVICE_DHT_HELLO_H
-
-#include "gnunet_util_lib.h"
-#include "gnunet_hello_lib.h"
-
-/**
- * Obtain a peer's HELLO if available
- *
- * @param peer peer to look for a HELLO from
- * @return HELLO for the given peer
- */
-const struct GNUNET_HELLO_Message *
-GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Initialize HELLO subsystem.
- */
-void
-GDS_HELLO_init (void);
-
-
-/**
- * Shutdown HELLO subsystem.
- */
-void
-GDS_HELLO_done (void);
-
-#endif
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index 6465d8d57..cc7333a9c 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2009-2017, 2021 GNUnet e.V.
+ Copyright (C) 2009-2017, 2021, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -25,24 +25,13 @@
* @author Nathan Evans
*/
#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_block_lib.h"
-#include "gnunet_hello_lib.h"
#include "gnunet_constants.h"
#include "gnunet_protocols.h"
-#include "gnunet_nse_service.h"
-#include "gnunet_ats_service.h"
-#include "gnunet_core_service.h"
-#include "gnunet_datacache_lib.h"
-#include "gnunet_transport_service.h"
+#include "gnunet_signatures.h"
#include "gnunet_hello_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_statistics_service.h"
+#include "gnunet_hello_uri_lib.h"
#include "gnunet-service-dht.h"
-#include "gnunet-service-dht_datacache.h"
-#include "gnunet-service-dht_hello.h"
#include "gnunet-service-dht_neighbours.h"
-#include "gnunet-service-dht_nse.h"
#include "gnunet-service-dht_routing.h"
#include "dht.h"
@@ -51,11 +40,19 @@
/**
* Enable slow sanity checks to debug issues.
+ *
+ * TODO: might want to eventually implement probabilistic
+ * load-based path verification, but for now it is all or nothing
+ * based on this define.
+ *
+ * 0: do not check -- if signatures become performance critical
+ * 1: check all external inputs -- normal production for now
+ * 2: check internal computations as well -- for debugging
*/
-#define SANITY_CHECKS 1
+#define SANITY_CHECKS 2
/**
- * How many buckets will we allow total.
+ * How many buckets will we allow in total.
*/
#define MAX_BUCKETS sizeof(struct GNUNET_HashCode) * 8
@@ -70,37 +67,36 @@
#define FIND_PEER_REPLICATION_LEVEL 4
/**
- * Maximum allowed replication level for all requests.
- */
-#define MAXIMUM_REPLICATION_LEVEL 16
-
-/**
* Maximum allowed number of pending messages per peer.
*/
#define MAXIMUM_PENDING_PER_PEER 64
/**
* How long at least to wait before sending another find peer request.
+ * This is basically the frequency at which we will usually send out
+ * requests when we are 'perfectly' connected.
*/
#define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
- GNUNET_TIME_UNIT_SECONDS, 30)
+ GNUNET_TIME_UNIT_MINUTES, 2)
+
/**
- * How long at most to wait before sending another find peer request.
+ * How long to additionally wait on average per #bucket_size to send out the
+ * FIND PEER requests if we did successfully connect (!) to a a new peer and
+ * added it to a bucket (as counted in #newly_found_peers). This time is
+ * Multiplied by 100 * newly_found_peers / bucket_size to get the new delay
+ * for finding peers (the #DHT_MINIMUM_FIND_PEER_INTERVAL is still added on
+ * top). Also the range in which we randomize, so the effective value
+ * is half of the number given here.
*/
-#define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
- GNUNET_TIME_UNIT_MINUTES, 10)
+#define DHT_AVG_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply ( \
+ GNUNET_TIME_UNIT_SECONDS, 6)
/**
* How long at most to wait for transmission of a GET request to another peer?
*/
#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
-/**
- * Hello address expiration
- */
-extern struct GNUNET_TIME_Relative hello_expiration;
-
GNUNET_NETWORK_STRUCT_BEGIN
@@ -115,29 +111,29 @@ struct PeerPutMessage
struct GNUNET_MessageHeader header;
/**
- * Processing options
+ * Content type.
*/
- uint32_t options GNUNET_PACKED;
+ uint32_t type GNUNET_PACKED;
/**
- * Content type.
+ * Processing options
*/
- uint32_t type GNUNET_PACKED;
+ uint16_t options GNUNET_PACKED;
/**
* Hop count
*/
- uint32_t hop_count GNUNET_PACKED;
+ uint16_t hop_count GNUNET_PACKED;
/**
* Replication level for this message
*/
- uint32_t desired_replication_level GNUNET_PACKED;
+ uint16_t desired_replication_level GNUNET_PACKED;
/**
* Length of the PUT path that follows (if tracked).
*/
- uint32_t put_path_length GNUNET_PACKED;
+ uint16_t put_path_length GNUNET_PACKED;
/**
* When does the content expire?
@@ -154,8 +150,12 @@ struct PeerPutMessage
*/
struct GNUNET_HashCode key;
+ /* trunc_peer (if truncated) */
+
/* put path (if tracked) */
+ /* sender_sig (if path tracking is on) */
+
/* Payload */
};
@@ -176,14 +176,19 @@ struct PeerResultMessage
uint32_t type GNUNET_PACKED;
/**
+ * Message options, actually an 'enum GNUNET_DHT_RouteOption' value in NBO.
+ */
+ uint32_t options GNUNET_PACKED;
+
+ /**
* Length of the PUT path that follows (if tracked).
*/
- uint32_t put_path_length GNUNET_PACKED;
+ uint16_t put_path_length GNUNET_PACKED;
/**
* Length of the GET path that follows (if tracked).
*/
- uint32_t get_path_length GNUNET_PACKED;
+ uint16_t get_path_length GNUNET_PACKED;
/**
* When does the content expire?
@@ -195,10 +200,14 @@ struct PeerResultMessage
*/
struct GNUNET_HashCode key;
+ /* trunc_peer (if truncated) */
+
/* put path (if tracked) */
/* get path (if tracked) */
+ /* sender_sig (if path tracking is on) */
+
/* Payload */
};
@@ -214,34 +223,29 @@ struct PeerGetMessage
struct GNUNET_MessageHeader header;
/**
- * Processing options
- */
- uint32_t options GNUNET_PACKED;
-
- /**
* Desired content type.
*/
uint32_t type GNUNET_PACKED;
/**
- * Hop count
+ * Processing options
*/
- uint32_t hop_count GNUNET_PACKED;
+ uint16_t options GNUNET_PACKED;
/**
- * Desired replication level for this request.
+ * Hop count
*/
- uint32_t desired_replication_level GNUNET_PACKED;
+ uint16_t hop_count GNUNET_PACKED;
/**
- * Size of the extended query.
+ * Desired replication level for this request.
*/
- uint32_t xquery_size;
+ uint16_t desired_replication_level GNUNET_PACKED;
/**
- * Bloomfilter mutator.
+ * Size of the result filter.
*/
- uint32_t bf_mutator;
+ uint16_t result_filter_size GNUNET_PACKED;
/**
* Bloomfilter (for peer identities) to stop circular routes
@@ -253,9 +257,10 @@ struct PeerGetMessage
*/
struct GNUNET_HashCode key;
+ /* result bloomfilter */
+
/* xquery */
- /* result bloomfilter */
};
GNUNET_NETWORK_STRUCT_END
@@ -263,81 +268,134 @@ GNUNET_NETWORK_STRUCT_END
/**
* Entry for a peer in a bucket.
*/
-struct PeerInfo
+struct PeerInfo;
+
+
+/**
+ * List of targets that we can use to reach this peer.
+ */
+struct Target
{
/**
- * Next peer entry (DLL)
+ * Kept in a DLL.
*/
- struct PeerInfo *next;
+ struct Target *next;
/**
- * Prev peer entry (DLL)
+ * Kept in a DLL.
*/
- struct PeerInfo *prev;
+ struct Target *prev;
/**
* Handle for sending messages to this peer.
*/
- struct GNUNET_MQ_Handle *mq;
+ struct GNUNET_DHTU_Target *utarget;
/**
- * What is the identity of the peer?
+ * Underlay providing this target.
*/
- const struct GNUNET_PeerIdentity *id;
+ struct GDS_Underlay *u;
/**
- * Hash of @e id.
+ * Peer this is a target for.
*/
- struct GNUNET_HashCode phash;
+ struct PeerInfo *pi;
/**
- * Which bucket is this peer in?
+ * Handle used to 'hold' the connection to this peer.
*/
- int peer_bucket;
+ struct GNUNET_DHTU_PreferenceHandle *ph;
+
+ /**
+ * Set to number of messages are waiting for the transmission to finish.
+ */
+ unsigned int load;
+
+ /**
+ * Set to @a true if the target was dropped, but we could not clean
+ * up yet because @e busy was also true.
+ */
+ bool dropped;
+
};
/**
- * Peers are grouped into buckets.
+ * Entry for a peer in a bucket.
*/
-struct PeerBucket
+struct PeerInfo
{
/**
- * Head of DLL
+ * What is the identity of the peer?
*/
- struct PeerInfo *head;
+ struct GNUNET_PeerIdentity id;
/**
- * Tail of DLL
+ * Hash of @e id.
*/
- struct PeerInfo *tail;
+ struct GNUNET_HashCode phash;
/**
- * Number of peers in the bucket.
+ * When does our HELLO from this peer expire?
*/
- unsigned int peers_size;
+ struct GNUNET_TIME_Absolute hello_expiration;
+
+ /**
+ * Next peer entry (DLL)
+ */
+ struct PeerInfo *next;
+
+ /**
+ * Prev peer entry (DLL)
+ */
+ struct PeerInfo *prev;
+
+ /**
+ * Head of DLL of targets for this peer.
+ */
+ struct Target *t_head;
+
+ /**
+ * Tail of DLL of targets for this peer.
+ */
+ struct Target *t_tail;
+
+ /**
+ * Block with a HELLO of this peer.
+ */
+ void *hello;
+
+ /**
+ * Number of bytes in @e hello.
+ */
+ size_t hello_size;
+
+ /**
+ * Which bucket is this peer in?
+ */
+ int peer_bucket;
};
/**
- * Information about a peer that we would like to connect to.
+ * Peers are grouped into buckets.
*/
-struct ConnectInfo
+struct PeerBucket
{
/**
- * Handle to active HELLO offer operation, or NULL.
+ * Head of DLL
*/
- struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
+ struct PeerInfo *head;
/**
- * Handle to active connectivity suggestion operation, or NULL.
+ * Tail of DLL
*/
- struct GNUNET_ATS_ConnectivitySuggestHandle *sh;
+ struct PeerInfo *tail;
/**
- * How much would we like to connect to this peer?
+ * Number of peers in the bucket.
*/
- uint32_t strength;
+ unsigned int peers_size;
};
@@ -347,11 +405,6 @@ struct ConnectInfo
static int cache_results;
/**
- * Should routing details be logged to stderr (for debugging)?
- */
-static int log_route_details_stderr;
-
-/**
* The lowest currently used bucket, initially 0 (for 0-bits matching bucket).
*/
static unsigned int closest_bucket;
@@ -379,12 +432,6 @@ static struct PeerBucket k_buckets[MAX_BUCKETS];
static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers;
/**
- * Hash map of all peers we would like to be connected to.
- * Values are of type `struct ConnectInfo`.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers;
-
-/**
* Maximum size for each bucket.
*/
static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
@@ -394,242 +441,173 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
*/
static struct GNUNET_SCHEDULER_Task *find_peer_task;
-/**
- * Identity of this peer.
- */
-static struct GNUNET_PeerIdentity my_identity;
-
-/**
- * Hash of the identity of this peer.
- */
-struct GNUNET_HashCode my_identity_hash;
/**
- * Handle to CORE.
- */
-static struct GNUNET_CORE_Handle *core_api;
-
-/**
- * Handle to ATS connectivity.
- */
-static struct GNUNET_ATS_ConnectivityHandle *ats_ch;
-
-
-/**
- * Find the optimal bucket for this key.
+ * Function called whenever we finished sending to a target.
+ * Marks the transmission as finished (and the target as ready
+ * for the next message).
*
- * @param hc the hashcode to compare our identity to
- * @return the proper bucket index, or #GNUNET_SYSERR
- * on error (same hashcode)
+ * @param cls a `struct Target *`
*/
-static int
-find_bucket (const struct GNUNET_HashCode *hc)
+static void
+send_done_cb (void *cls)
{
- unsigned int bits;
+ struct Target *t = cls;
+ struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
- bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, hc);
- if (bits == MAX_BUCKETS)
+ GNUNET_assert (t->load > 0);
+ t->load--;
+ if (0 < t->load)
+ return;
+ if (t->dropped)
{
- /* How can all bits match? Got my own ID? */
- GNUNET_break (0);
- return GNUNET_SYSERR;
+ GNUNET_free (t);
+ return;
}
- return MAX_BUCKETS - bits - 1;
+ /* move target back to the front */
+ GNUNET_CONTAINER_DLL_remove (pi->t_head,
+ pi->t_tail,
+ t);
+ GNUNET_CONTAINER_DLL_insert (pi->t_head,
+ pi->t_tail,
+ t);
}
/**
- * Function called when #GNUNET_TRANSPORT_offer_hello() is done.
- * Clean up the "oh" field in the @a cls
+ * Send @a msg to @a pi.
*
- * @param cls a `struct ConnectInfo`
+ * @param pi where to send the message
+ * @param msg message to send
*/
static void
-offer_hello_done (void *cls)
-{
- struct ConnectInfo *ci = cls;
-
- ci->oh = NULL;
-}
-
-
-/**
- * Function called for all entries in #all_desired_peers to clean up.
- *
- * @param cls NULL
- * @param peer peer the entry is for
- * @param value the value to remove
- * @return #GNUNET_YES
- */
-static int
-free_connect_info (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- void *value)
+do_send (struct PeerInfo *pi,
+ const struct GNUNET_MessageHeader *msg)
{
- struct ConnectInfo *ci = value;
+ struct Target *t;
- (void) cls;
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
- peer,
- ci));
- if (NULL != ci->sh)
+ for (t = pi->t_head;
+ NULL != t;
+ t = t->next)
+ if (t->load < MAXIMUM_PENDING_PER_PEER)
+ break;
+ if (NULL == t)
{
- GNUNET_ATS_connectivity_suggest_cancel (ci->sh);
- ci->sh = NULL;
+ /* all targets busy, drop message */
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# messages dropped (underlays busy)",
+ 1,
+ GNUNET_NO);
+ return;
}
- if (NULL != ci->oh)
+ t->load++;
+ /* rotate busy targets to the end */
+ if (MAXIMUM_PENDING_PER_PEER == t->load)
{
- GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
- ci->oh = NULL;
+ GNUNET_CONTAINER_DLL_remove (pi->t_head,
+ pi->t_tail,
+ t);
+ GNUNET_CONTAINER_DLL_insert_tail (pi->t_head,
+ pi->t_tail,
+ t);
}
- GNUNET_free (ci);
- return GNUNET_YES;
+ GDS_u_send (t->u,
+ t->utarget,
+ msg,
+ ntohs (msg->size),
+ &send_done_cb,
+ t);
}
/**
- * Consider if we want to connect to a given peer, and if so
- * let ATS know. If applicable, the HELLO is offered to the
- * TRANSPORT service.
+ * Sign that we are routing a message from @a pred to @a succ.
+ * (So the route is $PRED->us->$SUCC).
*
- * @param pid peer to consider connectivity requirements for
- * @param h a HELLO message, or NULL
+ * @param key key of the data (not necessarily the query hash)
+ * @param data payload (the block)
+ * @param data_size number of bytes in @a data
+ * @param exp_time expiration time of @a data
+ * @param pred predecessor peer ID
+ * @param succ successor peer ID
+ * @param[out] sig where to write the signature
+ * (of purpose #GNUNET_SIGNATURE_PURPOSE_DHT_PUT_HOP)
*/
static void
-try_connect (const struct GNUNET_PeerIdentity *pid,
- const struct GNUNET_MessageHeader *h)
+sign_path (const void *data,
+ size_t data_size,
+ struct GNUNET_TIME_Absolute exp_time,
+ const struct GNUNET_PeerIdentity *pred,
+ const struct GNUNET_PeerIdentity *succ,
+ struct GNUNET_CRYPTO_EddsaSignature *sig)
{
- int bucket;
- struct GNUNET_HashCode pid_hash;
- struct ConnectInfo *ci;
- uint32_t strength;
-
- GNUNET_CRYPTO_hash (pid,
- sizeof(struct GNUNET_PeerIdentity),
- &pid_hash);
- bucket = find_bucket (&pid_hash);
- if (bucket < 0)
- return; /* self? */
- ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
- pid);
+ struct GNUNET_DHT_HopSignature hs = {
+ .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DHT_HOP),
+ .purpose.size = htonl (sizeof (hs)),
+ .expiration_time = GNUNET_TIME_absolute_hton (exp_time),
+ .succ = *succ
+ };
- if (k_buckets[bucket].peers_size < bucket_size)
- strength = (bucket_size - k_buckets[bucket].peers_size) * bucket;
- else
- strength = bucket; /* minimum value of connectivity */
- if (GNUNET_YES ==
- GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
- pid))
- strength *= 2; /* double for connected peers */
- else if (k_buckets[bucket].peers_size > bucket_size)
- strength = 0; /* bucket full, we really do not care about more */
-
- if ((0 == strength) &&
- (NULL != ci))
- {
- /* release request */
- GNUNET_assert (GNUNET_YES ==
- free_connect_info (NULL,
- pid,
- ci));
- return;
- }
- if (NULL == ci)
- {
- ci = GNUNET_new (struct ConnectInfo);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
- pid,
- ci,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- }
- if ((NULL != ci->oh) &&
- (NULL != h))
- GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
- if (NULL != h)
- ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg,
- h,
- &offer_hello_done,
- ci);
- if ((NULL != ci->sh) &&
- (ci->strength != strength))
- GNUNET_ATS_connectivity_suggest_cancel (ci->sh);
- if (ci->strength != strength)
- ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch,
- pid,
- strength);
- ci->strength = strength;
+ if (NULL != pred)
+ hs.pred = *pred;
+ GNUNET_CRYPTO_hash (data,
+ data_size,
+ &hs.h_data);
+ GNUNET_CRYPTO_eddsa_sign (&GDS_my_private_key,
+ &hs,
+ sig);
}
/**
- * Function called for each peer in #all_desired_peers during
- * #update_connect_preferences() if we have reason to adjust
- * the strength of our desire to keep connections to certain
- * peers. Calls #try_connect() to update the calculations for
- * the given @a pid.
+ * Find the optimal bucket for this key.
*
- * @param cls NULL
- * @param pid peer to update
- * @param value unused
- * @return #GNUNET_YES (continue to iterate)
+ * @param hc the hashcode to compare our identity to
+ * @return the proper bucket index, or -1
+ * on error (same hashcode)
*/
static int
-update_desire_strength (void *cls,
- const struct GNUNET_PeerIdentity *pid,
- void *value)
+find_bucket (const struct GNUNET_HashCode *hc)
{
- (void) cls;
- (void) value;
- try_connect (pid,
- NULL);
- return GNUNET_YES;
-}
-
+ struct GNUNET_HashCode xor;
+ unsigned int bits;
-/**
- * Update our preferences for connectivity as given to ATS.
- *
- * @param cls the `struct PeerInfo` of the peer
- * @param tc scheduler context.
- */
-static void
-update_connect_preferences ()
-{
- GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
- &update_desire_strength,
- NULL);
+ GNUNET_CRYPTO_hash_xor (hc,
+ &GDS_my_identity_hash,
+ &xor);
+ bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
+ if (bits == MAX_BUCKETS)
+ {
+ /* How can all bits match? Got my own ID? */
+ GNUNET_break (0);
+ return -1;
+ }
+ return MAX_BUCKETS - bits - 1;
}
/**
- * Add each of the peers we already know to the bloom filter of
+ * Add each of the peers we already know to the Bloom filter of
* the request so that we don't get duplicate HELLOs.
*
* @param cls the `struct GNUNET_BLOCK_Group`
* @param key peer identity to add to the bloom filter
- * @param value value the peer information (unused)
+ * @param value the peer information
* @return #GNUNET_YES (we should continue to iterate)
*/
-static int
+static enum GNUNET_GenericReturnValue
add_known_to_bloom (void *cls,
const struct GNUNET_PeerIdentity *key,
void *value)
{
struct GNUNET_BLOCK_Group *bg = cls;
- struct GNUNET_HashCode key_hash;
+ struct PeerInfo *pi = value;
- (void) cls;
- (void) value;
- GNUNET_CRYPTO_hash (key,
- sizeof(struct GNUNET_PeerIdentity),
- &key_hash);
GNUNET_BLOCK_group_set_seen (bg,
- &key_hash,
+ &pi->phash,
1);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding known peer (%s) to bloomfilter for FIND PEER\n",
+ "Adding known peer (%s) to Bloom filter for FIND PEER\n",
GNUNET_i2s (key));
return GNUNET_YES;
}
@@ -640,191 +618,263 @@ add_known_to_bloom (void *cls,
* so that we can find the closest peers in the network to ourselves
* and attempt to connect to them.
*
- * @param cls closure for this task
+ * @param cls closure for this task, NULL
*/
static void
send_find_peer_message (void *cls)
{
- struct GNUNET_TIME_Relative next_send_time;
- struct GNUNET_BLOCK_Group *bg;
- struct GNUNET_CONTAINER_BloomFilter *peer_bf;
-
(void) cls;
- find_peer_task = NULL;
- if (newly_found_peers > bucket_size)
+
+ /* Compute when to do this again (and if we should
+ even send a message right now) */
{
- /* If we are finding many peers already, no need to send out our request right now! */
+ struct GNUNET_TIME_Relative next_send_time;
+ bool done_early;
+
+ find_peer_task = NULL;
+ done_early = (newly_found_peers > bucket_size);
+ /* schedule next round, taking longer if we found more peers
+ in the last round. */
+ next_send_time.rel_value_us =
+ DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us
+ + GNUNET_CRYPTO_random_u64 (
+ GNUNET_CRYPTO_QUALITY_WEAK,
+ GNUNET_TIME_relative_multiply (
+ DHT_AVG_FIND_PEER_INTERVAL,
+ 1 + 100 * (1 + newly_found_peers) / bucket_size).rel_value_us);
+ newly_found_peers = 0;
+ GNUNET_assert (NULL == find_peer_task);
find_peer_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
+ GNUNET_SCHEDULER_add_delayed (next_send_time,
&send_find_peer_message,
NULL);
- newly_found_peers = 0;
- return;
+ if (done_early)
+ return;
+ }
+
+ /* actually send 'find peer' request */
+ {
+ struct GNUNET_BLOCK_Group *bg;
+ struct GNUNET_CONTAINER_BloomFilter *peer_bf;
+
+ bg = GNUNET_BLOCK_group_create (GDS_block_context,
+ GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ NULL,
+ 0,
+ "filter-size",
+ DHT_BLOOM_SIZE,
+ NULL);
+ GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers,
+ &add_known_to_bloom,
+ bg);
+ peer_bf
+ = GNUNET_CONTAINER_bloomfilter_init (NULL,
+ DHT_BLOOM_SIZE,
+ GNUNET_CONSTANTS_BLOOMFILTER_K);
+ if (GNUNET_OK !=
+ GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ GNUNET_DHT_RO_FIND_APPROXIMATE
+ | GNUNET_DHT_RO_RECORD_ROUTE,
+ FIND_PEER_REPLICATION_LEVEL,
+ 0, /* hop count */
+ &GDS_my_identity_hash,
+ NULL, 0, /* xquery */
+ bg,
+ peer_bf))
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# Failed to initiate FIND PEER lookup",
+ 1,
+ GNUNET_NO);
+ }
+ else
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# FIND PEER messages initiated",
+ 1,
+ GNUNET_NO);
+ }
+ GNUNET_CONTAINER_bloomfilter_free (peer_bf);
+ GNUNET_BLOCK_group_destroy (bg);
}
- bg = GNUNET_BLOCK_group_create (GDS_block_context,
- GNUNET_BLOCK_TYPE_DHT_HELLO,
- GNUNET_CRYPTO_random_u32 (
- GNUNET_CRYPTO_QUALITY_WEAK,
- UINT32_MAX),
- NULL,
- 0,
- "filter-size",
- DHT_BLOOM_SIZE,
- NULL);
- GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers,
- &add_known_to_bloom,
- bg);
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# FIND PEER messages initiated"),
- 1,
- GNUNET_NO);
- peer_bf
- = GNUNET_CONTAINER_bloomfilter_init (NULL,
- DHT_BLOOM_SIZE,
- GNUNET_CONSTANTS_BLOOMFILTER_K);
- // FIXME: pass priority!?
- GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO,
- GNUNET_DHT_RO_FIND_PEER
- | GNUNET_DHT_RO_RECORD_ROUTE,
- FIND_PEER_REPLICATION_LEVEL,
- 0,
- &my_identity_hash,
- NULL,
- 0,
- bg,
- peer_bf);
- GNUNET_CONTAINER_bloomfilter_free (peer_bf);
- GNUNET_BLOCK_group_destroy (bg);
- /* schedule next round */
- next_send_time.rel_value_us =
- DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us
- + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
- DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us
- / (newly_found_peers + 1));
- newly_found_peers = 0;
- GNUNET_assert (NULL == find_peer_task);
- find_peer_task =
- GNUNET_SCHEDULER_add_delayed (next_send_time,
- &send_find_peer_message,
- NULL);
}
/**
- * Method called whenever a peer connects.
+ * The list of the first #bucket_size peers of @a bucket
+ * changed. We should thus make sure we have called 'hold'
+ * all of the first bucket_size peers!
*
- * @param cls closure
- * @param peer peer identity this notification is about
- * @param mq message queue for sending messages to @a peer
- * @return our `struct PeerInfo` for @a peer
+ * @param[in,out] bucket the bucket where the peer set changed
*/
-static void *
-handle_core_connect (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- struct GNUNET_MQ_Handle *mq)
+static void
+update_hold (struct PeerBucket *bucket)
{
+ unsigned int off = 0;
+
+ /* find the peer -- we just go over all of them, should
+ be hardly any more expensive than just finding the 'right'
+ one. */
+ for (struct PeerInfo *pos = bucket->head;
+ NULL != pos;
+ pos = pos->next)
+ {
+ if (off > bucket_size)
+ break; /* We only hold up to #bucket_size peers per bucket */
+ off++;
+ for (struct Target *tp = pos->t_head;
+ NULL != tp;
+ tp = tp->next)
+ if (NULL == tp->ph)
+ tp->ph = GDS_u_hold (tp->u,
+ tp->utarget);
+ }
+}
+
+
+void
+GDS_u_connect (void *cls,
+ struct GNUNET_DHTU_Target *target,
+ const struct GNUNET_PeerIdentity *pid,
+ void **ctx)
+{
+ struct GDS_Underlay *u = cls;
struct PeerInfo *pi;
+ struct PeerBucket *bucket;
+ bool do_hold = false;
- (void) cls;
/* Check for connect to self message */
- if (0 == GNUNET_memcmp (&my_identity,
- peer))
- return NULL;
+ if (0 == GNUNET_memcmp (&GDS_my_identity,
+ pid))
+ return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connected to %s\n",
- GNUNET_i2s (peer));
- GNUNET_assert (GNUNET_NO ==
- GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
- peer));
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# peers connected"),
- 1,
- GNUNET_NO);
- pi = GNUNET_new (struct PeerInfo);
- pi->id = peer;
- pi->mq = mq;
- GNUNET_CRYPTO_hash (peer,
- sizeof(struct GNUNET_PeerIdentity),
- &pi->phash);
- pi->peer_bucket = find_bucket (&pi->phash);
- GNUNET_assert ((pi->peer_bucket >= 0) &&
- ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
- GNUNET_CONTAINER_DLL_insert_tail (k_buckets[pi->peer_bucket].head,
- k_buckets[pi->peer_bucket].tail,
- pi);
- k_buckets[pi->peer_bucket].peers_size++;
- closest_bucket = GNUNET_MAX (closest_bucket,
- (unsigned int) pi->peer_bucket);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
- pi->id,
- pi,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- if ((pi->peer_bucket > 0) &&
- (k_buckets[pi->peer_bucket].peers_size <= bucket_size))
- {
- update_connect_preferences ();
- newly_found_peers++;
+ "Connected to peer %s\n",
+ GNUNET_i2s (pid));
+ pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
+ pid);
+ if (NULL == pi)
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# peers connected",
+ 1,
+ GNUNET_NO);
+ pi = GNUNET_new (struct PeerInfo);
+ pi->id = *pid;
+ GNUNET_CRYPTO_hash (pid,
+ sizeof(*pid),
+ &pi->phash);
+ pi->peer_bucket = find_bucket (&pi->phash);
+ GNUNET_assert ( (pi->peer_bucket >= 0) &&
+ ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
+ bucket = &k_buckets[pi->peer_bucket];
+ GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
+ bucket->tail,
+ pi);
+ bucket->peers_size++;
+ closest_bucket = GNUNET_MAX (closest_bucket,
+ (unsigned int) pi->peer_bucket + 1);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
+ &pi->id,
+ pi,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ if (bucket->peers_size <= bucket_size)
+ {
+ newly_found_peers++;
+ do_hold = true;
+ }
+ if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
+ (GNUNET_YES != disable_try_connect) )
+ {
+ /* got a first connection, good time to start with FIND PEER requests... */
+ GNUNET_assert (NULL == find_peer_task);
+ find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
+ NULL);
+ }
}
- if ((1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
- (GNUNET_YES != disable_try_connect))
{
- /* got a first connection, good time to start with FIND PEER requests... */
- GNUNET_assert (NULL == find_peer_task);
- find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
- NULL);
+ struct Target *t;
+
+ t = GNUNET_new (struct Target);
+ t->u = u;
+ t->utarget = target;
+ t->pi = pi;
+ GNUNET_CONTAINER_DLL_insert (pi->t_head,
+ pi->t_tail,
+ t);
+ *ctx = t;
+
}
- return pi;
+ if (do_hold)
+ update_hold (bucket);
}
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- * @param internal_cls our `struct PeerInfo` for @a peer
- */
-static void
-handle_core_disconnect (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- void *internal_cls)
+void
+GDS_u_disconnect (void *ctx)
{
- struct PeerInfo *to_remove = internal_cls;
+ struct Target *t = ctx;
+ struct PeerInfo *pi;
+ struct PeerBucket *bucket;
+ bool was_held = false;
- (void) cls;
- /* Check for disconnect from self message */
- if (NULL == to_remove)
+ /* Check for disconnect from self message (on shutdown) */
+ if (NULL == t)
return;
+ pi = t->pi;
+ GNUNET_CONTAINER_DLL_remove (pi->t_head,
+ pi->t_tail,
+ t);
+ if (NULL != t->ph)
+ {
+ GDS_u_drop (t->u,
+ t->ph);
+ t->ph = NULL;
+ was_held = true;
+ }
+ if (t->load > 0)
+ {
+ t->dropped = true;
+ t->pi = NULL;
+ }
+ else
+ {
+ GNUNET_free (t);
+ }
+ if (NULL != pi->t_head)
+ return; /* got other connections still */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Disconnected %s\n",
- GNUNET_i2s (peer));
+ "Disconnected from peer %s\n",
+ GNUNET_i2s (&pi->id));
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# peers connected"),
+ "# peers connected",
-1,
GNUNET_NO);
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
- peer,
- to_remove));
- if ((0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
- (GNUNET_YES != disable_try_connect))
+ &pi->id,
+ pi));
+ if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
+ (GNUNET_YES != disable_try_connect))
{
GNUNET_SCHEDULER_cancel (find_peer_task);
find_peer_task = NULL;
}
- GNUNET_assert (to_remove->peer_bucket >= 0);
- GNUNET_CONTAINER_DLL_remove (k_buckets[to_remove->peer_bucket].head,
- k_buckets[to_remove->peer_bucket].tail,
- to_remove);
- GNUNET_assert (k_buckets[to_remove->peer_bucket].peers_size > 0);
- k_buckets[to_remove->peer_bucket].peers_size--;
- while ((closest_bucket > 0) &&
- (0 == k_buckets[to_remove->peer_bucket].peers_size))
+ GNUNET_assert (pi->peer_bucket >= 0);
+ bucket = &k_buckets[pi->peer_bucket];
+ GNUNET_CONTAINER_DLL_remove (bucket->head,
+ bucket->tail,
+ pi);
+ GNUNET_assert (bucket->peers_size > 0);
+ bucket->peers_size--;
+ if ( (was_held) &&
+ (bucket->peers_size >= bucket_size - 1) )
+ update_hold (bucket);
+ while ( (closest_bucket > 0) &&
+ (0 == k_buckets[closest_bucket - 1].peers_size))
closest_bucket--;
- if (k_buckets[to_remove->peer_bucket].peers_size < bucket_size)
- update_connect_preferences ();
- GNUNET_free (to_remove);
+ GNUNET_free (pi->hello);
+ GNUNET_free (pi);
}
@@ -837,23 +887,21 @@ handle_core_disconnect (void *cls,
* @return Some number of peers to forward the message to
*/
static unsigned int
-get_forward_count (uint32_t hop_count,
- uint32_t target_replication)
+get_forward_count (uint16_t hop_count,
+ uint16_t target_replication)
{
uint32_t random_value;
uint32_t forward_count;
float target_value;
+ float rm1;
- if (0 == target_replication)
- target_replication = 1; /* 0 is verboten */
- if (target_replication > MAXIMUM_REPLICATION_LEVEL)
- target_replication = MAXIMUM_REPLICATION_LEVEL;
if (hop_count > GDS_NSE_get () * 4.0)
{
/* forcefully terminate */
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# requests TTL-dropped"),
- 1, GNUNET_NO);
+ "# requests TTL-dropped",
+ 1,
+ GNUNET_NO);
return 0;
}
if (hop_count > GDS_NSE_get () * 2.0)
@@ -861,59 +909,26 @@ get_forward_count (uint32_t hop_count,
/* Once we have reached our ideal number of hops, only forward to 1 peer */
return 1;
}
- /* bound by system-wide maximum */
+ /* bound by system-wide maximum and minimum */
+ if (0 == target_replication)
+ target_replication = 1; /* 0 is verboten */
target_replication =
- GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL, target_replication);
+ GNUNET_MIN (GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL,
+ target_replication);
+ rm1 = target_replication - 1.0;
target_value =
- 1 + (target_replication - 1.0) / (GDS_NSE_get ()
- + ((float) (target_replication - 1.0)
- * hop_count));
-
+ 1 + (rm1) / (GDS_NSE_get () + (rm1 * hop_count));
/* Set forward count to floor of target_value */
forward_count = (uint32_t) target_value;
/* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
target_value = target_value - forward_count;
- random_value =
- GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
+ random_value = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ UINT32_MAX);
if (random_value < (target_value * UINT32_MAX))
forward_count++;
return GNUNET_MIN (forward_count,
- MAXIMUM_REPLICATION_LEVEL);
-}
-
-
-/**
- * Compute the distance between have and target as a 64-bit value.
- * Differences in the lower bits must count stronger than differences
- * in the higher bits.
- *
- * @param target
- * @param have
- * @param bucket up to which offset are @a target and @a have identical and thus those bits should not be considered
- * @return 0 if have==target, otherwise a number
- * that is larger as the distance between
- * the two hash codes increases
- */
-static uint64_t
-get_distance (const struct GNUNET_HashCode *target,
- const struct GNUNET_HashCode *have,
- unsigned int bucket)
-{
- uint64_t lsb = 0;
-
- for (unsigned int i = bucket + 1;
- (i < sizeof(struct GNUNET_HashCode) * 8) &&
- (i < bucket + 1 + 64);
- i++)
- {
- if (GNUNET_CRYPTO_hash_get_bit_rtl (target, i) !=
- GNUNET_CRYPTO_hash_get_bit_rtl (have, i))
- lsb |= (1LLU << (bucket + 64 - i)); /* first bit set will be 1,
- * last bit set will be 63 -- if
- * i does not reach 512 first... */
- }
- return lsb;
+ GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL);
}
@@ -927,60 +942,74 @@ get_distance (const struct GNUNET_HashCode *target,
* @return #GNUNET_YES if node location is closest,
* #GNUNET_NO otherwise.
*/
-int
+enum GNUNET_GenericReturnValue
GDS_am_closest_peer (const struct GNUNET_HashCode *key,
const struct GNUNET_CONTAINER_BloomFilter *bloom)
{
- int bits;
- int other_bits;
- int bucket_num;
- struct PeerInfo *pos;
-
- if (0 == GNUNET_memcmp (&my_identity_hash,
+ if (0 == GNUNET_memcmp (&GDS_my_identity_hash,
key))
return GNUNET_YES;
- bucket_num = find_bucket (key);
- GNUNET_assert (bucket_num >= 0);
- bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
- key);
- pos = k_buckets[bucket_num].head;
- while (NULL != pos)
- {
- if ((NULL != bloom) &&
- (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bloom,
- &pos->phash)))
+ for (int bucket_num = find_bucket (key);
+ bucket_num < closest_bucket;
+ bucket_num++)
+ {
+ unsigned int count = 0;
+
+ GNUNET_assert (bucket_num >= 0);
+ for (struct PeerInfo *pos = k_buckets[bucket_num].head;
+ NULL != pos;
+ pos = pos->next)
{
- pos = pos->next;
- continue; /* Skip already checked entries */
+ if (count >= bucket_size)
+ break; /* we only consider first #bucket_size entries per bucket */
+ count++;
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bloom,
+ &pos->phash)) )
+ continue; /* Ignore filtered peers */
+ /* All peers in this bucket must be closer than us, as
+ they mismatch with our PID on the pivotal bit. So
+ because an unfiltered peer exists, we are not the
+ closest. */
+ int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
+ &GDS_my_identity_hash,
+ key);
+ switch (delta)
+ {
+ case -1: /* pos closer */
+ return GNUNET_NO;
+ case 0: /* identical, impossible! */
+ GNUNET_assert (0);
+ break;
+ case 1: /* I am closer */
+ break;
+ }
}
- other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->phash,
- key);
- if (other_bits > bits)
- return GNUNET_NO;
- if (other_bits == bits) /* We match the same number of bits */
- return GNUNET_YES;
- pos = pos->next;
}
- /* No peers closer, we are the closest! */
+ /* No closer (unfiltered) peers found; we must be the closest! */
return GNUNET_YES;
}
/**
* Select a peer from the routing table that would be a good routing
- * destination for sending a message for "key". The resulting peer
- * must not be in the set of blocked peers.<p>
+ * destination for sending a message for @a key. The resulting peer
+ * must not be in the set of @a bloom blocked peers.
*
* Note that we should not ALWAYS select the closest peer to the
- * target, peers further away from the target should be chosen with
- * exponentially declining probability.
- *
- * FIXME: double-check that this is fine
+ * target, we do a "random" peer selection if the number of @a hops
+ * is below the logarithm of the network size estimate.
*
+ * In all cases, we only consider at most the first #bucket_size peers of any
+ * #k_buckets. The other peers in the bucket are there because GNUnet doesn't
+ * really allow the DHT to "reject" connections, but we only use the first
+ * #bucket_size, even if more exist. (The idea is to ensure that those
+ * connections are frequently used, and for others to be not used by the DHT,
+ * and thus possibly dropped by transport due to disuse).
*
* @param key the key we are selecting a peer to route to
- * @param bloom a bloomfilter containing entries this request has seen already
+ * @param bloom a Bloom filter containing entries this request has seen already
* @param hops how many hops has this message traversed thus far
* @return Peer to route to, or NULL on error
*/
@@ -989,139 +1018,198 @@ select_peer (const struct GNUNET_HashCode *key,
const struct GNUNET_CONTAINER_BloomFilter *bloom,
uint32_t hops)
{
- unsigned int bc;
- unsigned int count;
- unsigned int selected;
- struct PeerInfo *pos;
- struct PeerInfo *chosen;
-
+ if (0 == closest_bucket)
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# Peer selection failed",
+ 1,
+ GNUNET_NO);
+ return NULL; /* we have zero connections */
+ }
if (hops >= GDS_NSE_get ())
{
- /* greedy selection (closest peer that is not in bloomfilter) */
- unsigned int best_bucket = 0;
- uint64_t best_in_bucket = UINT64_MAX;
+ /* greedy selection (closest peer that is not in Bloom filter) */
+ struct PeerInfo *chosen = NULL;
+ int best_bucket;
+ int bucket_offset;
+
+ {
+ struct GNUNET_HashCode xor;
- chosen = NULL;
- for (bc = 0; bc <= closest_bucket; bc++)
+ GNUNET_CRYPTO_hash_xor (key,
+ &GDS_my_identity_hash,
+ &xor);
+ best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
+ }
+ if (best_bucket >= closest_bucket)
+ bucket_offset = closest_bucket - 1;
+ else
+ bucket_offset = best_bucket;
+ while (-1 != bucket_offset)
{
- count = 0;
- for (pos = k_buckets[bc].head;
- (pos != NULL) &&
- (count < bucket_size);
+ struct PeerBucket *bucket = &k_buckets[bucket_offset];
+ unsigned int count = 0;
+
+ for (struct PeerInfo *pos = bucket->head;
+ NULL != pos;
pos = pos->next)
{
- unsigned int bucket;
- uint64_t dist;
-
- bucket = GNUNET_CRYPTO_hash_matching_bits (key,
- &pos->phash);
- dist = get_distance (key,
- &pos->phash,
- bucket);
- if (bucket < best_bucket)
- continue;
- if (dist > best_in_bucket)
- continue;
- best_bucket = bucket;
- best_in_bucket = dist;
- if ( (NULL == bloom) ||
- (GNUNET_NO ==
+ if (count >= bucket_size)
+ break; /* we only consider first #bucket_size entries per bucket */
+ count++;
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
GNUNET_CONTAINER_bloomfilter_test (bloom,
&pos->phash)) )
{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Excluded peer `%s' due to BF match in greedy routing for %s\n",
+ GNUNET_i2s (&pos->id),
+ GNUNET_h2s (key));
+ continue;
+ }
+ if (NULL == chosen)
+ {
+ /* First candidate */
chosen = pos;
}
else
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Excluded peer `%s' due to BF match in greedy routing for %s\n",
- GNUNET_i2s (pos->id),
- GNUNET_h2s (key));
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# Peers excluded from routing due to Bloomfilter"),
- 1,
- GNUNET_NO);
- chosen = NULL;
+ int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
+ &chosen->phash,
+ key);
+ switch (delta)
+ {
+ case -1: /* pos closer */
+ chosen = pos;
+ break;
+ case 0: /* identical, impossible! */
+ GNUNET_assert (0);
+ break;
+ case 1: /* chosen closer */
+ break;
+ }
}
count++;
+ } /* for all (#bucket_size) peers in bucket */
+ if (NULL != chosen)
+ break;
+
+ /* If we chose nothing in first iteration, first go through deeper
+ buckets (best chance to find a good match), and if we still found
+ nothing, then to shallower buckets. Terminate on any match in the
+ current bucket, as this search order guarantees that it can only get
+ worse as we keep going. */
+ if (bucket_offset > best_bucket)
+ {
+ /* Go through more deeper buckets */
+ bucket_offset++;
+ if (bucket_offset == closest_bucket)
+ {
+ /* Can't go any deeper, if nothing selected,
+ go for shallower buckets */
+ bucket_offset = best_bucket - 1;
+ }
}
- }
+ else
+ {
+ /* We're either at the 'best_bucket' or already moving
+ on to shallower buckets. */
+ if (bucket_offset == best_bucket)
+ bucket_offset++; /* go for deeper buckets */
+ else
+ bucket_offset--; /* go for shallower buckets */
+ }
+ } /* for applicable buckets (starting at best match) */
if (NULL == chosen)
+ {
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# Peer selection failed"),
+ "# Peer selection failed",
1,
GNUNET_NO);
- else
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Selected peer `%s' in greedy routing for %s\n",
- GNUNET_i2s (chosen->id),
- GNUNET_h2s (key));
+ return NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Selected peer `%s' in greedy routing for %s\n",
+ GNUNET_i2s (&chosen->id),
+ GNUNET_h2s (key));
return chosen;
- }
+ } /* end of 'greedy' peer selection */
/* select "random" peer */
- /* count number of peers that are available and not filtered */
- count = 0;
- for (bc = 0; bc <= closest_bucket; bc++)
+ /* count number of peers that are available and not filtered,
+ but limit to at most #bucket_size peers, starting with
+ those 'furthest' from us. */
{
- pos = k_buckets[bc].head;
- while ((NULL != pos) && (count < bucket_size))
+ unsigned int total = 0;
+ unsigned int selected;
+
+ for (unsigned int bc = 0; bc < closest_bucket; bc++)
{
- if ((NULL != bloom) &&
- (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bloom,
- &pos->phash)))
+ struct PeerBucket *bucket = &k_buckets[bc];
+ unsigned int count = 0;
+
+ for (struct PeerInfo *pos = bucket->head;
+ NULL != pos;
+ pos = pos->next)
{
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- (
- "# Peers excluded from routing due to Bloomfilter"),
- 1, GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Excluded peer `%s' due to BF match in random routing for %s\n",
- GNUNET_i2s (pos->id),
- GNUNET_h2s (key));
- pos = pos->next;
- continue; /* Ignore bloomfiltered peers */
- }
- count++;
- pos = pos->next;
+ count++;
+ if (count > bucket_size)
+ break; /* limits search to #bucket_size peers per bucket */
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bloom,
+ &pos->phash)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Excluded peer `%s' due to BF match in random routing for %s\n",
+ GNUNET_i2s (&pos->id),
+ GNUNET_h2s (key));
+ continue; /* Ignore filtered peers */
+ }
+ total++;
+ } /* for all peers in bucket */
+ } /* for all buckets */
+ if (0 == total) /* No peers to select from! */
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# Peer selection failed",
+ 1,
+ GNUNET_NO);
+ return NULL;
}
- }
- if (0 == count) /* No peers to select from! */
- {
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# Peer selection failed"), 1,
- GNUNET_NO);
- return NULL;
- }
- /* Now actually choose a peer */
- selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- count);
- count = 0;
- for (bc = 0; bc <= closest_bucket; bc++)
- {
- for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size));
- pos = pos->next)
+
+ /* Now actually choose a peer */
+ selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ total);
+ for (unsigned int bc = 0; bc < closest_bucket; bc++)
{
- if ((bloom != NULL) &&
- (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bloom,
- &pos->phash)))
- {
- continue; /* Ignore bloomfiltered peers */
- }
- if (0 == selected--)
+ unsigned int count = 0;
+
+ for (struct PeerInfo *pos = k_buckets[bc].head;
+ pos != NULL;
+ pos = pos->next)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Selected peer `%s' in random routing for %s\n",
- GNUNET_i2s (pos->id),
- GNUNET_h2s (key));
- return pos;
- }
- }
- }
+ count++;
+ if (count > bucket_size)
+ break; /* limits search to #bucket_size peers per bucket */
+
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bloom,
+ &pos->phash)) )
+ continue; /* Ignore bloomfiltered peers */
+ if (0 == selected--)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Selected peer `%s' in random routing for %s\n",
+ GNUNET_i2s (&pos->id),
+ GNUNET_h2s (key));
+ return pos;
+ }
+ } /* for peers in bucket */
+ } /* for all buckets */
+ } /* random peer selection scope */
GNUNET_break (0);
return NULL;
}
@@ -1132,38 +1220,39 @@ select_peer (const struct GNUNET_HashCode *key,
* forwarded to.
*
* @param key routing key
- * @param bloom bloom filter excluding peers as targets, all selected
- * peers will be added to the bloom filter
+ * @param[in,out] bloom Bloom filter excluding peers as targets,
+ * all selected peers will be added to the Bloom filter
* @param hop_count number of hops the request has traversed so far
* @param target_replication desired number of replicas
- * @param targets where to store an array of target peers (to be
- * free'd by the caller)
- * @return number of peers returned in 'targets'.
+ * @param[out] targets where to store an array of target peers (to be
+ * free()ed by the caller)
+ * @return number of peers returned in @a targets.
*/
static unsigned int
get_target_peers (const struct GNUNET_HashCode *key,
struct GNUNET_CONTAINER_BloomFilter *bloom,
- uint32_t hop_count,
- uint32_t target_replication,
+ uint16_t hop_count,
+ uint16_t target_replication,
struct PeerInfo ***targets)
{
- unsigned int ret;
+ unsigned int target;
unsigned int off;
struct PeerInfo **rtargets;
- struct PeerInfo *nxt;
GNUNET_assert (NULL != bloom);
- ret = get_forward_count (hop_count,
- target_replication);
- if (0 == ret)
+ target = get_forward_count (hop_count,
+ target_replication);
+ if (0 == target)
{
*targets = NULL;
return 0;
}
- rtargets = GNUNET_new_array (ret,
+ rtargets = GNUNET_new_array (target,
struct PeerInfo *);
- for (off = 0; off < ret; off++)
+ for (off = 0; off < target; off++)
{
+ struct PeerInfo *nxt;
+
nxt = select_peer (key,
bloom,
hop_count);
@@ -1182,7 +1271,7 @@ get_target_peers (const struct GNUNET_HashCode *key,
GNUNET_CONTAINER_multipeermap_size (all_connected_peers),
(unsigned int) hop_count,
GNUNET_h2s (key),
- ret);
+ target);
if (0 == off)
{
GNUNET_free (rtargets);
@@ -1194,67 +1283,153 @@ get_target_peers (const struct GNUNET_HashCode *key,
"Forwarding query `%s' to %u peers (goal was %u peers)\n",
GNUNET_h2s (key),
off,
- ret);
+ target);
return off;
}
/**
- * Perform a PUT operation. Forwards the given request to other
- * peers. Does not store the data locally. Does not give the
- * data to local clients. May do nothing if this is the only
- * peer in the network (or if we are the closest peer in the
- * network).
+ * If we got a HELLO, consider it for our own routing table
*
- * @param type type of the block
- * @param options routing options
- * @param desired_replication_level desired replication count
- * @param expiration_time when does the content expire
- * @param hop_count how many hops has this message traversed so far
- * @param bf Bloom filter of peers this PUT has already traversed
- * @param key key for the content
- * @param put_path_length number of entries in @a put_path
- * @param put_path peers this request has traversed so far (if tracked)
- * @param data payload to store
- * @param data_size number of bytes in @a data
- * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
+ * @param bd block data we got
*/
-int
-GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
- enum GNUNET_DHT_RouteOption options,
- uint32_t desired_replication_level,
- struct GNUNET_TIME_Absolute expiration_time,
- uint32_t hop_count,
- struct GNUNET_CONTAINER_BloomFilter *bf,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- struct GNUNET_PeerIdentity *put_path,
- const void *data,
- size_t data_size)
+static void
+hello_check (const struct GNUNET_DATACACHE_Block *bd)
+{
+ struct GNUNET_PeerIdentity pid;
+ struct GNUNET_HELLO_Builder *b;
+
+ if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO != bd->type)
+ return;
+
+ b = GNUNET_HELLO_builder_from_block (bd->data,
+ bd->data_size);
+ if (GNUNET_YES != disable_try_connect)
+ GNUNET_HELLO_builder_iterate (b,
+ &pid,
+ &GDS_try_connect,
+ &pid);
+ GNUNET_HELLO_builder_free (b);
+}
+
+
+enum GNUNET_GenericReturnValue
+GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
+ uint16_t desired_replication_level,
+ uint16_t hop_count,
+ struct GNUNET_CONTAINER_BloomFilter *bf)
{
unsigned int target_count;
- unsigned int i;
struct PeerInfo **targets;
- struct PeerInfo *target;
size_t msize;
- struct GNUNET_MQ_Envelope *env;
- struct PeerPutMessage *ppm;
- struct GNUNET_PeerIdentity *pp;
unsigned int skip_count;
+ enum GNUNET_DHT_RouteOption ro = bd->ro;
+ unsigned int put_path_length = bd->put_path_length;
+ const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
+ const struct GNUNET_PeerIdentity *trunc_peer
+ = truncated
+ ? &bd->trunc_peer
+ : NULL;
+
+#if SANITY_CHECKS > 1
+ unsigned int failure_offset;
+
+ failure_offset
+ = GNUNET_DHT_verify_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ trunc_peer,
+ put_path,
+ put_path_length,
+ NULL, 0, /* get_path */
+ &GDS_my_identity);
+ if (0 != failure_offset)
+ {
+ GNUNET_break_op (0);
+ truncated = true;
+ trunc_peer = &put_path[failure_offset - 1].pred;
+ put_path = &put_path[failure_offset];
+ put_path_length = put_path_length - failure_offset;
+ ro |= GNUNET_DHT_RO_TRUNCATED;
+ }
+#endif
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding myself (%s) to PUT bloomfilter for %s with RO(%s/%s)\n",
+ GNUNET_i2s (&GDS_my_identity),
+ GNUNET_h2s (&bd->key),
+ (bd->ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
+ (bd->ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
+ /* if we got a HELLO, consider it for our own routing table */
+ hello_check (bd);
GNUNET_assert (NULL != bf);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding myself (%s) to PUT bloomfilter for %s\n",
- GNUNET_i2s (&my_identity),
- GNUNET_h2s (key));
GNUNET_CONTAINER_bloomfilter_add (bf,
- &my_identity_hash);
+ &GDS_my_identity_hash);
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# PUT requests routed"),
+ "# PUT requests routed",
1,
GNUNET_NO);
+ if (bd->data_size
+ > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
+ - sizeof(struct PeerPutMessage))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ msize = bd->data_size + sizeof(struct PeerPutMessage);
+ if (tracking)
+ {
+ if (msize + sizeof (struct GNUNET_CRYPTO_EddsaSignature)
+ > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Discarding message that is too large due to tracking\n");
+ return GNUNET_NO;
+ }
+ msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
+ }
+ else
+ {
+ /* If tracking is disabled, also discard any path we might have
+ gotten from some broken peer */
+ GNUNET_break_op (0 == put_path_length);
+ put_path_length = 0;
+ }
+ if (truncated)
+ msize += sizeof (struct GNUNET_PeerIdentity);
+ if (msize + put_path_length * sizeof(struct GNUNET_DHT_PathElement)
+ > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
+ {
+ unsigned int mlen;
+ unsigned int ppl;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Truncating path that is too large due\n");
+ mlen = GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE - msize;
+ if (! truncated)
+ {
+ /* We need extra space for the truncation, consider that,
+ too! */
+ truncated = true;
+ mlen -= sizeof (struct GNUNET_PeerIdentity);
+ msize += sizeof (struct GNUNET_PeerIdentity);
+ }
+ /* compute maximum length of path we can keep */
+ ppl = mlen / sizeof (struct GNUNET_DHT_PathElement);
+ GNUNET_assert (put_path_length - ppl > 0);
+ trunc_peer = &put_path[put_path_length - ppl - 1].pred;
+ put_path = &put_path[put_path_length - ppl];
+ put_path_length = ppl;
+ ro |= GNUNET_DHT_RO_TRUNCATED;
+ }
+ else
+ {
+ msize += bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement);
+ }
target_count
- = get_target_peers (key,
+ = get_target_peers (&bd->key,
bf,
hop_count,
desired_replication_level,
@@ -1263,59 +1438,34 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing PUT for %s terminates after %u hops at %s\n",
- GNUNET_h2s (key),
+ GNUNET_h2s (&bd->key),
(unsigned int) hop_count,
- GNUNET_i2s (&my_identity));
+ GNUNET_i2s (&GDS_my_identity));
return GNUNET_NO;
}
- msize = put_path_length * sizeof(struct GNUNET_PeerIdentity) + data_size;
- if (msize + sizeof(struct PeerPutMessage)
- >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
- {
- put_path_length = 0;
- msize = data_size;
- }
- if (msize + sizeof(struct PeerPutMessage)
- >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- GNUNET_free (targets);
- return GNUNET_NO;
- }
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# PUT messages queued for transmission"),
- target_count,
- GNUNET_NO);
skip_count = 0;
- for (i = 0; i < target_count; i++)
+ for (unsigned int i = 0; i < target_count; i++)
{
- target = targets[i];
- if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
- {
- /* skip */
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# P2P messages dropped due to full queue"),
- 1,
- GNUNET_NO);
- skip_count++;
- continue;
- }
+ struct PeerInfo *target = targets[i];
+ struct PeerPutMessage *ppm;
+ char buf[msize] GNUNET_ALIGN;
+ struct GNUNET_DHT_PathElement *pp;
+ void *data;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing PUT for %s after %u hops to %s\n",
- GNUNET_h2s (key),
+ GNUNET_h2s (&bd->key),
(unsigned int) hop_count,
- GNUNET_i2s (target->id));
- env = GNUNET_MQ_msg_extra (ppm,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
- ppm->options = htonl (options);
- ppm->type = htonl (type);
- ppm->hop_count = htonl (hop_count + 1);
- ppm->desired_replication_level = htonl (desired_replication_level);
- ppm->put_path_length = htonl (put_path_length);
- ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
+ GNUNET_i2s (&target->id));
+ ppm = (struct PeerPutMessage *) buf;
+ ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
+ ppm->header.size = htons (sizeof (buf));
+ ppm->type = htonl (bd->type);
+ ppm->options = htons (ro);
+ ppm->hop_count = htons (hop_count + 1);
+ ppm->desired_replication_level = htons (desired_replication_level);
+ ppm->put_path_length = htons (put_path_length);
+ ppm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
GNUNET_break (GNUNET_YES ==
GNUNET_CONTAINER_bloomfilter_test (bf,
&target->phash));
@@ -1323,44 +1473,82 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
GNUNET_CONTAINER_bloomfilter_get_raw_data (bf,
ppm->bloomfilter,
DHT_BLOOM_SIZE));
- ppm->key = *key;
- pp = (struct GNUNET_PeerIdentity *) &ppm[1];
+ ppm->key = bd->key;
+ if (truncated)
+ {
+ void *tgt = &ppm[1];
+
+ GNUNET_memcpy (tgt,
+ trunc_peer,
+ sizeof (struct GNUNET_PeerIdentity));
+ pp = (struct GNUNET_DHT_PathElement *)
+ (tgt + sizeof (struct GNUNET_PeerIdentity));
+ }
+ else
+ {
+ pp = (struct GNUNET_DHT_PathElement *) &ppm[1];
+ }
GNUNET_memcpy (pp,
put_path,
- sizeof(struct GNUNET_PeerIdentity) * put_path_length);
- GNUNET_memcpy (&pp[put_path_length],
- data,
- data_size);
- GNUNET_MQ_send (target->mq,
- env);
+ sizeof (struct GNUNET_DHT_PathElement) * put_path_length);
+ if (tracking)
+ {
+ void *tgt = &pp[put_path_length];
+ struct GNUNET_CRYPTO_EddsaSignature last_sig;
+
+ if (0 == put_path_length)
+ {
+ /* Note that the signature in 'put_path' was not initialized before,
+ so this is crucial to avoid sending garbage. */
+ sign_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ trunc_peer,
+ &target->id,
+ &last_sig);
+ }
+ else
+ {
+ sign_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ &pp[put_path_length - 1].pred,
+ &target->id,
+ &last_sig);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Signing PUT PATH %u => %s\n",
+ put_path_length,
+ GNUNET_B2S (&last_sig));
+ memcpy (tgt,
+ &last_sig,
+ sizeof (last_sig));
+ data = tgt + sizeof (last_sig);
+ }
+ else /* ! tracking */
+ {
+ data = &ppm[1];
+ }
+ GNUNET_memcpy (data,
+ bd->data,
+ bd->data_size);
+ do_send (target,
+ &ppm->header);
}
GNUNET_free (targets);
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# PUT messages queued for transmission",
+ target_count - skip_count,
+ GNUNET_NO);
return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
}
-/**
- * Perform a GET operation. Forwards the given request to other
- * peers. Does not lookup the key locally. May do nothing if this is
- * the only peer in the network (or if we are the closest peer in the
- * network).
- *
- * @param type type of the block
- * @param options routing options
- * @param desired_replication_level desired replication count
- * @param hop_count how many hops did this request traverse so far?
- * @param key key for the content
- * @param xquery extended query
- * @param xquery_size number of bytes in @a xquery
- * @param bg group to use for filtering replies
- * @param peer_bf filter for peers not to select (again)
- * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
- */
-int
+enum GNUNET_GenericReturnValue
GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
enum GNUNET_DHT_RouteOption options,
- uint32_t desired_replication_level,
- uint32_t hop_count,
+ uint16_t desired_replication_level,
+ uint16_t hop_count,
const struct GNUNET_HashCode *key,
const void *xquery,
size_t xquery_size,
@@ -1369,19 +1557,14 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
{
unsigned int target_count;
struct PeerInfo **targets;
- struct PeerInfo *target;
- struct GNUNET_MQ_Envelope *env;
size_t msize;
- struct PeerGetMessage *pgm;
- char *xq;
- size_t reply_bf_size;
- void *reply_bf;
+ size_t result_filter_size;
+ void *result_filter;
unsigned int skip_count;
- uint32_t bf_nonce;
GNUNET_assert (NULL != peer_bf);
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# GET requests routed"),
+ "# GET requests routed",
1,
GNUNET_NO);
target_count = get_target_peers (key,
@@ -1390,73 +1573,61 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
desired_replication_level,
&targets);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding myself (%s) to GET bloomfilter for %s\n",
- GNUNET_i2s (&my_identity),
- GNUNET_h2s (key));
+ "Adding myself (%s) to GET bloomfilter for %s with RO(%s/%s)\n",
+ GNUNET_i2s (&GDS_my_identity),
+ GNUNET_h2s (key),
+ (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
+ (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
+
GNUNET_CONTAINER_bloomfilter_add (peer_bf,
- &my_identity_hash);
+ &GDS_my_identity_hash);
if (0 == target_count)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing GET for %s terminates after %u hops at %s\n",
GNUNET_h2s (key),
(unsigned int) hop_count,
- GNUNET_i2s (&my_identity));
+ GNUNET_i2s (&GDS_my_identity));
return GNUNET_NO;
}
if (GNUNET_OK !=
GNUNET_BLOCK_group_serialize (bg,
- &bf_nonce,
- &reply_bf,
- &reply_bf_size))
- {
- reply_bf = NULL;
- reply_bf_size = 0;
- bf_nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- UINT32_MAX);
+ &result_filter,
+ &result_filter_size))
+ {
+ result_filter = NULL;
+ result_filter_size = 0;
}
- msize = xquery_size + reply_bf_size;
+ msize = xquery_size + result_filter_size;
if (msize + sizeof(struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
- GNUNET_free (reply_bf);
+ GNUNET_free (result_filter);
GNUNET_free (targets);
return GNUNET_NO;
}
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# GET messages queued for transmission"),
- target_count,
- GNUNET_NO);
/* forward request */
skip_count = 0;
for (unsigned int i = 0; i < target_count; i++)
{
- target = targets[i];
- if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
- {
- /* skip */
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# P2P messages dropped due to full queue"),
- 1, GNUNET_NO);
- skip_count++;
- continue;
- }
+ struct PeerInfo *target = targets[i];
+ struct PeerGetMessage *pgm;
+ char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
+ char *rf;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing GET for %s after %u hops to %s\n",
GNUNET_h2s (key),
(unsigned int) hop_count,
- GNUNET_i2s (target->id));
- env = GNUNET_MQ_msg_extra (pgm,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
- pgm->options = htonl (options);
+ GNUNET_i2s (&target->id));
+ pgm = (struct PeerGetMessage *) buf;
+ pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
+ pgm->header.size = htons (sizeof (buf));
pgm->type = htonl (type);
- pgm->hop_count = htonl (hop_count + 1);
- pgm->desired_replication_level = htonl (desired_replication_level);
- pgm->xquery_size = htonl (xquery_size);
- pgm->bf_mutator = bf_nonce;
+ pgm->options = htons (options);
+ pgm->hop_count = htons (hop_count + 1);
+ pgm->desired_replication_level = htons (desired_replication_level);
+ pgm->result_filter_size = htons ((uint16_t) result_filter_size);
GNUNET_break (GNUNET_YES ==
GNUNET_CONTAINER_bloomfilter_test (peer_bf,
&target->phash));
@@ -1465,142 +1636,247 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
pgm->bloomfilter,
DHT_BLOOM_SIZE));
pgm->key = *key;
- xq = (char *) &pgm[1];
- GNUNET_memcpy (xq,
+ rf = (char *) &pgm[1];
+ GNUNET_memcpy (rf,
+ result_filter,
+ result_filter_size);
+ GNUNET_memcpy (&rf[result_filter_size],
xquery,
xquery_size);
- GNUNET_memcpy (&xq[xquery_size],
- reply_bf,
- reply_bf_size);
- GNUNET_MQ_send (target->mq,
- env);
+ do_send (target,
+ &pgm->header);
}
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# GET messages queued for transmission",
+ target_count - skip_count,
+ GNUNET_NO);
GNUNET_free (targets);
- GNUNET_free (reply_bf);
+ GNUNET_free (result_filter);
return (skip_count < target_count) ? GNUNET_OK : GNUNET_NO;
}
-/**
- * Handle a reply (route to origin). Only forwards the reply back to
- * the given peer. Does not do local caching or forwarding to local
- * clients.
- *
- * @param target neighbour that should receive the block (if still connected)
- * @param type type of the block
- * @param expiration_time when does the content expire
- * @param key key for the content
- * @param put_path_length number of entries in @a put_path
- * @param put_path peers the original PUT traversed (if tracked)
- * @param get_path_length number of entries in @a get_path
- * @param get_path peers this reply has traversed so far (if tracked)
- * @param data payload of the reply
- * @param data_size number of bytes in @a data
- */
-void
-GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute expiration_time,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
+struct PeerInfo *
+GDS_NEIGHBOURS_lookup_peer (const struct GNUNET_PeerIdentity *target)
+{
+ return GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
+ target);
+}
+
+
+bool
+GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
+ const struct GNUNET_DATACACHE_Block *bd,
+ const struct GNUNET_HashCode *query_hash,
unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- const void *data,
- size_t data_size)
+ const struct GNUNET_DHT_PathElement *get_path)
{
- struct PeerInfo *pi;
- struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_DHT_PathElement *paths;
size_t msize;
- struct PeerResultMessage *prm;
- struct GNUNET_PeerIdentity *paths;
-
- msize = data_size + (get_path_length + put_path_length)
- * sizeof(struct GNUNET_PeerIdentity);
- if ((msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
- (get_path_length >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
- (put_path_length >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
- (data_size > GNUNET_MAX_MESSAGE_SIZE))
+ unsigned int ppl = bd->put_path_length;
+ const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
+ enum GNUNET_DHT_RouteOption ro = bd->ro;
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ const struct GNUNET_PeerIdentity *trunc_peer
+ = truncated
+ ? &bd->trunc_peer
+ : NULL;
+ bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
+#if SANITY_CHECKS > 1
+ unsigned int failure_offset;
+
+ failure_offset
+ = GNUNET_DHT_verify_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ trunc_peer,
+ put_path,
+ ppl,
+ get_path,
+ get_path_length,
+ &GDS_my_identity);
+ if (0 != failure_offset)
{
- GNUNET_break (0);
- return;
+ GNUNET_assert (failure_offset <= ppl + get_path_length);
+ GNUNET_break_op (0);
+ if (failure_offset < ppl)
+ {
+ trunc_peer = &put_path[failure_offset - 1].pred;
+ put_path += failure_offset;
+ ppl -= failure_offset;
+ truncated = true;
+ ro |= GNUNET_DHT_RO_TRUNCATED;
+ }
+ else
+ {
+ failure_offset -= ppl;
+ if (0 == failure_offset)
+ trunc_peer = &put_path[ppl - 1].pred;
+ else
+ trunc_peer = &get_path[failure_offset - 1].pred;
+ ppl = 0;
+ put_path = NULL;
+ truncated = true;
+ ro |= GNUNET_DHT_RO_TRUNCATED;
+ get_path += failure_offset;
+ get_path_length -= failure_offset;
+ }
}
- pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
- target);
- if (NULL == pi)
+#endif
+ msize = bd->data_size + sizeof (struct PeerResultMessage);
+ if (msize > GNUNET_MAX_MESSAGE_SIZE)
{
- /* peer disconnected in the meantime, drop reply */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No matching peer for reply for key %s\n",
- GNUNET_h2s (key));
- return;
+ GNUNET_break_op (0);
+ return false;
}
- if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
+ if (truncated)
+ msize += sizeof (struct GNUNET_PeerIdentity);
+ if (tracking)
+ msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
+ if (msize < bd->data_size)
{
- /* skip */
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# P2P messages dropped due to full queue"),
- 1,
- GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peer queue full, ignoring reply for key %s\n",
- GNUNET_h2s (key));
- return;
+ GNUNET_break_op (0);
+ return false;
}
-
+ if ( (GNUNET_MAX_MESSAGE_SIZE - msize)
+ / sizeof(struct GNUNET_DHT_PathElement)
+ < (get_path_length + ppl) )
+ {
+ get_path_length = 0;
+ ppl = 0;
+ }
+ if ( (get_path_length > UINT16_MAX) ||
+ (ppl > UINT16_MAX) )
+ {
+ GNUNET_break (0);
+ get_path_length = 0;
+ ppl = 0;
+ }
+ msize += (get_path_length + ppl)
+ * sizeof(struct GNUNET_DHT_PathElement);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Forwarding reply for key %s to peer %s\n",
- GNUNET_h2s (key),
- GNUNET_i2s (target));
+ GNUNET_h2s (query_hash),
+ GNUNET_i2s (&pi->id));
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop
- ("# RESULT messages queued for transmission"), 1,
+ "# RESULT messages queued for transmission",
+ 1,
GNUNET_NO);
- env = GNUNET_MQ_msg_extra (prm,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
- prm->type = htonl (type);
- prm->put_path_length = htonl (put_path_length);
- prm->get_path_length = htonl (get_path_length);
- prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
- prm->key = *key;
- paths = (struct GNUNET_PeerIdentity *) &prm[1];
- GNUNET_memcpy (paths,
- put_path,
- put_path_length * sizeof(struct GNUNET_PeerIdentity));
- GNUNET_memcpy (&paths[put_path_length],
- get_path,
- get_path_length * sizeof(struct GNUNET_PeerIdentity));
- GNUNET_memcpy (&paths[put_path_length + get_path_length],
- data,
- data_size);
- GNUNET_MQ_send (pi->mq,
- env);
-}
-
+ {
+ struct PeerResultMessage *prm;
+ char buf[msize] GNUNET_ALIGN;
+ void *data;
+
+ prm = (struct PeerResultMessage *) buf;
+ prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
+ prm->header.size = htons (sizeof (buf));
+ prm->type = htonl ((uint32_t) bd->type);
+ prm->options = htonl ((uint32_t) ro);
+ prm->put_path_length = htons ((uint16_t) ppl);
+ prm->get_path_length = htons ((uint16_t) get_path_length);
+ prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
+ prm->key = *query_hash;
+ if (truncated)
+ {
+ void *tgt = &prm[1];
-/**
- * To be called on core init/fail.
- *
- * @param cls service closure
- * @param identity the public identity of this peer
- */
-static void
-core_init (void *cls,
- const struct GNUNET_PeerIdentity *identity)
-{
- (void) cls;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "CORE called, I am %s\n",
- GNUNET_i2s (identity));
- my_identity = *identity;
- GNUNET_CRYPTO_hash (identity,
- sizeof(struct GNUNET_PeerIdentity),
- &my_identity_hash);
- GNUNET_SERVICE_resume (GDS_service);
+ GNUNET_memcpy (tgt,
+ trunc_peer,
+ sizeof (struct GNUNET_PeerIdentity));
+ paths = (struct GNUNET_DHT_PathElement *)
+ (tgt + sizeof (struct GNUNET_PeerIdentity));
+ }
+ else
+ {
+ paths = (struct GNUNET_DHT_PathElement *) &prm[1];
+ }
+ if (NULL != put_path)
+ {
+ GNUNET_memcpy (paths,
+ put_path,
+ ppl * sizeof(struct GNUNET_DHT_PathElement));
+ }
+ else
+ {
+ GNUNET_assert (0 == ppl);
+ }
+ if (NULL != get_path)
+ {
+ GNUNET_memcpy (&paths[ppl],
+ get_path,
+ get_path_length * sizeof(struct GNUNET_DHT_PathElement));
+ }
+ else
+ {
+ GNUNET_assert (0 == get_path_length);
+ }
+ if (tracking)
+ {
+ struct GNUNET_CRYPTO_EddsaSignature sig;
+ void *tgt = &paths[get_path_length + ppl];
+ const struct GNUNET_PeerIdentity *pred;
+
+ if (ppl + get_path_length > 0)
+ pred = &paths[ppl + get_path_length - 1].pred;
+ else if (truncated)
+ pred = trunc_peer;
+ else
+ pred = NULL; /* we are first! */
+ /* Note that the last signature in 'paths' was not initialized before,
+ so this is crucial to avoid sending garbage. */
+ sign_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ pred,
+ &pi->id,
+ &sig);
+ memcpy (tgt,
+ &sig,
+ sizeof (sig));
+ data = tgt + sizeof (sig);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Signing GET PATH %u/%u of %s => %s\n",
+ ppl,
+ get_path_length,
+ GNUNET_h2s (query_hash),
+ GNUNET_B2S (&sig));
+#if SANITY_CHECKS > 1
+ {
+ struct GNUNET_DHT_PathElement xpaths[get_path_length + 1];
+
+ memcpy (xpaths,
+ &paths[ppl],
+ get_path_length * sizeof (struct GNUNET_DHT_PathElement));
+ xpaths[get_path_length].sig = sig;
+ xpaths[get_path_length].pred = GDS_my_identity;
+ if (0 !=
+ GNUNET_DHT_verify_path (bd->data,
+ bd->data_size,
+ bd->expiration_time,
+ trunc_peer,
+ paths,
+ ppl,
+ xpaths,
+ get_path_length + 1,
+ &pi->id))
+ {
+ GNUNET_break (0);
+ return false;
+ }
+ }
+#endif
+ }
+ else
+ {
+ data = &prm[1];
+ }
+ GNUNET_memcpy (data,
+ bd->data,
+ bd->data_size);
+ do_send (pi,
+ &prm->header);
+ }
+ return true;
}
@@ -1611,21 +1887,34 @@ core_init (void *cls,
* @param message message
* @return #GNUNET_OK if the message is valid
*/
-static int
+static enum GNUNET_GenericReturnValue
check_dht_p2p_put (void *cls,
const struct PeerPutMessage *put)
{
- uint32_t putlen;
- uint16_t msize;
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
+ uint16_t msize = ntohs (put->header.size);
+ uint16_t putlen = ntohs (put->put_path_length);
+ size_t xsize = (has_path
+ ? sizeof (struct GNUNET_CRYPTO_EddsaSignature)
+ : 0)
+ + (truncated
+ ? sizeof (struct GNUNET_PeerIdentity)
+ : 0);
+ size_t var_meta_size
+ = putlen * sizeof(struct GNUNET_DHT_PathElement)
+ + xsize;
(void) cls;
- msize = ntohs (put->header.size);
- putlen = ntohl (put->put_path_length);
- if ((msize <
- sizeof(struct PeerPutMessage)
- + putlen * sizeof(struct GNUNET_PeerIdentity)) ||
- (putlen >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
+ if ( (msize <
+ sizeof (struct PeerPutMessage) + var_meta_size) ||
+ (putlen >
+ (GNUNET_MAX_MESSAGE_SIZE
+ - sizeof (struct PeerPutMessage)
+ - xsize)
+ / sizeof(struct GNUNET_DHT_PathElement)) )
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@@ -1637,407 +1926,353 @@ check_dht_p2p_put (void *cls,
/**
* Core handler for p2p put requests.
*
- * @param cls closure with the `struct PeerInfo` of the sender
+ * @param cls closure with the `struct Target` of the sender
* @param message message
*/
static void
handle_dht_p2p_put (void *cls,
const struct PeerPutMessage *put)
{
- struct PeerInfo *peer = cls;
- const struct GNUNET_PeerIdentity *put_path;
- const void *payload;
- uint32_t putlen;
- uint16_t msize;
- size_t payload_size;
- enum GNUNET_DHT_RouteOption options;
- struct GNUNET_CONTAINER_BloomFilter *bf;
- struct GNUNET_HashCode test_key;
- int forwarded;
- struct GNUNET_TIME_Absolute exp_time;
-
- exp_time = GNUNET_TIME_absolute_ntoh (put->expiration_time);
- if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
+ struct Target *t = cls;
+ struct PeerInfo *peer = t->pi;
+ enum GNUNET_DHT_RouteOption ro
+ = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
+ bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
+ bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
+ uint16_t msize = ntohs (put->header.size);
+ uint16_t putlen = ntohs (put->put_path_length);
+ const struct GNUNET_PeerIdentity *trunc_peer
+ = truncated
+ ? (const struct GNUNET_PeerIdentity *) &put[1]
+ : NULL;
+ const struct GNUNET_DHT_PathElement *put_path
+ = truncated
+ ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
+ : (const struct GNUNET_DHT_PathElement *) &put[1];
+ const struct GNUNET_CRYPTO_EddsaSignature *last_sig
+ = has_path
+ ? (const struct GNUNET_CRYPTO_EddsaSignature *) &put_path[putlen]
+ : NULL;
+ const char *data
+ = has_path
+ ? (const char *) &last_sig[1]
+ : (const char *) &put_path[putlen];
+ size_t var_meta_size
+ = putlen * sizeof(struct GNUNET_DHT_PathElement)
+ + has_path ? sizeof (*last_sig) : 0
+ + truncated ? sizeof (*trunc_peer) : 0;
+ struct GNUNET_DATACACHE_Block bd = {
+ .key = put->key,
+ .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
+ .type = ntohl (put->type),
+ .ro = ro,
+ .data_size = msize - sizeof(*put) - var_meta_size,
+ .data = data
+ };
+
+ if (NULL != trunc_peer)
+ bd.trunc_peer = *trunc_peer;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "PUT for `%s' from %s with RO (%s/%s)\n",
+ GNUNET_h2s (&put->key),
+ GNUNET_i2s (&peer->id),
+ (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
+ has_path ? "R" : "-");
+ if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
{
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# Expired PUTs discarded"),
+ "# Expired PUTs discarded",
1,
GNUNET_NO);
return;
}
- msize = ntohs (put->header.size);
- putlen = ntohl (put->put_path_length);
+ if (GNUNET_NO ==
+ GNUNET_BLOCK_check_block (GDS_block_context,
+ bd.type,
+ bd.data,
+ bd.data_size))
+ {
+ GNUNET_break_op (0);
+ return;
+ }
+ if (! has_path)
+ putlen = 0;
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# P2P PUT requests received"),
+ "# P2P PUT requests received",
1,
GNUNET_NO);
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# P2P PUT bytes received"),
+ "# P2P PUT bytes received",
msize,
GNUNET_NO);
- put_path = (const struct GNUNET_PeerIdentity *) &put[1];
- payload = &put_path[putlen];
- options = ntohl (put->options);
- payload_size = msize - (sizeof(struct PeerPutMessage)
- + putlen * sizeof(struct GNUNET_PeerIdentity));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "PUT for `%s' from %s\n",
- GNUNET_h2s (&put->key),
- GNUNET_i2s (peer->id));
- if (GNUNET_YES == log_route_details_stderr)
- {
- char *tmp;
- char *pp;
-
- pp = GNUNET_STRINGS_pp2s (put_path,
- putlen);
- tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
- LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
- "R5N PUT %s: %s->%s (%u, %u=>%u, PP: %s)\n",
- GNUNET_h2s (&put->key),
- GNUNET_i2s (peer->id),
- tmp,
- ntohl (put->hop_count),
- GNUNET_CRYPTO_hash_matching_bits (&peer->phash,
- &put->key),
- GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
- &put->key),
- pp);
- GNUNET_free (pp);
- GNUNET_free (tmp);
- }
- switch (GNUNET_BLOCK_get_key
- (GDS_block_context,
- ntohl (put->type),
- payload,
- payload_size,
- &test_key))
- {
- case GNUNET_YES:
- if (0 != memcmp (&test_key,
- &put->key,
- sizeof(struct GNUNET_HashCode)))
- {
- char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
-
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "PUT with key `%s' for block with key %s\n",
- put_s,
- GNUNET_h2s_full (&test_key));
- GNUNET_free (put_s);
- return;
- }
- break;
-
- case GNUNET_NO:
- GNUNET_break_op (0);
- return;
-
- case GNUNET_SYSERR:
- /* cannot verify, good luck */
- break;
- }
- if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
- {
- switch (GNUNET_BLOCK_evaluate (GDS_block_context,
- ntohl (put->type),
- NULL, /* query group */
- GNUNET_BLOCK_EO_NONE,
- NULL, /* query */
- NULL, 0, /* xquery */
- payload,
- payload_size))
+ {
+ struct GNUNET_HashCode test_key;
+ enum GNUNET_GenericReturnValue ret;
+
+ ret = GNUNET_BLOCK_get_key (GDS_block_context,
+ bd.type,
+ bd.data,
+ bd.data_size,
+ &test_key);
+ switch (ret)
{
- case GNUNET_BLOCK_EVALUATION_OK_MORE:
- case GNUNET_BLOCK_EVALUATION_OK_LAST:
+ case GNUNET_YES:
+ if (0 != GNUNET_memcmp (&test_key,
+ &bd.key))
+ {
+ GNUNET_break_op (0);
+ return;
+ }
+ break;
+ case GNUNET_NO:
+ /* cannot verify, good luck */
+ break;
+ case GNUNET_SYSERR:
+ /* block type not supported, good luck */
break;
-
- case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
- case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
- case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
- case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
- case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
- case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
- default:
- GNUNET_break_op (0);
- return;
}
}
- bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
- DHT_BLOOM_SIZE,
- GNUNET_CONSTANTS_BLOOMFILTER_K);
- GNUNET_break_op (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bf,
- &peer->phash));
{
- struct GNUNET_PeerIdentity pp[putlen + 1];
-
+ struct GNUNET_CONTAINER_BloomFilter *bf;
+ struct GNUNET_DHT_PathElement pp[putlen + 1];
+
+ bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
+ DHT_BLOOM_SIZE,
+ GNUNET_CONSTANTS_BLOOMFILTER_K);
+ GNUNET_break_op (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bf,
+ &peer->phash));
/* extend 'put path' by sender */
- if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
+ bd.put_path = (const struct GNUNET_DHT_PathElement *) pp;
+ bd.put_path_length = putlen + 1;
+ if (has_path)
{
+ unsigned int failure_offset;
+
+ GNUNET_memcpy (pp,
+ put_path,
+ putlen * sizeof(struct GNUNET_DHT_PathElement));
+ pp[putlen].pred = peer->id;
+ pp[putlen].sig = *last_sig;
#if SANITY_CHECKS
- for (unsigned int i = 0; i <= putlen; i++)
+ /* TODO: might want to eventually implement probabilistic
+ load-based path verification, but for now it is all or nothing */
+ failure_offset
+ = GNUNET_DHT_verify_path (bd.data,
+ bd.data_size,
+ bd.expiration_time,
+ trunc_peer,
+ pp,
+ putlen + 1,
+ NULL, 0, /* get_path */
+ &GDS_my_identity);
+#else
+ failure_offset = 0;
+#endif
+ if (0 != failure_offset)
{
- for (unsigned int j = 0; j < i; j++)
- {
- GNUNET_break (0 != memcmp (&pp[i],
- &pp[j],
- sizeof(struct GNUNET_PeerIdentity)));
- }
- GNUNET_break (0 != memcmp (&pp[i],
- peer->id,
- sizeof(struct GNUNET_PeerIdentity)));
+ GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Recorded put path invalid at offset %u, truncating\n",
+ failure_offset);
+ GNUNET_assert (failure_offset <= putlen + 1);
+ bd.put_path = &pp[failure_offset];
+ bd.put_path_length = putlen - failure_offset;
+ bd.ro |= GNUNET_DHT_RO_TRUNCATED;
+ bd.trunc_peer = pp[failure_offset - 1].pred;
}
-#endif
- GNUNET_memcpy (pp,
- put_path,
- putlen * sizeof(struct GNUNET_PeerIdentity));
- pp[putlen] = *peer->id;
- putlen++;
}
else
- putlen = 0;
+ {
+ bd.put_path_length = 0;
+ }
/* give to local clients */
- GDS_CLIENTS_handle_reply (exp_time,
- &put->key,
- 0,
- NULL,
- putlen,
- pp,
- ntohl (put->type),
- payload_size,
- payload);
+ GNUNET_break (GDS_CLIENTS_handle_reply (&bd,
+ &bd.key,
+ 0, NULL /* get path */));
+
/* store locally */
- if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
- (GDS_am_closest_peer (&put->key, bf)))
- GDS_DATACACHE_handle_put (exp_time,
- &put->key,
- putlen,
- pp,
- ntohl (put->type),
- payload_size,
- payload);
- /* route to other peers */
- forwarded = GDS_NEIGHBOURS_handle_put (ntohl (put->type),
- options,
- ntohl (
- put->desired_replication_level),
- exp_time,
- ntohl (put->hop_count),
- bf,
- &put->key,
- putlen,
- pp,
- payload,
- payload_size);
- /* notify monitoring clients */
- GDS_CLIENTS_process_put (options
- | ((GNUNET_OK == forwarded)
- ? GNUNET_DHT_RO_LAST_HOP
- : 0),
- ntohl (put->type),
- ntohl (put->hop_count),
- ntohl (put->desired_replication_level),
- putlen, pp,
- exp_time,
- &put->key,
- payload,
- payload_size);
+ if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+ (GDS_am_closest_peer (&put->key,
+ bf)) )
+ GDS_DATACACHE_handle_put (&bd);
+ {
+ enum GNUNET_GenericReturnValue forwarded;
+
+ /* route to other peers */
+ forwarded
+ = GDS_NEIGHBOURS_handle_put (&bd,
+ ntohs (put->desired_replication_level),
+ ntohs (put->hop_count),
+ bf);
+ /* notify monitoring clients */
+ bd.ro |= ((GNUNET_OK == forwarded)
+ ? GNUNET_DHT_RO_LAST_HOP
+ : 0);
+ GDS_CLIENTS_process_put (&bd,
+ ntohs (put->hop_count),
+ ntohs (put->desired_replication_level));
+ }
+ GNUNET_CONTAINER_bloomfilter_free (bf);
}
- GNUNET_CONTAINER_bloomfilter_free (bf);
}
/**
- * We have received a FIND PEER request. Send matching
- * HELLOs back.
+ * We have received a request for a HELLO. Sends our
+ * HELLO back.
*
- * @param sender sender of the FIND PEER request
+ * @param pi sender of the request
* @param key peers close to this key are desired
* @param bg group for filtering peers
*/
static void
-handle_find_peer (const struct GNUNET_PeerIdentity *sender,
- const struct GNUNET_HashCode *key,
- struct GNUNET_BLOCK_Group *bg)
+handle_find_my_hello (struct PeerInfo *pi,
+ const struct GNUNET_HashCode *query_hash,
+ struct GNUNET_BLOCK_Group *bg)
{
- int bucket_idx;
- struct PeerBucket *bucket;
- struct PeerInfo *peer;
- unsigned int choice;
- const struct GNUNET_HELLO_Message *hello;
- size_t hello_size;
+ size_t block_size = 0;
+
+ /* TODO: consider caching our HELLO block for a bit, to
+ avoid signing too often here... */
+ GNUNET_break (GNUNET_NO ==
+ GNUNET_HELLO_builder_to_block (GDS_my_hello,
+ &GDS_my_private_key,
+ NULL,
+ &block_size));
+ {
+ char block[block_size];
- /* first, check about our own HELLO */
- if (NULL != GDS_my_hello)
- {
- hello_size = GNUNET_HELLO_size ((const struct
- GNUNET_HELLO_Message *) GDS_my_hello);
- GNUNET_break (hello_size >= sizeof(struct GNUNET_MessageHeader));
- if (GNUNET_BLOCK_EVALUATION_OK_MORE ==
- GNUNET_BLOCK_evaluate (GDS_block_context,
- GNUNET_BLOCK_TYPE_DHT_HELLO,
- bg,
- GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO,
- &my_identity_hash,
- NULL, 0,
- GDS_my_hello,
- hello_size))
+ if (GNUNET_OK !=
+ GNUNET_HELLO_builder_to_block (GDS_my_hello,
+ &GDS_my_private_key,
+ block,
+ &block_size))
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# FIND PEER requests ignored due to lack of HELLO",
+ 1,
+ GNUNET_NO);
+ }
+ else if (GNUNET_BLOCK_REPLY_OK_MORE ==
+ GNUNET_BLOCK_check_reply (GDS_block_context,
+ GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ bg,
+ &GDS_my_identity_hash,
+ NULL, 0,
+ block,
+ block_size))
{
- GDS_NEIGHBOURS_handle_reply (sender,
- GNUNET_BLOCK_TYPE_DHT_HELLO,
- GNUNET_TIME_relative_to_absolute (
- hello_expiration),
- key,
- 0,
- NULL,
- 0,
- NULL,
- GDS_my_hello,
- hello_size);
+ struct GNUNET_DATACACHE_Block bd = {
+ .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ .expiration_time
+ = GNUNET_TIME_relative_to_absolute (
+ GNUNET_HELLO_ADDRESS_EXPIRATION),
+ .key = GDS_my_identity_hash,
+ .data = block,
+ .data_size = block_size
+ };
+
+ GNUNET_break (GDS_NEIGHBOURS_handle_reply (pi,
+ &bd,
+ query_hash,
+ 0, NULL /* get path */));
}
else
{
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# FIND PEER requests ignored due to Bloomfilter"),
+ "# FIND PEER requests ignored due to Bloomfilter",
1,
GNUNET_NO);
}
}
- else
- {
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# FIND PEER requests ignored due to lack of HELLO"),
- 1,
- GNUNET_NO);
- }
+}
- /* then, also consider sending a random HELLO from the closest bucket */
- if (0 == memcmp (&my_identity_hash,
- key,
- sizeof(struct GNUNET_HashCode)))
- bucket_idx = closest_bucket;
- else
- bucket_idx = GNUNET_MIN ((int) closest_bucket,
- find_bucket (key));
- if (bucket_idx < 0)
- return;
- bucket = &k_buckets[bucket_idx];
- if (bucket->peers_size == 0)
- return;
- choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- bucket->peers_size);
- peer = bucket->head;
- while (choice > 0)
- {
- GNUNET_assert (NULL != peer);
- peer = peer->next;
- choice--;
- }
- choice = bucket->peers_size;
- do
- {
- peer = peer->next;
- if (0 == choice--)
- return; /* no non-masked peer available */
- if (NULL == peer)
- peer = bucket->head;
- hello = GDS_HELLO_get (peer->id);
+
+/**
+ * We have received a request for nearby HELLOs. Sends matching
+ * HELLOs back.
+ *
+ * @param pi sender of the request
+ * @param key peers close to this key are desired
+ * @param bg group for filtering peers
+ */
+static void
+handle_find_local_hello (struct PeerInfo *pi,
+ const struct GNUNET_HashCode *query_hash,
+ struct GNUNET_BLOCK_Group *bg)
+{
+ /* Force non-random selection by hop count */
+ struct PeerInfo *peer;
+
+ peer = select_peer (query_hash,
+ NULL,
+ GDS_NSE_get () + 1);
+ if ( (NULL != peer->hello) &&
+ (! GNUNET_TIME_absolute_is_past (peer->hello_expiration)) &&
+ (GNUNET_BLOCK_REPLY_OK_MORE ==
+ GNUNET_BLOCK_check_reply (
+ GDS_block_context,
+ GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ bg,
+ &peer->phash,
+ NULL, 0, /* xquery */
+ peer->hello,
+ peer->hello_size)) )
+ {
+ struct GNUNET_DATACACHE_Block bd = {
+ .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ .expiration_time = peer->hello_expiration,
+ .key = peer->phash,
+ .data = peer->hello,
+ .data_size = peer->hello_size
+ };
+
+ GNUNET_break (GDS_NEIGHBOURS_handle_reply (pi,
+ &bd,
+ query_hash,
+ 0, NULL /* get path */));
}
- while ((NULL == hello) ||
- (GNUNET_BLOCK_EVALUATION_OK_MORE !=
- GNUNET_BLOCK_evaluate (GDS_block_context,
- GNUNET_BLOCK_TYPE_DHT_HELLO,
- bg,
- GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO,
- &peer->phash,
- NULL, 0,
- hello,
- (hello_size = GNUNET_HELLO_size (hello)))));
- GDS_NEIGHBOURS_handle_reply (sender,
- GNUNET_BLOCK_TYPE_DHT_HELLO,
- GNUNET_TIME_relative_to_absolute
- (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION),
- key,
- 0,
- NULL,
- 0,
- NULL,
- hello,
- hello_size);
}
/**
- * Handle a result from local datacache for a GET operation.
+ * Handle an exact result from local datacache for a GET operation.
*
* @param cls the `struct PeerInfo` for which this is a reply
- * @param type type of the block
- * @param expiration_time when does the content expire
- * @param key key for the content
- * @param put_path_length number of entries in @a put_path
- * @param put_path peers the original PUT traversed (if tracked)
- * @param get_path_length number of entries in @a get_path
- * @param get_path peers this reply has traversed so far (if tracked)
- * @param data payload of the reply
- * @param data_size number of bytes in @a data
+ * @param bd details about the block we found locally
*/
static void
handle_local_result (void *cls,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute expiration_time,
- const struct GNUNET_HashCode *key,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- const void *data,
- size_t data_size)
+ const struct GNUNET_DATACACHE_Block *bd)
{
struct PeerInfo *peer = cls;
- char *pp;
- pp = GNUNET_STRINGS_pp2s (put_path,
- put_path_length);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Found local result for %s (PP: %s)\n",
- GNUNET_h2s (key),
- pp);
- GNUNET_free (pp);
- GDS_NEIGHBOURS_handle_reply (peer->id,
- type,
- expiration_time,
- key,
- put_path_length, put_path,
- get_path_length, get_path,
- data, data_size);
+ GNUNET_break (GDS_NEIGHBOURS_handle_reply (peer,
+ bd,
+ &bd->key,
+ 0, NULL /* get path */));
}
/**
* Check validity of p2p get request.
*
- * @param cls closure with the `struct PeerInfo` of the sender
+ * @param cls closure with the `struct Target` of the sender
* @param get the message
* @return #GNUNET_OK if the message is well-formed
*/
-static int
+static enum GNUNET_GenericReturnValue
check_dht_p2p_get (void *cls,
const struct PeerGetMessage *get)
{
- uint32_t xquery_size;
- uint16_t msize;
+ uint16_t msize = ntohs (get->header.size);
+ uint16_t result_filter_size = ntohs (get->result_filter_size);
(void) cls;
- msize = ntohs (get->header.size);
- xquery_size = ntohl (get->xquery_size);
- if (msize < sizeof(struct PeerGetMessage) + xquery_size)
+ if (msize < sizeof(*get) + result_filter_size)
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@@ -2049,163 +2284,211 @@ check_dht_p2p_get (void *cls,
/**
* Core handler for p2p get requests.
*
- * @param cls closure with the `struct PeerInfo` of the sender
+ * @param cls closure with the `struct Target` of the sender
* @param get the message
*/
static void
handle_dht_p2p_get (void *cls,
const struct PeerGetMessage *get)
{
- struct PeerInfo *peer = cls;
- uint32_t xquery_size;
- size_t reply_bf_size;
- uint16_t msize;
- enum GNUNET_BLOCK_Type type;
- enum GNUNET_DHT_RouteOption options;
- enum GNUNET_BLOCK_EvaluationResult eval;
- struct GNUNET_BLOCK_Group *bg;
- struct GNUNET_CONTAINER_BloomFilter *peer_bf;
- const char *xquery;
- int forwarded;
+ struct Target *t = cls;
+ struct PeerInfo *peer = t->pi;
+ uint16_t msize = ntohs (get->header.size);
+ uint16_t result_filter_size = ntohs (get->result_filter_size);
+ uint16_t hop_count = ntohs (get->hop_count);
+ enum GNUNET_BLOCK_Type type = (enum GNUNET_BLOCK_Type) ntohl (get->type);
+ enum GNUNET_DHT_RouteOption options = (enum GNUNET_DHT_RouteOption) ntohs (
+ get->options);
+ enum GNUNET_BLOCK_ReplyEvaluationResult eval = GNUNET_BLOCK_REPLY_OK_MORE;
+ const void *result_filter = (const void *) &get[1];
+ const void *xquery = result_filter + result_filter_size;
+ size_t xquery_size = msize - sizeof (*get) - result_filter_size;
/* parse and validate message */
- msize = ntohs (get->header.size);
- xquery_size = ntohl (get->xquery_size);
- reply_bf_size = msize - (sizeof(struct PeerGetMessage) + xquery_size);
- type = ntohl (get->type);
- options = ntohl (get->options);
- xquery = (const char *) &get[1];
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# P2P GET requests received"),
+ "# P2P GET requests received",
1,
GNUNET_NO);
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# P2P GET bytes received"),
+ "# P2P GET bytes received",
msize,
GNUNET_NO);
- if (GNUNET_YES == log_route_details_stderr)
- {
- char *tmp;
-
- tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
- LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
- "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
- GNUNET_h2s (&get->key),
- GNUNET_i2s (peer->id),
- tmp,
- ntohl (get->hop_count),
- GNUNET_CRYPTO_hash_matching_bits (&peer->phash,
- &get->key),
- GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
- &get->key),
- ntohl (get->xquery_size),
- xquery);
- GNUNET_free (tmp);
- }
- eval
- = GNUNET_BLOCK_evaluate (GDS_block_context,
- type,
- NULL,
- GNUNET_BLOCK_EO_NONE,
- &get->key,
- xquery,
- xquery_size,
- NULL,
- 0);
- if (eval != GNUNET_BLOCK_EVALUATION_REQUEST_VALID)
- {
- /* request invalid or block type not supported */
- GNUNET_break_op (eval == GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED);
+ if (GNUNET_NO ==
+ GNUNET_BLOCK_check_query (GDS_block_context,
+ type,
+ &get->key,
+ xquery,
+ xquery_size))
+ {
+ /* request invalid */
+ GNUNET_break_op (0);
return;
}
- peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
- DHT_BLOOM_SIZE,
- GNUNET_CONSTANTS_BLOOMFILTER_K);
- GNUNET_break_op (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (peer_bf,
- &peer->phash));
- bg = GNUNET_BLOCK_group_create (GDS_block_context,
- type,
- get->bf_mutator,
- &xquery[xquery_size],
- reply_bf_size,
- "filter-size",
- reply_bf_size,
- NULL);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GET for %s at %s after %u hops\n",
- GNUNET_h2s (&get->key),
- GNUNET_i2s (&my_identity),
- (unsigned int) ntohl (get->hop_count));
- /* local lookup (this may update the reply_bf) */
- if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
- (GDS_am_closest_peer (&get->key,
- peer_bf)))
- {
- if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
+
+ {
+ struct GNUNET_BLOCK_Group *bg;
+ struct GNUNET_CONTAINER_BloomFilter *peer_bf;
+
+ peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
+ DHT_BLOOM_SIZE,
+ GNUNET_CONSTANTS_BLOOMFILTER_K);
+ GNUNET_break_op (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (peer_bf,
+ &peer->phash));
+ bg = GNUNET_BLOCK_group_create (GDS_block_context,
+ type,
+ result_filter,
+ result_filter_size,
+ "filter-size",
+ result_filter_size,
+ NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GET for %s at %s after %u hops\n",
+ GNUNET_h2s (&get->key),
+ GNUNET_i2s (&GDS_my_identity),
+ (unsigned int) hop_count);
+ /* local lookup (this may update the bg) */
+ if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+ (GDS_am_closest_peer (&get->key,
+ peer_bf)) )
+ {
+ if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == type)
+ {
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# P2P HELLO lookup requests processed",
+ 1,
+ GNUNET_NO);
+ handle_find_my_hello (peer,
+ &get->key,
+ bg);
+ if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
+ handle_find_local_hello (peer,
+ &get->key,
+ bg);
+ }
+ else
+ {
+ if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
+ eval = GDS_DATACACHE_get_closest (&get->key,
+ type,
+ xquery,
+ xquery_size,
+ bg,
+ &handle_local_result,
+ peer);
+ else
+ eval = GDS_DATACACHE_handle_get (&get->key,
+ type,
+ xquery,
+ xquery_size,
+ bg,
+ &handle_local_result,
+ peer);
+ }
+ }
+ else
{
GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop (
- "# P2P FIND PEER requests processed"),
+ "# P2P GET requests ONLY routed",
1,
GNUNET_NO);
- handle_find_peer (peer->id,
- &get->key,
- bg);
}
- else
+
+ /* remember request for routing replies
+ TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
+ */
+ GDS_ROUTING_add (&peer->id,
+ type,
+ bg, /* bg now owned by routing, but valid at least until end of this function! */
+ options,
+ &get->key,
+ xquery,
+ xquery_size);
+
+ /* P2P forwarding */
{
- eval = GDS_DATACACHE_handle_get (&get->key,
- type,
- xquery,
- xquery_size,
- bg,
- &handle_local_result,
- peer);
+ bool forwarded = false;
+ uint16_t desired_replication_level = ntohs (
+ get->desired_replication_level);
+
+ if (eval != GNUNET_BLOCK_REPLY_OK_LAST)
+ forwarded = (GNUNET_OK ==
+ GDS_NEIGHBOURS_handle_get (type,
+ options,
+ desired_replication_level,
+ hop_count,
+ &get->key,
+ xquery,
+ xquery_size,
+ bg,
+ peer_bf));
+ GDS_CLIENTS_process_get (
+ options
+ | (forwarded
+ ? 0
+ : GNUNET_DHT_RO_LAST_HOP),
+ type,
+ hop_count,
+ desired_replication_level,
+ &get->key);
}
+ /* clean up; note that 'bg' is owned by routing now! */
+ GNUNET_CONTAINER_bloomfilter_free (peer_bf);
}
- else
+}
+
+
+/**
+ * Process a reply, after the @a get_path has been updated.
+ *
+ * @param bd block details
+ * @param query_hash hash of the original query, might not match key in @a bd
+ * @param get_path_length number of entries in @a get_path
+ * @param get_path path the reply has taken
+ * @return true on success
+ */
+static bool
+process_reply_with_path (const struct GNUNET_DATACACHE_Block *bd,
+ const struct GNUNET_HashCode *query_hash,
+ unsigned int get_path_length,
+ const struct GNUNET_DHT_PathElement *get_path)
+{
+ /* forward to local clients */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Forwarding reply to local clients\n");
+ if (! GDS_CLIENTS_handle_reply (bd,
+ query_hash,
+ get_path_length,
+ get_path))
{
- GNUNET_STATISTICS_update (GDS_stats,
- gettext_noop ("# P2P GET requests ONLY routed"),
- 1,
- GNUNET_NO);
+ GNUNET_break (0);
+ return false;
}
+ GDS_CLIENTS_process_get_resp (bd,
+ get_path,
+ get_path_length);
+ if (GNUNET_YES == cache_results)
+ {
+ struct GNUNET_DHT_PathElement xput_path[GNUNET_NZL (get_path_length
+ + bd->put_path_length)];
+ struct GNUNET_DATACACHE_Block bdx = *bd;
- /* remember request for routing replies */
- GDS_ROUTING_add (peer->id,
- type,
- bg, /* bg now owned by routing, but valid at least until end of this function! */
- options,
- &get->key,
- xquery,
- xquery_size);
-
- /* P2P forwarding */
- forwarded = GNUNET_NO;
- if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST)
- forwarded = GDS_NEIGHBOURS_handle_get (type,
- options,
- ntohl (
- get->desired_replication_level),
- ntohl (get->hop_count),
- &get->key,
- xquery,
- xquery_size,
- bg,
- peer_bf);
- GDS_CLIENTS_process_get (options
- | ((GNUNET_OK == forwarded)
- ? GNUNET_DHT_RO_LAST_HOP : 0),
- type,
- ntohl (get->hop_count),
- ntohl (get->desired_replication_level),
- 0,
- NULL,
- &get->key);
-
- /* clean up; note that 'bg' is owned by routing now! */
- GNUNET_CONTAINER_bloomfilter_free (peer_bf);
+ GNUNET_memcpy (xput_path,
+ bd->put_path,
+ bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
+ GNUNET_memcpy (&xput_path[bd->put_path_length],
+ get_path,
+ get_path_length * sizeof(struct GNUNET_DHT_PathElement));
+ bdx.put_path = xput_path;
+ bdx.put_path_length += get_path_length;
+ GDS_DATACACHE_handle_put (&bdx);
+ }
+ /* forward to other peers */
+ GDS_ROUTING_process (bd,
+ query_hash,
+ get_path_length,
+ get_path);
+ return true;
}
@@ -2216,26 +2499,23 @@ handle_dht_p2p_get (void *cls,
* @param message message
* @return #GNUNET_YES if the message is well-formed
*/
-static int
+static enum GNUNET_GenericReturnValue
check_dht_p2p_result (void *cls,
const struct PeerResultMessage *prm)
{
- uint32_t get_path_length;
- uint32_t put_path_length;
- uint16_t msize;
+ uint16_t get_path_length = ntohs (prm->get_path_length);
+ uint16_t put_path_length = ntohs (prm->put_path_length);
+ uint16_t msize = ntohs (prm->header.size);
(void) cls;
- msize = ntohs (prm->header.size);
- put_path_length = ntohl (prm->put_path_length);
- get_path_length = ntohl (prm->get_path_length);
- if ((msize <
- sizeof(struct PeerResultMessage) + (get_path_length
- + put_path_length)
- * sizeof(struct GNUNET_PeerIdentity)) ||
- (get_path_length >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
- (put_path_length >
- GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
+ if ( (msize <
+ sizeof(struct PeerResultMessage)
+ + (get_path_length + put_path_length)
+ * sizeof(struct GNUNET_DHT_PathElement)) ||
+ (get_path_length >
+ GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ||
+ (put_path_length >
+ GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) )
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@@ -2245,81 +2525,6 @@ check_dht_p2p_result (void *cls,
/**
- * Process a reply, after the @a get_path has been updated.
- *
- * @param expiration_time when does the reply expire
- * @param key key matching the query
- * @param get_path_length number of entries in @a get_path
- * @param get_path path the reply has taken
- * @param put_path_length number of entries in @a put_path
- * @param put_path path the PUT has taken
- * @param type type of the block
- * @param data_size number of bytes in @a data
- * @param data payload of the reply
- */
-static void
-process_reply_with_path (struct GNUNET_TIME_Absolute expiration_time,
- const struct GNUNET_HashCode *key,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int put_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- enum GNUNET_BLOCK_Type type,
- size_t data_size,
- const void *data)
-{
- /* forward to local clients */
- GDS_CLIENTS_handle_reply (expiration_time,
- key,
- get_path_length,
- get_path,
- put_path_length,
- put_path,
- type,
- data_size,
- data);
- GDS_CLIENTS_process_get_resp (type,
- get_path,
- get_path_length,
- put_path,
- put_path_length,
- expiration_time,
- key,
- data,
- data_size