diff options
author | Nils Gillmann <ng0@n0.is> | 2018-11-13 11:42:15 +0000 |
---|---|---|
committer | Nils Gillmann <ng0@n0.is> | 2018-11-13 11:42:15 +0000 |
commit | 9d1e77b9331acb9bd8b6c99aa942f62b9759e650 (patch) | |
tree | 85475b117fff75b563a6f9512d3ead476a830f7d | |
parent | e8a1a082555f98af40f98fd3a20ccd803ad478f8 (diff) | |
parent | 98288a7b26344294a3668101b9c2b502dfc19e12 (diff) |
Merge branch 'master' of gnunet.org:gnunet
26 files changed, 2679 insertions, 312 deletions
diff --git a/configure.ac b/configure.ac index e37df28dd..3310168e0 100644 --- a/configure.ac +++ b/configure.ac @@ -681,7 +681,7 @@ AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false]) if test x$nss = xfalse then AM_CONDITIONAL(HAVE_GLIBCNSS, false) - AC_MSG_WARN([ERROR: No GNU libc nss header, will not build NSS plugin]) + AC_MSG_WARN([No GNU libc nss header, will not build NSS plugin]) else AM_CONDITIONAL(HAVE_GLIBCNSS, true) fi diff --git a/po/POTFILES.in b/po/POTFILES.in index caf7353be..5f4c5ee7f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,13 +4,21 @@ src/arm/arm_monitor_api.c src/arm/gnunet-arm.c src/arm/gnunet-service-arm.c src/arm/mockup-service.c +src/ats-tests/ats-testing-experiment.c +src/ats-tests/ats-testing-log.c +src/ats-tests/ats-testing-preferences.c +src/ats-tests/ats-testing-traffic.c +src/ats-tests/ats-testing.c +src/ats-tests/gnunet-ats-sim.c +src/ats-tests/gnunet-solver-eval.c +src/ats-tool/gnunet-ats.c src/ats/ats_api_connectivity.c src/ats/ats_api_performance.c src/ats/ats_api_scanner.c src/ats/ats_api_scheduling.c src/ats/gnunet-ats-solver-eval.c -src/ats/gnunet-service-ats_addresses.c src/ats/gnunet-service-ats.c +src/ats/gnunet-service-ats_addresses.c src/ats/gnunet-service-ats_connectivity.c src/ats/gnunet-service-ats_normalization.c src/ats/gnunet-service-ats_performance.c @@ -21,14 +29,6 @@ src/ats/gnunet-service-ats_scheduling.c src/ats/plugin_ats_mlp.c src/ats/plugin_ats_proportional.c src/ats/plugin_ats_ril.c -src/ats-tests/ats-testing.c -src/ats-tests/ats-testing-experiment.c -src/ats-tests/ats-testing-log.c -src/ats-tests/ats-testing-preferences.c -src/ats-tests/ats-testing-traffic.c -src/ats-tests/gnunet-ats-sim.c -src/ats-tests/gnunet-solver-eval.c -src/ats-tool/gnunet-ats.c src/auction/gnunet-auction-create.c src/auction/gnunet-auction-info.c src/auction/gnunet-auction-join.c @@ -40,8 +40,8 @@ src/block/plugin_block_test.c src/cadet/cadet_api.c src/cadet/cadet_test_lib.c src/cadet/desirability_table.c -src/cadet/gnunet-cadet.c src/cadet/gnunet-cadet-profiler.c +src/cadet/gnunet-cadet.c src/cadet/gnunet-service-cadet.c src/cadet/gnunet-service-cadet_channel.c src/cadet/gnunet-service-cadet_connection.c @@ -57,15 +57,15 @@ src/consensus/gnunet-service-consensus.c src/consensus/plugin_block_consensus.c src/conversation/conversation_api.c src/conversation/conversation_api_call.c -src/conversation/gnunet-conversation.c src/conversation/gnunet-conversation-test.c -src/conversation/gnunet_gst.c -src/conversation/gnunet_gst_test.c -src/conversation/gnunet-helper-audio-playback.c +src/conversation/gnunet-conversation.c src/conversation/gnunet-helper-audio-playback-gst.c -src/conversation/gnunet-helper-audio-record.c +src/conversation/gnunet-helper-audio-playback.c src/conversation/gnunet-helper-audio-record-gst.c +src/conversation/gnunet-helper-audio-record.c src/conversation/gnunet-service-conversation.c +src/conversation/gnunet_gst.c +src/conversation/gnunet_gst_test.c src/conversation/microphone.c src/conversation/plugin_gnsrecord_conversation.c src/conversation/speaker.c @@ -101,7 +101,6 @@ src/dht/dht_api.c src/dht/dht_test_lib.c src/dht/gnunet-dht-get.c src/dht/gnunet-dht-monitor.c -src/dht/gnunet_dht_profiler.c src/dht/gnunet-dht-put.c src/dht/gnunet-service-dht.c src/dht/gnunet-service-dht_clients.c @@ -110,6 +109,7 @@ src/dht/gnunet-service-dht_hello.c src/dht/gnunet-service-dht_neighbours.c src/dht/gnunet-service-dht_nse.c src/dht/gnunet-service-dht_routing.c +src/dht/gnunet_dht_profiler.c src/dht/plugin_block_dht.c src/dns/dns_api.c src/dns/gnunet-dns-monitor.c @@ -123,8 +123,8 @@ src/dv/gnunet-dv.c src/dv/gnunet-service-dv.c src/dv/plugin_transport_dv.c src/exit/gnunet-daemon-exit.c -src/exit/gnunet-helper-exit.c src/exit/gnunet-helper-exit-windows.c +src/exit/gnunet-helper-exit.c src/fragmentation/defragmentation.c src/fragmentation/fragmentation.c src/fs/fs_api.c @@ -149,8 +149,8 @@ src/fs/gnunet-auto-share.c src/fs/gnunet-daemon-fsprofiler.c src/fs/gnunet-directory.c src/fs/gnunet-download.c -src/fs/gnunet-fs.c src/fs/gnunet-fs-profiler.c +src/fs/gnunet-fs.c src/fs/gnunet-helper-fs-publish.c src/fs/gnunet-publish.c src/fs/gnunet-search.c @@ -170,10 +170,10 @@ src/gns/gns_tld_api.c src/gns/gnunet-bcd.c src/gns/gnunet-dns2gns.c src/gns/gnunet-gns-benchmark.c -src/gns/gnunet-gns.c src/gns/gnunet-gns-helper-service-w32.c src/gns/gnunet-gns-import.c src/gns/gnunet-gns-proxy.c +src/gns/gnunet-gns.c src/gns/gnunet-service-gns.c src/gns/gnunet-service-gns_interceptor.c src/gns/gnunet-service-gns_resolver.c @@ -181,15 +181,15 @@ src/gns/nss/nss_gns.c src/gns/nss/nss_gns_query.c src/gns/plugin_block_gns.c src/gns/plugin_gnsrecord_gns.c +src/gns/w32nsp-install.c +src/gns/w32nsp-resolve.c +src/gns/w32nsp-uninstall.c +src/gns/w32nsp.c src/gnsrecord/gnsrecord.c src/gnsrecord/gnsrecord_crypto.c src/gnsrecord/gnsrecord_misc.c src/gnsrecord/gnsrecord_serialization.c src/gnsrecord/plugin_gnsrecord_dns.c -src/gns/w32nsp.c -src/gns/w32nsp-install.c -src/gns/w32nsp-resolve.c -src/gns/w32nsp-uninstall.c src/hello/address.c src/hello/gnunet-hello.c src/hello/hello.c @@ -218,8 +218,8 @@ src/namecache/namecache_api.c src/namecache/plugin_namecache_flat.c src/namecache/plugin_namecache_postgres.c src/namecache/plugin_namecache_sqlite.c -src/namestore/gnunet-namestore.c src/namestore/gnunet-namestore-fcfsd.c +src/namestore/gnunet-namestore.c src/namestore/gnunet-service-namestore.c src/namestore/gnunet-zoneimport.c src/namestore/namestore_api.c @@ -234,10 +234,10 @@ src/nat-auto/gnunet-service-nat-auto.c src/nat-auto/gnunet-service-nat-auto_legacy.c src/nat-auto/nat_auto_api.c src/nat-auto/nat_auto_api_test.c -src/nat/gnunet-helper-nat-client.c src/nat/gnunet-helper-nat-client-windows.c -src/nat/gnunet-helper-nat-server.c +src/nat/gnunet-helper-nat-client.c src/nat/gnunet-helper-nat-server-windows.c +src/nat/gnunet-helper-nat-server.c src/nat/gnunet-nat.c src/nat/gnunet-service-nat.c src/nat/gnunet-service-nat_externalip.c @@ -246,15 +246,15 @@ src/nat/gnunet-service-nat_mini.c src/nat/gnunet-service-nat_stun.c src/nat/nat_api.c src/nat/nat_api_stun.c -src/nse/gnunet-nse.c src/nse/gnunet-nse-profiler.c +src/nse/gnunet-nse.c src/nse/gnunet-service-nse.c src/nse/nse_api.c +src/peerinfo-tool/gnunet-peerinfo.c +src/peerinfo-tool/gnunet-peerinfo_plugins.c src/peerinfo/gnunet-service-peerinfo.c src/peerinfo/peerinfo_api.c src/peerinfo/peerinfo_api_notify.c -src/peerinfo-tool/gnunet-peerinfo.c -src/peerinfo-tool/gnunet-peerinfo_plugins.c src/peerstore/gnunet-peerstore.c src/peerstore/gnunet-service-peerstore.c src/peerstore/peerstore_api.c @@ -301,7 +301,6 @@ src/regex/regex_internal_dht.c src/regex/regex_test_graph.c src/regex/regex_test_lib.c src/regex/regex_test_random.c -src/rest/gnunet-rest-server.c src/rest-plugins/json_reclaim.c src/rest-plugins/oidc_helper.c src/rest-plugins/plugin_rest_copying.c @@ -312,27 +311,28 @@ src/rest-plugins/plugin_rest_namestore.c src/rest-plugins/plugin_rest_openid_connect.c src/rest-plugins/plugin_rest_peerinfo.c src/rest-plugins/plugin_rest_reclaim.c +src/rest/gnunet-rest-server.c src/rest/rest.c src/revocation/gnunet-revocation.c src/revocation/gnunet-service-revocation.c src/revocation/plugin_block_revocation.c src/revocation/revocation_api.c -src/rps/gnunet-rps.c src/rps/gnunet-rps-profiler.c +src/rps/gnunet-rps.c src/rps/gnunet-service-rps.c src/rps/gnunet-service-rps_custommap.c src/rps/gnunet-service-rps_sampler.c src/rps/gnunet-service-rps_sampler_elem.c src/rps/gnunet-service-rps_view.c -src/rps/rps_api.c src/rps/rps-sampler_client.c src/rps/rps-sampler_common.c src/rps/rps-test_util.c +src/rps/rps_api.c src/scalarproduct/gnunet-scalarproduct.c -src/scalarproduct/gnunet-service-scalarproduct_alice.c -src/scalarproduct/gnunet-service-scalarproduct_bob.c src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c +src/scalarproduct/gnunet-service-scalarproduct_alice.c +src/scalarproduct/gnunet-service-scalarproduct_bob.c src/scalarproduct/scalarproduct_api.c src/secretsharing/gnunet-secretsharing-profiler.c src/secretsharing/gnunet-service-secretsharing.c @@ -361,15 +361,16 @@ src/statistics/gnunet-statistics.c src/statistics/statistics_api.c src/template/gnunet-service-template.c src/template/gnunet-template.c +src/testbed-logger/gnunet-service-testbed-logger.c +src/testbed-logger/testbed_logger_api.c src/testbed/generate-underlay-topology.c src/testbed/gnunet-daemon-latency-logger.c src/testbed/gnunet-daemon-testbed-blacklist.c src/testbed/gnunet-daemon-testbed-underlay.c src/testbed/gnunet-helper-testbed.c -src/testbed/gnunet_mpi_test.c src/testbed/gnunet-service-test-barriers.c -src/testbed/gnunet-service-testbed_barriers.c src/testbed/gnunet-service-testbed.c +src/testbed/gnunet-service-testbed_barriers.c src/testbed/gnunet-service-testbed_cache.c src/testbed/gnunet-service-testbed_connectionpool.c src/testbed/gnunet-service-testbed_cpustatus.c @@ -377,20 +378,19 @@ src/testbed/gnunet-service-testbed_links.c src/testbed/gnunet-service-testbed_meminfo.c src/testbed/gnunet-service-testbed_oc.c src/testbed/gnunet-service-testbed_peers.c -src/testbed/gnunet_testbed_mpi_spawn.c src/testbed/gnunet-testbed-profiler.c -src/testbed-logger/gnunet-service-testbed-logger.c -src/testbed-logger/testbed_logger_api.c -src/testbed/testbed_api_barriers.c +src/testbed/gnunet_mpi_test.c +src/testbed/gnunet_testbed_mpi_spawn.c src/testbed/testbed_api.c +src/testbed/testbed_api_barriers.c src/testbed/testbed_api_hosts.c src/testbed/testbed_api_operations.c src/testbed/testbed_api_peers.c src/testbed/testbed_api_sd.c src/testbed/testbed_api_services.c src/testbed/testbed_api_statistics.c -src/testbed/testbed_api_testbed.c src/testbed/testbed_api_test.c +src/testbed/testbed_api_testbed.c src/testbed/testbed_api_topology.c src/testbed/testbed_api_underlay.c src/testing/gnunet-testing.c @@ -398,29 +398,31 @@ src/testing/list-keys.c src/testing/testing.c src/topology/friends.c src/topology/gnunet-daemon-topology.c +src/transport/gnunet-communicator-unix.c src/transport/gnunet-helper-transport-bluetooth.c -src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-helper-transport-wlan-dummy.c -src/transport/gnunet-service-transport_ats.c +src/transport/gnunet-helper-transport-wlan.c +src/transport/gnunet-service-tng.c src/transport/gnunet-service-transport.c +src/transport/gnunet-service-transport_ats.c src/transport/gnunet-service-transport_hello.c src/transport/gnunet-service-transport_manipulation.c src/transport/gnunet-service-transport_neighbours.c src/transport/gnunet-service-transport_plugins.c src/transport/gnunet-service-transport_validation.c -src/transport/gnunet-transport.c src/transport/gnunet-transport-certificate-creation.c src/transport/gnunet-transport-profiler.c src/transport/gnunet-transport-wlan-receiver.c src/transport/gnunet-transport-wlan-sender.c +src/transport/gnunet-transport.c src/transport/plugin_transport_http_client.c src/transport/plugin_transport_http_common.c src/transport/plugin_transport_http_server.c src/transport/plugin_transport_smtp.c src/transport/plugin_transport_tcp.c src/transport/plugin_transport_template.c -src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_udp.c +src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_unix.c src/transport/plugin_transport_wlan.c src/transport/plugin_transport_xt.c @@ -429,6 +431,11 @@ src/transport/tcp_connection_legacy.c src/transport/tcp_server_legacy.c src/transport/tcp_server_mst_legacy.c src/transport/tcp_service_legacy.c +src/transport/transport-testing-filenames.c +src/transport/transport-testing-loggers.c +src/transport/transport-testing-main.c +src/transport/transport-testing-send.c +src/transport/transport-testing.c src/transport/transport_api2_communication.c src/transport/transport_api_address_to_string.c src/transport/transport_api_blacklist.c @@ -438,11 +445,6 @@ src/transport/transport_api_manipulation.c src/transport/transport_api_monitor_peers.c src/transport/transport_api_monitor_plugins.c src/transport/transport_api_offer_hello.c -src/transport/transport-testing.c -src/transport/transport-testing-filenames.c -src/transport/transport-testing-loggers.c -src/transport/transport-testing-main.c -src/transport/transport-testing-send.c src/util/bandwidth.c src/util/benchmark.c src/util/bio.c @@ -455,8 +457,8 @@ src/util/configuration_loader.c src/util/container_bloomfilter.c src/util/container_heap.c src/util/container_meta_data.c -src/util/container_multihashmap32.c src/util/container_multihashmap.c +src/util/container_multihashmap32.c src/util/container_multipeermap.c src/util/container_multishortmap.c src/util/crypto_abe.c @@ -478,15 +480,15 @@ src/util/dnsparser.c src/util/dnsstub.c src/util/getopt.c src/util/getopt_helpers.c -src/util/gnunet-config.c src/util/gnunet-config-diff.c +src/util/gnunet-config.c src/util/gnunet-ecc.c src/util/gnunet-helper-w32-console.c src/util/gnunet-resolver.c src/util/gnunet-scrypt.c src/util/gnunet-service-resolver.c -src/util/gnunet-timeout.c src/util/gnunet-timeout-w32.c +src/util/gnunet-timeout.c src/util/gnunet-uri.c src/util/helper.c src/util/load.c @@ -514,13 +516,13 @@ src/util/tun.c src/util/w32cat.c src/util/win.c src/util/winproc.c -src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-helper-vpn-windows.c +src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-service-vpn.c src/vpn/gnunet-vpn.c src/vpn/vpn_api.c -src/zonemaster/gnunet-service-zonemaster.c src/zonemaster/gnunet-service-zonemaster-monitor.c +src/zonemaster/gnunet-service-zonemaster.c src/fs/fs_api.h src/include/gnunet_common.h src/include/gnunet_mq_lib.h diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf index 5ad67fec2..30e496aff 100644 --- a/src/cadet/test_cadet.conf +++ b/src/cadet/test_cadet.conf @@ -98,3 +98,7 @@ START_ON_DEMAND = NO [topology] IMMEDIATE_START = NO START_ON_DEMAND = NO + +[rps] +IMMEDIATE_START = NO +START_ON_DEMAND = NO diff --git a/src/fs/fs_getopt.c b/src/fs/fs_getopt.c index 7b5c2991d..cbd9339c9 100644 --- a/src/fs/fs_getopt.c +++ b/src/fs/fs_getopt.c @@ -38,19 +38,20 @@ * @param scls must be of type "struct GNUNET_FS_Uri **" * @param option name of the option (typically 'k') * @param value command line argument given - * @return GNUNET_OK on success + * @return #GNUNET_OK on success */ static int -getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext - *ctx, void *scls, const char *option, - const char *value) +getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, + void *scls, + const char *option, + const char *value) { struct GNUNET_FS_Uri **uri = scls; struct GNUNET_FS_Uri *u = *uri; char *val; size_t slen; - if (u == NULL) + if (NULL == u) { u = GNUNET_new (struct GNUNET_FS_Uri); *uri = u; @@ -60,10 +61,10 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext } else { - GNUNET_assert (u->type == GNUNET_FS_URI_KSK); + GNUNET_assert (GNUNET_FS_URI_KSK == u->type); } slen = strlen (value); - if (slen == 0) + if (0 == slen) return GNUNET_SYSERR; /* cannot be empty */ if (value[0] == '+') { @@ -75,7 +76,9 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext /* remove the quotes, keep the '+' */ val = GNUNET_malloc (slen - 1); val[0] = '+'; - GNUNET_memcpy (&val[1], &value[2], slen - 3); + GNUNET_memcpy (&val[1], + &value[2], + slen - 3); val[slen - 2] = '\0'; } else @@ -91,7 +94,9 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext /* remove the quotes, add a space */ val = GNUNET_malloc (slen); val[0] = ' '; - GNUNET_memcpy (&val[1], &value[1], slen - 2); + GNUNET_memcpy (&val[1], + &value[1], + slen - 2); val[slen - 1] = '\0'; } else @@ -102,10 +107,13 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext strcat (val, value); } } - GNUNET_array_append (u->data.ksk.keywords, u->data.ksk.keywordCount, val); + GNUNET_array_append (u->data.ksk.keywords, + u->data.ksk.keywordCount, + val); return GNUNET_OK; } + /** * Allow user to specify keywords. * @@ -135,6 +143,7 @@ GNUNET_FS_GETOPT_KEYWORDS (char shortName, return clo; } + /** * Command-line option parser function that allows the user to specify * one or more '-m' options with metadata. Each specified entry of diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c index 999301c2f..ffcf9b5d0 100644 --- a/src/fs/gnunet-publish.c +++ b/src/fs/gnunet-publish.c @@ -496,21 +496,22 @@ uri_ksk_continuation (void *cls, emsg); ret = 1; } - if (NULL != namespace) + if (NULL == namespace) { - priv = GNUNET_IDENTITY_ego_get_private_key (namespace); - GNUNET_FS_publish_sks (ctx, - priv, - this_id, - next_id, - meta, - uri, - &bo, - GNUNET_FS_PUBLISH_OPTION_NONE, - &uri_sks_continuation, NULL); + GNUNET_SCHEDULER_shutdown (); return; } - GNUNET_SCHEDULER_shutdown (); + priv = GNUNET_IDENTITY_ego_get_private_key (namespace); + GNUNET_FS_publish_sks (ctx, + priv, + this_id, + next_id, + meta, + uri, + &bo, + GNUNET_FS_PUBLISH_OPTION_NONE, + &uri_sks_continuation, + NULL); } @@ -728,7 +729,8 @@ identity_continuation (const char *args0) GNUNET_SCHEDULER_shutdown (); return; } - GNUNET_FS_publish_ksk (ctx, topKeywords, + GNUNET_FS_publish_ksk (ctx, + topKeywords, meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, @@ -889,7 +891,8 @@ run (void *cls, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_option_uint ('a', @@ -922,26 +925,22 @@ main (int argc, char *const *argv) "TYPE:VALUE", gettext_noop ("set the meta-data for the given TYPE to the given VALUE"), &meta), - GNUNET_GETOPT_option_flag ('n', - "noindex", - gettext_noop ("do not index, perform full insertion (stores " - "entire file in encrypted form in GNUnet database)"), - &do_insert), - + "noindex", + gettext_noop ("do not index, perform full insertion (stores " + "entire file in encrypted form in GNUnet database)"), + &do_insert), GNUNET_GETOPT_option_string ('N', "next", "ID", gettext_noop ("specify ID of an updated version to be " "published in the future (for namespace insertions only)"), &next_id), - GNUNET_GETOPT_option_uint ('p', - "priority", - "PRIORITY", - gettext_noop ("specify the priority of the content"), - &bo.content_priority), - + "priority", + "PRIORITY", + gettext_noop ("specify the priority of the content"), + &bo.content_priority), GNUNET_GETOPT_option_string ('P', "pseudonym", "NAME", @@ -964,7 +963,6 @@ main (int argc, char *const *argv) gettext_noop ("set the ID of this version of the publication " "(for namespace insertions only)"), &this_id), - GNUNET_GETOPT_option_string ('u', "uri", "URI", @@ -982,10 +980,14 @@ main (int argc, char *const *argv) if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-publish [OPTIONS] FILENAME", + GNUNET_PROGRAM_run (argc, + argv, + "gnunet-publish [OPTIONS] FILENAME", gettext_noop ("Publish a file or directory on GNUnet"), - options, &run, NULL)) ? ret : 1; + options, + &run, + NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } diff --git a/src/fs/gnunet-search.c b/src/fs/gnunet-search.c index 780b3c93d..2a0a153e7 100644 --- a/src/fs/gnunet-search.c +++ b/src/fs/gnunet-search.c @@ -304,49 +304,44 @@ int main (int argc, char *const *argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_uint ('a', - "anonymity", - "LEVEL", - gettext_noop ("set the desired LEVEL of receiver-anonymity"), - &anonymity), - - + "anonymity", + "LEVEL", + gettext_noop ("set the desired LEVEL of receiver-anonymity"), + &anonymity), GNUNET_GETOPT_option_flag ('n', - "no-network", - gettext_noop ("only search the local peer (no P2P network search)"), - &local_only), - + "no-network", + gettext_noop ("only search the local peer (no P2P network search)"), + &local_only), GNUNET_GETOPT_option_string ('o', "output", "PREFIX", gettext_noop ("write search results to file starting with PREFIX"), &output_filename), - GNUNET_GETOPT_option_relative_time ('t', - "timeout", - "DELAY", - gettext_noop ("automatically terminate search after DELAY"), - &timeout), - - + "timeout", + "DELAY", + gettext_noop ("automatically terminate search after DELAY"), + &timeout), GNUNET_GETOPT_option_verbose (&verbose), - GNUNET_GETOPT_option_uint ('N', - "results", - "VALUE", - gettext_noop ("automatically terminate search " - "after VALUE results are found"), - &results_limit), - + "results", + "VALUE", + gettext_noop ("automatically terminate search " + "after VALUE results are found"), + &results_limit), 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; ret = (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-search [OPTIONS] KEYWORD", + GNUNET_PROGRAM_run (argc, + argv, + "gnunet-search [OPTIONS] KEYWORD", gettext_noop ("Search GNUnet for files that were published on GNUnet"), options, &run, NULL)) ? ret : 1; diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index a9013390e..e1997e215 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c @@ -59,6 +59,12 @@ #define MAX_HTTP_URI_LENGTH 2048 /** + * Maximum number of DANE records we support + * per domain name (and port and protocol). + */ +#define MAX_DANES 32 + +/** * Size of the buffer for the data upload / download. Must be * enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k). */ @@ -543,9 +549,9 @@ struct Socks5Request char *leho; /** - * Payload of the (last) DANE record encountered. + * Payload of the DANE records encountered. */ - char *dane_data; + char *dane_data[MAX_DANES + 1]; /** * The URL to fetch @@ -575,7 +581,13 @@ struct Socks5Request /** * Number of bytes in @e dane_data. */ - size_t dane_data_len; + int dane_data_len[MAX_DANES + 1]; + + /** + * Number of entries used in @e dane_data_len + * and @e dane_data. + */ + unsigned int num_danes; /** * Number of bytes already in read buffer @@ -816,7 +828,8 @@ cleanup_s5r (struct Socks5Request *s5r) GNUNET_free_non_null (s5r->domain); GNUNET_free_non_null (s5r->leho); GNUNET_free_non_null (s5r->url); - GNUNET_free_non_null (s5r->dane_data); + for (unsigned int i=0;i<s5r->num_danes;i++) + GNUNET_free (s5r->dane_data[i]); GNUNET_free (s5r); } @@ -989,10 +1002,8 @@ check_ssl_certificate (struct Socks5Request *s5r) } /* check for TLSA/DANE records */ #if HAVE_GNUTLS_DANE - if (NULL != s5r->dane_data) + if (0 != s5r->num_danes) { - char *dd[] = { s5r->dane_data, NULL }; - int dlen[] = { s5r->dane_data_len, 0}; dane_state_t dane_state; dane_query_t dane_query; unsigned int verify; @@ -1010,10 +1021,12 @@ check_ssl_certificate (struct Socks5Request *s5r) gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } + s5r->dane_data[s5r->num_danes] = NULL; + s5r->dane_data_len[s5r->num_danes] = 0; if (0 != (rc = dane_raw_tlsa (dane_state, &dane_query, - dd, - dlen, + s5r->dane_data, + s5r->dane_data_len, GNUNET_YES, GNUNET_NO))) { @@ -3070,12 +3083,17 @@ handle_gns_result (void *cls, (ntohs (box->protocol) != IPPROTO_TCP) || (ntohs (box->service) != s5r->port) ) break; /* BOX record does not apply */ - GNUNET_free_non_null (s5r->dane_data); - s5r->dane_data_len = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord); - s5r->dane_data = GNUNET_malloc (s5r->dane_data_len); - GNUNET_memcpy (s5r->dane_data, - &box[1], - s5r->dane_data_len); + if (s5r->num_danes >= MAX_DANES) + { + GNUNET_break (0); /* MAX_DANES too small */ + break; + } + s5r->dane_data_len[s5r->num_danes] + = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord); + s5r->dane_data[s5r->num_danes] + = GNUNET_memdup (&box[1], + s5r->dane_data_len); + s5r->num_danes++; break; } default: diff --git a/src/gns/test_gns_defaults.conf b/src/gns/test_gns_defaults.conf index 19ba01ebb..80a2f3c44 100644 --- a/src/gns/test_gns_defaults.conf +++ b/src/gns/test_gns_defaults.conf @@ -20,3 +20,15 @@ PLUGINS = tcp [transport-tcp] BINDTO = 127.0.0.1 + +[fs] +IMMEDIATE_START = NO +START_ON_DEMAND = NO + +[rps] +IMMEDIATE_START = NO +START_ON_DEMAND = NO + +[topology] +IMMEDIATE_START = NO +START_ON_DEMAND = NO diff --git a/src/gns/test_gns_gns2dns_cname_lookup.sh b/src/gns/test_gns_gns2dns_cname_lookup.sh index 84ad8549f..17196f820 100755 --- a/src/gns/test_gns_gns2dns_cname_lookup.sh +++ b/src/gns/test_gns_gns2dns_cname_lookup.sh @@ -43,7 +43,15 @@ MY_EGO="myego" # various names we will use for resolution TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO" +which timeout &> /dev/null && DO_TIMEOUT="timeout 15" + + gnunet-arm -s -c test_gns_lookup.conf + +echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found, skipping test"; exit 77; } +echo $OUT | grep $TEST6_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found, skipping test"; exit 77; } + + gnunet-identity -C $MY_EGO -c test_gns_lookup.conf # set IP address for DNS resolver for resolving in gnunet.org domain @@ -52,7 +60,6 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECOR gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS2 -e never -c test_gns_lookup.conf gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS3 -e never -c test_gns_lookup.conf -which timeout &> /dev/null && DO_TIMEOUT="timeout 15" echo "EGOs:" gnunet-identity -d diff --git a/src/gns/test_gns_gns2dns_lookup.sh b/src/gns/test_gns_gns2dns_lookup.sh index 122e45525..431f01086 100755 --- a/src/gns/test_gns_gns2dns_lookup.sh +++ b/src/gns/test_gns_gns2dns_lookup.sh @@ -44,8 +44,17 @@ TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO" TEST_DOMAIN_ALT="${TEST_RECORD_NAME}.$MY_EGO" TEST_DOMAIN_ALT2="docs.${TEST_RECORD_NAME}.$MY_EGO" +which timeout &> /dev/null && DO_TIMEOUT="timeout 15" + gnunet-arm -s -c test_gns_lookup.conf + +OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf gnunet.org` +echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found, skipping test"; exit 77; } +echo $OUT | grep $TEST6_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found, skipping test"; exit 77; } + + + gnunet-identity -C $MY_EGO -c test_gns_lookup.conf # set IP address for DNS resolver for resolving in gnunet.org domain @@ -53,7 +62,6 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RESOLVER_LABEL -t A -V $TEST_IP_GNS2D # map '$TEST_RECORD_NAME.$MY_EGO' to 'gnunet.org' in DNS gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf -which timeout &> /dev/null && DO_TIMEOUT="timeout 15" echo "EGOs:" gnunet-identity -d diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index b80d86073..f0d7a839e 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -28,10 +28,7 @@ #include "gnunet_constants.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gnsrecord_plugin.h" -#include "gnunet_json_lib.h" #include "gnunet_tun_lib.h" -#include <jansson.h> - #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) diff --git a/src/include/gnunet_configuration_lib.h b/src/include/gnunet_configuration_lib.h index e3eefa18d..ec3d12738 100644 --- a/src/include/gnunet_configuration_lib.h +++ b/src/include/gnunet_configuration_lib.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2006, 2008, 2009 GNUnet e.V. + Copyright (C) 2006, 2008, 2009, 2018 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 @@ -191,6 +191,35 @@ GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg); /** + * Signature of a function to be run with a configuration. + * + * @param cls closure + * @param cfg the configuration + * @return status code + */ +typedef int +(*GNUNET_CONFIGURATION_Callback)(void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Parse a configuration file @a filename and run the function + * @a cb with the resulting configuration object. Then free the + * configuration object and return the status value from @a cb. + * + * @param filename configuration to parse, NULL for "default" + * @param cb function to run + * @param cb_cls closure for @a cb + * @return #GNUNET_SYSERR if parsing the configuration failed, + * otherwise return value from @a cb. + */ +int +GNUNET_CONFIGURATION_parse_and_run (const char *filename, + GNUNET_CONFIGURATION_Callback cb, + void *cb_cls); + + +/** * Function to iterate over options. * * @param cls closure diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 898ad6258..fbdee5415 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -3051,15 +3051,30 @@ extern "C" #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE 1206 /** + * Response from communicator: will try to create queue. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK 1207 + +/** + * Response from communicator: address bogus, will not try to create queue. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL 1208 + +/** * @brief transport tells communicator it wants to transmit */ -#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1207 +#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1209 /** * @brief communicator tells transports that message was sent */ -#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1208 +#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1210 +/** + * Message sent to indicate to the transport which address + * prefix is supported by a communicator. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR 1211 /** * Next available: 1300 diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h index d93d5134e..50f94bddf 100644 --- a/src/include/gnunet_transport_communication_service.h +++ b/src/include/gnunet_transport_communication_service.h @@ -42,6 +42,7 @@ extern "C" #endif #include "gnunet_util_lib.h" +#include "gnunet_ats_service.h" /** * Version number of the transport communication API. @@ -69,7 +70,7 @@ extern "C" typedef int (*GNUNET_TRANSPORT_CommunicatorMqInit) (void *cls, const struct GNUNET_PeerIdentity *peer, - const void *address); + const char *address); /** @@ -82,7 +83,9 @@ struct GNUNET_TRANSPORT_CommunicatorHandle; * Connect to the transport service. * * @param cfg configuration to use - * @param name name of the communicator that is connecting + * @param config_section section of the configuration to use for options + * @param addr_prefix address prefix for addresses supported by this + * communicator, could be NULL for incoming-only communicators * @param mtu maximum message size supported by communicator, 0 if * sending is not supported, SIZE_MAX for no MTU * @param mq_init function to call to initialize a message queue given @@ -93,7 +96,8 @@ struct GNUNET_TRANSPORT_CommunicatorHandle; */ struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *name, + const char *config_section_name, + const char *addr_prefix, size_t mtu, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls); diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index c5f48848e..619d0c528 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c @@ -33,6 +33,24 @@ /** + * Entry in record set for bulk processing. + */ +struct RecordSetEntry +{ + /** + * Kept in a linked list. + */ + struct RecordSetEntry *next; + + /** + * The record to add/remove. + */ + struct GNUNET_GNSRECORD_Data record; + +}; + + +/** * Handle to the namestore. */ static struct GNUNET_NAMESTORE_Handle *ns; @@ -173,14 +191,10 @@ static void *data; static size_t data_size; /** - * Expirationstring converted to relative time. + * Expiration string converted to numeric value. */ -static struct GNUNET_TIME_Relative etime_rel; +static uint64_t etime; -/** - * Expirationstring converted to absolute time. - */ -static struct GNUNET_TIME_Absolute etime_abs; /** * Is expiration time relative or absolute time? @@ -197,6 +211,11 @@ static struct GNUNET_NAMESTORE_ZoneMonitor *zm; */ static int monitor; +/** + * Entry in record set for processing records in bulk. + */ +static struct RecordSetEntry *recordset; + /** * Task run on shutdown. Cleans up everything. @@ -516,6 +535,8 @@ display_record_lookup (void *cls, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { + (void) cls; + (void) zone_key; get_qe = NULL; display_record (rname, rd_len, @@ -694,14 +715,10 @@ get_existing_record (void *cls, rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; if (1 != is_public) rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; + rde->expiration_time = etime; if (GNUNET_YES == etime_is_rel) - { - rde->expiration_time = etime_rel.rel_value_us; rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_NO == etime_is_rel) - rde->expiration_time = etime_abs.abs_value_us; - else + else if (GNUNET_NO != etime_is_rel) rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; GNUNET_assert (NULL != name); add_qe = GNUNET_NAMESTORE_records_store (ns, @@ -864,6 +881,94 @@ del_monitor (void *cls, /** + * Parse expiration time. + * + * @param expirationstring text to parse + * @param etime_is_rel[out] set to #GNUNET_YES if time is relative + * @param etime[out] set to expiration time (abs or rel) + * @return #GNUNET_OK on success + */ +static int +parse_expiration (const char *expirationstring, + int *etime_is_rel, + uint64_t *etime) +{ + struct GNUNET_TIME_Relative etime_rel; + struct GNUNET_TIME_Absolute etime_abs; + + if (0 == strcmp (expirationstring, + "never")) + { + *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + *etime_is_rel = GNUNET_NO; + return GNUNET_OK; + } + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_relative (expirationstring, + &etime_rel)) + { + *etime_is_rel = GNUNET_YES; + *etime = etime_rel.rel_value_us; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Storing record with relative expiration time of %s\n", + GNUNET_STRINGS_relative_time_to_string (etime_rel, + GNUNET_NO)); + return GNUNET_OK; + } + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, + &etime_abs)) + { + *etime_is_rel = GNUNET_NO; + *etime = etime_abs.abs_value_us; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Storing record with absolute expiration time of %s\n", + GNUNET_STRINGS_absolute_time_to_string (etime_abs)); + return GNUNET_OK; + } + return GNUNET_SYSERR; +} + + +#if 0 +/* globals? */ +unsigned int rd_count; +struct GNUNET_GNSRECORD_Data *rd; + + +rd_count = 0; +for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) + rd_count++; +rd = GNUNET_new_array (rd_count, + struct GNUNET_GNSRECORD_Data); +rd_count = 0; +for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) +{ + rd[rd_count] = e->record; + rd_count++; +} + +/* if add: */ +qe = GNUNET_NAMESTORE_records_store (..., + rd_count, + rd, + &my_cont + ..); + +in 'my_cont' and/or shutdown: + +qe = NULL; +GNUNET_free (rd); + +in shutdown: + +if NULL != qe NAMESTORE_cancel (qe); +GNUNET_free (rd); + +#endif + + +/** * Callback invoked from identity service with ego information. * An @a ego of NULL means the ego was not found. * @@ -976,32 +1081,10 @@ identity_cb (void *cls, ret = 1; return; } - if (0 == strcmp (expirationstring, - "never")) - { - etime_abs = GNUNET_TIME_UNIT_FOREVER_ABS; - etime_is_rel = GNUNET_NO; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_relative (expirationstring, - &etime_rel)) - { - etime_is_rel = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Storing record with relative expiration time of %s\n", - GNUNET_STRINGS_relative_time_to_string (etime_rel, - GNUNET_NO)); - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, - &etime_abs)) - { - etime_is_rel = GNUNET_NO; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Storing record with absolute expiration time of %s\n", - GNUNET_STRINGS_absolute_time_to_string (etime_abs)); - } - else + if (GNUNET_OK != + parse_expiration (expirationstring, + &etime_is_rel, + &etime)) { fprintf (stderr, _("Invalid time format `%s'\n"), @@ -1106,16 +1189,9 @@ identity_cb (void *cls, rd.data = &pkey; rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; - if (GNUNET_YES == etime_is_rel) - { - rd.expiration_time = etime_rel.rel_value_us; + rd.expiration_time = etime; + if (GNUNET_YES == etime_is_rel) rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_NO == etime_is_rel) - rd.expiration_time = etime_abs.abs_value_us; - else - rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - if (1 == is_shadow) rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; add_qe_uri = GNUNET_NAMESTORE_records_store (ns, @@ -1247,6 +1323,161 @@ run (void *cls, /** + * Command-line option parser function that allows the user to specify + * a complete record as one argument for adding/removing. A pointer + * to the head of the list of record sets must be passed as the "scls" + * argument. + * + * @param ctx command line processor context + * @param scls must be of type "struct GNUNET_FS_Uri **" + * @param option name of the option (typically 'R') + * @param value command line argument given; format is + * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs), + * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or + * a combination of 's' (shadow) and 'p' (public) and VALUE is the + * value (in human-readable format) + * @return #GNUNET_OK on success + */ +static int +multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, + void *scls, + const char *option, + const char *value) +{ + struct RecordSetEntry **head = scls; + struct RecordSetEntry *r; + struct GNUNET_GNSRECORD_Data record; + char *cp; + char *tok; + int etime_is_rel; + void *raw_data; + + (void) ctx; + (void) option; + cp = GNUNET_strdup (value); + tok = strtok (cp, " "); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Empty record line argument is not allowed.\n")); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + parse_expiration (tok, + &etime_is_rel, + &record.expiration_time)) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Invalid expiration time `%s'\n"), + tok); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + tok = strtok (NULL, " "); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Missing entries in record line `%s'.\n"), + value); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + record.record_type = GNUNET_GNSRECORD_typename_to_number (tok); + if (UINT32_MAX == record.record_type) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Unknown record type `%s'\n"), + tok); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + tok = strtok (NULL, " "); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Missing entries in record line `%s'.\n"), + value); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + record.flags = GNUNET_GNSRECORD_RF_NONE; + if (etime_is_rel) + record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */ + record.flags |= GNUNET_GNSRECORD_RF_PRIVATE; + if (NULL != strchr (tok, (unsigned char) 's')) + record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; + /* find beginning of record value */ + tok = strchr (&value[tok - cp], (unsigned char) ' '); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Missing entries in record line `%s'.\n"), + value); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + GNUNET_free (cp); + tok++; /* skip space */ + if (GNUNET_OK != + GNUNET_GNSRECORD_string_to_value (record.record_type, + tok, + &raw_data, + &record.data_size)) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Invalid record data for type %s: `%s'.\n"), + GNUNET_GNSRECORD_number_to_typename (record.record_type), + tok); + return GNUNET_SYSERR; + } + + r = GNUNET_malloc (sizeof (struct RecordSetEntry) + record.data_size); + r->next = *head; + record.data = &r[1]; + memcpy (&r[1], + raw_data, + record.data_size); + GNUNET_free (raw_data); + r->record = record; + *head = r; + return GNUNET_OK; +} + + +/** + * Allow user to specify keywords. + * + * @param shortName short name of the option + * @param name long name of the option + * @param argumentHelp help text for the option argument + * @param description long help text for the option + * @param[out] topKeywords set to the desired value + */ +struct GNUNET_GETOPT_CommandLineOption +multirecord_option (char shortName, + const char *name, + const char *argumentHelp, + const char *description, + struct RecordSetEntry **rs) +{ + struct GNUNET_GETOPT_CommandLineOption clo = { + .shortName = shortName, + .name = name, + .argumentHelp = argumentHelp, + .description = description, + .require_argument = 1, + .processor = &multirecord_process, + .scls = (void *) rs + }; + + return clo; +} + + + +/** * The main function for gnunet-namestore. * * @param argc number of arguments from the command line @@ -1294,6 +1525,11 @@ main (int argc, "PKEY", gettext_noop ("determine our name for the given PKEY"), &reverse_pkey), + multirecord_option ('R', + "record", + "RECORDLINE", + gettext_noop ("complete record on one line to add/delete/display; can be specified multiple times"), + &recordset), GNUNET_GETOPT_option_string ('t', "type", "TYPE", diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c index f7a4e4525..dd384d9a1 100644 --- a/src/topology/gnunet-daemon-topology.c +++ b/src/topology/gnunet-daemon-topology.c @@ -1213,7 +1213,8 @@ run (void *cls, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END diff --git a/src/transport/.gitignore b/src/transport/.gitignore index d035b4011..90f908a47 100644 --- a/src/transport/.gitignore +++ b/src/transport/.gitignore @@ -83,3 +83,4 @@ test_transport_blacklisting_outbound_bl_full test_transport_blacklisting_outbound_bl_plugin test_transport_testing_restart test_transport_testing_startstop +gnunet-communicator-unix diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index d0db6b141..92b53137f 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -140,6 +140,7 @@ endif noinst_PROGRAMS = \ gnunet-transport-profiler \ + gnunet-communicator-unix \ $(WLAN_BIN_SENDER) \ $(WLAN_BIN_RECEIVER) @@ -149,6 +150,7 @@ endif lib_LTLIBRARIES = \ libgnunettransport.la \ + libgnunettransportcommunicator.la \ $(TESTING_LIBS) libgnunettransporttesting_la_SOURCES = \ @@ -187,6 +189,17 @@ libgnunettransport_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:2 + + +libgnunettransportcommunicator_la_SOURCES = \ + transport_api2_communication.c +libgnunettransportcommunicator_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +libgnunettransportcommunicator_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + libexec_PROGRAMS = \ $(WLAN_BIN) \ $(WLAN_BIN_DUMMY) \ @@ -207,6 +220,14 @@ gnunet_transport_certificate_creation_SOURCES = \ gnunet_transport_certificate_creation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +gnunet_communicator_unix_SOURCES = \ + gnunet-communicator-unix.c +gnunet_communicator_unix_LDADD = \ + libgnunettransportcommunicator.la \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la + + gnunet_helper_transport_wlan_SOURCES = \ gnunet-helper-transport-wlan.c diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c new file mode 100644 index 000000000..cd3ae5dce --- /dev/null +++ b/src/transport/gnunet-communicator-unix.c @@ -0,0 +1,1148 @@ +/* + This file is part of GNUnet + Copyright (C) 2010-2014, 2018 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/>. +*/ + +/** + * @file transport/gnunet-communicator-unix.c + * @brief Transport plugin using unix domain sockets (!) + * Clearly, can only be used locally on Unix/Linux hosts... + * ONLY INTENDED FOR TESTING!!! + * @author Christian Grothoff + * @author Nathan Evans + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_statistics_service.h" +#include "gnunet_transport_communication_service.h" + +/** + * How many messages do we keep at most in the queue to the + * transport service before we start to drop (default, + * can be changed via the configuration file). + * Should be _below_ the level of the communicator API, as + * otherwise we may read messages just to have them dropped + * by the communicator API. + */ +#define DEFAULT_MAX_QUEUE_LENGTH 8 + +/** + * Address prefix used by the communicator. + */ +#define COMMUNICATOR_ADDRESS_PREFIX "unix" + +/** + * Configuration section used by the communicator. + */ +#define COMMUNICATOR_CONFIG_SECTION "communicator-unix" + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * UNIX Message-Packet header. + */ +struct UNIXMessage +{ + /** + * Message header. + */ + struct GNUNET_MessageHeader header; + + /** + * What is the identity of the sender (GNUNET_hash of public key) + */ + struct GNUNET_PeerIdentity sender; + +}; + +GNUNET_NETWORK_STRUCT_END + + +/** + * Handle for a queue. + */ +struct Queue +{ + + /** + * Queues with pending messages (!) are kept in a DLL. + */ + struct Queue *next; + + /** + * Queues with pending messages (!) are kept in a DLL. + */ + struct Queue *prev; + + /** + * To whom are we talking to. + */ + struct GNUNET_PeerIdentity target; + + /** + * Address of the other peer. + */ + struct sockaddr_un *address; + + /** + * Length of the address. + */ + socklen_t address_len; + + /** + * Message currently scheduled for transmission, non-NULL if and only + * if this queue is in the #queue_head DLL. + */ + const struct GNUNET_MessageHeader *msg; + + /** + * Message queue we are providing for the #ch. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * handle for this queue with the #ch. + */ + struct GNUNET_TRANSPORT_QueueHandle *qh; + + /** + * Number of bytes we currently have in our write queue. + */ + unsigned long long bytes_in_queue; + + /** + * Timeout for this queue. + */ + struct GNUNET_TIME_Absolute timeout; + + /** + * Queue timeout task. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + +}; + + +/** + * ID of read task + */ +static struct GNUNET_SCHEDULER_Task *read_task; + +/** + * ID of write task + */ +static struct GNUNET_SCHEDULER_Task *write_task; + +/** + * Number of messages we currently have in our queues towards the transport service. + */ +static unsigned long long delivering_messages; + +/** + * Maximum queue length before we stop reading towards the transport service. + */ +static unsigned long long max_queue_length; + +/** + * For logging statistics. + */ +static struct GNUNET_STATISTICS_Handle *stats; + +/** + * Our environment. + */ +static struct GNUNET_TRANSPORT_CommunicatorHandle *ch; + +/** + * Queues (map from peer identity to `struct Queue`) + */ +static struct GNUNET_CONTAINER_MultiPeerMap *queue_map; + +/** + * Head of queue of messages to transmit. + */ +static struct Queue *queue_head; + +/** + * Tail of queue of messages to transmit. + */ +static struct Queue *queue_tail; + +/** + * socket that we transmit all data with + */ +static struct GNUNET_NETWORK_Handle *unix_sock; + +/** + * Handle to the operation that publishes our address. + */ +static struct GNUNET_TRANSPORT_AddressIdentifier *ai; + + +/** + * Functions with this signature are called whenever we need + * to close a queue due to a disconnect or failure to + * establish a connection. + * + * @param queue queue to close down + */ +static void +queue_destroy (struct Queue *queue) +{ + struct GNUNET_MQ_Handle *mq; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting queue for peer `%s'\n", + GNUNET_i2s (&queue->target)); + if (0 != queue->bytes_in_queue) + { + GNUNET_CONTAINER_DLL_remove (queue_head, + queue_tail, + queue); + queue->bytes_in_queue = 0; + } + if (NULL != (mq = queue->mq)) + { + queue->mq = NULL; + GNUNET_MQ_destroy (mq); + } + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (queue_map, + &queue->target, + queue)); + GNUNET_STATISTICS_set (stats, + "# UNIX queues active", + GNUNET_CONTAINER_multipeermap_size (queue_map), + GNUNET_NO); + if (NULL != queue->timeout_task) + { + GNUNET_SCHEDULER_cancel (queue->timeout_task); + queue->timeout_task = NULL; + } + GNUNET_free (queue->address); + GNUNET_free (queue); +} + + +/** + * Queue was idle for too long, so disconnect it + * + * @param cls the `struct Queue *` to disconnect + */ +static void +queue_timeout (void *cls) +{ + struct Queue *queue = cls; + struct GNUNET_TIME_Relative left; + + queue->timeout_task = NULL; + left = GNUNET_TIME_absolute_get_remaining (queue->timeout); + if (0 != left.rel_value_us) + { + /* not actually our turn yet, but let's at least update + the monitor, it may think we're about to die ... */ + queue->timeout_task + = GNUNET_SCHEDULER_add_delayed (left, + &queue_timeout, + queue); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Queue %p was idle for %s, disconnecting\n", + queue, + GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + GNUNET_YES)); + queue_destroy (queue); +} + + +/** + * Increment queue timeout due to activity. We do not immediately + * notify the monitor here as that might generate excessive + * signalling. + * + * @param queue queue for which the timeout should be rescheduled + */ +static void +reschedule_queue_timeout (struct Queue *queue) +{ + GNUNET_assert (NULL != queue->timeout_task); + queue->timeout + = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); +} + + +/** + * Convert unix path to a `struct sockaddr_un *` + * + * @param unixpath path to convert + * @param[out] sock_len set to the length of the address + * @param is_abstract is this an abstract @a unixpath + * @return converted unix path + */ +static struct sockaddr_un * +unix_address_to_sockaddr (const char *unixpath, + socklen_t *sock_len) +{ + struct sockaddr_un *un; + size_t slen; + + GNUNET_assert (0 < strlen (unixpath)); /* sanity check */ + un = GNUNET_new (struct sockaddr_un); + un->sun_family = AF_UNIX; + slen = strlen (unixpath); + if (slen >= sizeof (un->sun_path)) + slen = sizeof (un->sun_path) - 1; + GNUNET_memcpy (un->sun_path, + unixpath, + slen); + un->sun_path[slen] = '\0'; + slen = sizeof (struct sockaddr_un); +#if HAVE_SOCKADDR_UN_SUN_LEN + un->sun_len = (u_char) slen; +#endif + (*sock_len) = slen; + if ('@' == un->sun_path[0]) + un->sun_path[0] = '\0'; + return un; +} + + +/** + * Closure to #lookup_queue_it(). + */ +struct LookupCtx +{ + /** + * Location to store the queue, if found. + */ + struct Queue *res; + + /** + * Address we are looking for. + */ + const struct sockaddr_un *un; + + /** + * Number of bytes in @a un + */ + socklen_t un_len; +}; + + +/** + * Function called to find a queue by address. + * + * @param cls the `struct LookupCtx *` + * @param key peer we are looking for (unused) + * @param value a queue + * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success + */ +static int +lookup_queue_it (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) +{ + struct LookupCtx *lctx = cls; + struct Queue *queue = value; + + if ( (queue->address_len = lctx->un_len) && + (0 == memcmp (lctx->un, + queue->address, + queue->address_len)) ) + { + lctx->res = queue; + return GNUNET_NO; + } + return GNUNET_YES; +} + + +/** + * Find an existing queue by address. + * + * @param plugin the plugin + * @param address the address to find + * @return NULL if queue was not found + */ +static struct Queue * +lookup_queue (const struct GNUNET_PeerIdentity *peer, + const struct sockaddr_un *un, + socklen_t un_len) +{ + struct LookupCtx lctx; + + lctx.un = un; + lctx.un_len = un_len; + GNUNET_CONTAINER_multipeermap_get_multiple (queue_map, + peer, + &lookup_queue_it, + &lctx); + return lctx.res; +} + + +/** + * We have been notified that our socket is ready to write. + * Then reschedule this function to be called again once more is available. + * + * @param cls NULL + */ +static void +select_write_cb (void *cls) +{ + struct Queue *queue = queue_tail; + const struct GNUNET_MessageHeader *msg = queue->msg; + size_t msg_size = ntohs (msg->size); + ssize_t sent; + + /* take queue of the ready list */ + write_task = NULL; + GNUNET_CONTAINER_DLL_remove (queue_head, + queue_tail, + queue); + if (NULL != queue_head) + write_task = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_write_cb, + NULL); + + /* send 'msg' */ + queue->msg = NULL; + GNUNET_MQ_impl_send_continue (queue->mq); + resend: + /* Send the data */ + sent = GNUNET_NETWORK_socket_sendto (unix_sock, + queue->msg, + msg_size, + (const struct sockaddr *) queue->address, + queue->address_len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "UNIX transmitted message to %s (%d/%u: %s)\n", + GNUNET_i2s (&queue->target), + (int) sent, + (unsigned int) msg_size, + (sent < 0) ? STRERROR (errno) : "ok"); + if (-1 != sent) + { + GNUNET_STATISTICS_update (stats, + "# bytes sent", + (long long) sent, + GNUNET_NO); + reschedule_queue_timeout (queue); + return; /* all good */ + } + GNUNET_STATISTICS_update (stats, + "# network transmission failures", + 1, + GNUNET_NO); + switch (errno) + { + case EAGAIN: + case ENOBUFS: + /* We should retry later... */ + GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, + "send"); + return; + case EMSGSIZE: + { + socklen_t size = 0; + socklen_t len = sizeof (size); + + GNUNET_NETWORK_socket_getsockopt (unix_sock, + SOL_SOCKET, + SO_SNDBUF, + &size, + &len); + if (size > ntohs (msg->size)) + { + /* Buffer is bigger than message: error, no retry + * This should never happen!*/ + GNUNET_break (0); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to increase socket buffer size from %u to %u for message size %u\n", + (unsigned int) size, + (unsigned int) ((msg_size / 1000) + 2) * 1000, + (unsigned int) msg_size); + size = ((msg_size / 1000) + 2) * 1000; + if (GNUNET_OK == + GNUNET_NETWORK_socket_setsockopt (unix_sock, + SOL_SOCKET, + SO_SNDBUF, + &size, + sizeof (size))) + goto resend; /* Increased buffer size, retry sending */ + /* Ok, then just try very modest increase */ + size = msg_size; + if (GNUNET_OK == + GNUNET_NETWORK_socket_setsockopt (unix_sock, + SOL_SOCKET, + SO_SNDBUF, + &size, + sizeof (size))) + goto resend; /* Increased buffer size, retry sending */ + /* Could not increase buffer size: error, no retry */ + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "setsockopt"); + return; + } + default: + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "send"); + return; + } +} + + +/** + * Signature of functions implementing the sending functionality of a + * message queue. + * + * @param mq the message queue + * @param msg the message to send + * @param impl_state our `struct Queue` + */ +static void +mq_send (struct GNUNET_MQ_Handle *mq, + const struct GNUNET_MessageHeader *msg, + void *impl_state) +{ + struct Queue *queue = impl_state; + + GNUNET_assert (mq == queue->mq); + GNUNET_assert (NULL == queue->msg); + queue->msg = msg; + GNUNET_CONTAINER_DLL_insert (queue_head, + queue_tail, + queue); + if (NULL == write_task) + write_task = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_write_cb, + NULL); +} + + +/** + * Signature of functions implementing the destruction of a message + * queue. Implementations must not free @a mq, but should take care + * of @a impl_state. + * + * @param mq the message queue to destroy + * @param impl_state our `struct Queue` + */ +static void +mq_destroy (struct GNUNET_MQ_Handle *mq, + void *impl_state) +{ + struct Queue *queue = impl_state; + + if (mq == queue->mq) + { + queue->mq = NULL; + queue_destroy (queue); + } +} + + +/** + * Implementation function that cancels the currently sent message. + * + * @param mq message queue + * @param impl_state our `struct Queue` + */ +static void +mq_cancel (struct GNUNET_MQ_Handle *mq, + void *impl_state) +{ + struct Queue *queue = impl_state; + + GNUNET_assert (NULL != queue->msg); + queue->msg = NULL; + GNUNET_CONTAINER_DLL_remove (queue_head, + queue_tail, + queue); + GNUNET_assert (NULL != write_task); + if (NULL == queue_head) + { + GNUNET_SCHEDULER_cancel (write_task); + write_task = NULL; + } +} + + +/** + * Generic error handler, called with the appropriate + * error code and the same closure specified at the creation of + * the message queue. + * Not every message queue implementation supports an error handler. + * + * @param cls our `struct Queue` + * @param error error code + */ +static void +mq_error (void *cls, + enum GNUNET_MQ_Error error) +{ + struct Queue *queue = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "UNIX MQ error in queue to %s: %d\n", + GNUNET_i2s (&queue->target), + (int) error); + queue_destroy (queue); +} + + +/** + * Creates a new outbound queue the transport service will use to send + * data to another peer. + * + * @param peer the target peer + * @param un the address + * @param un_len number of bytes in @a un + * @return the queue or NULL of max connections exceeded + */ +static struct Queue * +setup_queue (const struct GNUNET_PeerIdentity *target, + const struct sockaddr_un *un, + socklen_t un_len) +{ + struct Queue *queue; + + queue = GNUNET_new (struct Queue); + queue->target = *target; + queue->address = GNUNET_memdup (un, + un_len); + queue->address_len = un_len; + (void) GNUNET_CONTAINER_multipeermap_put (queue_map, + &queue->target, + queue, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + GNUNET_STATISTICS_set (stats, + "# queues active", + GNUNET_CONTAINER_multipeermap_size (queue_map), + GNUNET_NO); + queue->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); + queue->timeout_task + = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + &queue_timeout, + queue); + queue->mq + = GNUNET_MQ_queue_for_callbacks (&mq_send, + &mq_destroy, + &mq_cancel, + queue, + NULL, + &mq_error, + queue); + { + char *foreign_addr; + + if ('\0' == un->sun_path[0]) + GNUNET_asprintf (&foreign_addr, + "%s-@%s", + COMMUNICATOR_ADDRESS_PREFIX, + &un->sun_path[1]); + else + GNUNET_asprintf (&foreign_addr, + "%s-%s", + COMMUNICATOR_ADDRESS_PREFIX, + un->sun_path); + queue->qh + = GNUNET_TRANSPORT_communicator_mq_add (ch, + &queue->target, + foreign_addr, + GNUNET_ATS_NET_LOOPBACK, + queue->mq); + GNUNET_free (foreign_addr); + } + return queue; +} + + +/** + * We have been notified that our socket has something to read. Do the + * read and reschedule this function to be called again once more is + * available. + * + * @param cls NULL + */ +static void +select_read_cb (void *cls); + + +/** + * Function called when message was successfully passed to + * transport service. Continue read activity. + * + * @param cls NULL + * @param success #GNUNET_OK on success + */ +static void +receive_complete_cb (void *cls, + int success) +{ + delivering_messages--; + if (GNUNET_OK != success) + GNUNET_STATISTICS_update (stats, + "# transport transmission failures", + 1, + GNUNET_NO); + if ( (NULL == read_task) && + (delivering_messages < max_queue_length) ) + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); +} + + +/** + * We have been notified that our socket has something to read. Do the + * read and reschedule this function to be called again once more is + * available. + * + * @param cls NULL + */ +static void +select_read_cb (void *cls) +{ + char buf[65536] GNUNET_ALIGN; + struct Queue *queue; + const struct UNIXMessage *msg; + struct sockaddr_un un; + socklen_t addrlen; + ssize_t ret; + uint16_t msize; + + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); + addrlen = sizeof (un); + memset (&un, + 0, + sizeof (un)); + ret = GNUNET_NETWORK_socket_recvfrom (unix_sock, + buf, + sizeof (buf), + (struct sockaddr *) &un, + &addrlen); + if ( (-1 == ret) && + ( (EAGAIN == errno) || + (ENOBUFS == errno) ) ) + return; + if (-1 == ret) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "recvfrom"); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Read %d bytes from socket %s\n", + (int) ret, + un.sun_path); + GNUNET_assert (AF_UNIX == (un.sun_family)); + msg = (struct UNIXMessage *) buf; + msize = ntohs (msg->header.size); + if ( (msize < sizeof (struct UNIXMessage)) || + (msize > ret) ) + { + GNUNET_break_op (0); + return; + } + queue = lookup_queue (&msg->sender, + &un, + addrlen); + if (NULL == queue) + queue = setup_queue (&msg->sender, + &un, + addrlen); + else + reschedule_queue_timeout (queue); + if (NULL == queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Maximum number of UNIX connections exceeded, dropping incoming message\n")); + return; + } + + { + uint16_t offset = 0; + uint16_t tsize = msize - sizeof (struct UNIXMessage); + const char *msgbuf = (const char *) &msg[1]; + + while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) + { + const struct GNUNET_MessageHeader *currhdr; + struct GNUNET_MessageHeader al_hdr; + uint16_t csize; + + currhdr = (const struct GNUNET_MessageHeader *) &msgbuf[offset]; + /* ensure aligned access */ + memcpy (&al_hdr, + currhdr, + sizeof (al_hdr)); + csize = ntohs (al_hdr.size); + if ( (csize < sizeof (struct GNUNET_MessageHeader)) || + (csize > tsize - offset)) + { + GNUNET_break_op (0); + break; + } + ret = GNUNET_TRANSPORT_communicator_receive (ch, + &msg->sender, + currhdr, + &receive_complete_cb, + NULL); + if (GNUNET_SYSERR == ret) + return; /* transport not up */ + if (GNUNET_NO == ret) + break; + delivering_messages++; + offset += csize; + } + } + if (delivering_messages >= max_queue_length) + { + /* we should try to apply 'back pressure' */ + GNUNET_SCHEDULER_cancel (read_task); + read_task = NULL; + } +} + + +/** + * Function called by the transport service to initialize a + * message queue given address information about another peer. + * If and when the communication channel is established, the + * communicator must call #GNUNET_TRANSPORT_communicator_mq_add() + * to notify the service that the channel is now up. It is + * the responsibility of the communicator to manage sane + * retries and timeouts for any @a peer/@a address combination + * provided by the transport service. Timeouts and retries + * do not need to be signalled to the transport service. + * + * @param cls closure + * @param peer identity of the other peer + * @param address where to send the message, human-readable + * communicator-specific format, 0-terminated, UTF-8 + * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid + */ +static int +mq_init (void *cls, + const struct GNUNET_PeerIdentity *peer, + const char *address) +{ + struct Queue *queue; + const char *path; + struct sockaddr_un *un; + socklen_t un_len; + + if (0 != strncmp (address, + COMMUNICATOR_ADDRESS_PREFIX "-", + strlen (COMMUNICATOR_ADDRESS_PREFIX "-"))) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; + un = unix_address_to_sockaddr (path, + &un_len); + queue = lookup_queue (peer, + un, + un_len); + if (NULL != queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Address `%s' for %s ignored, queue exists\n", + path, + GNUNET_i2s (peer)); + GNUNET_free (un); + return GNUNET_OK; + } + queue = setup_queue (peer, + un, + un_len); + GNUNET_free (un); + if (NULL == queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Failed to setup queue to %s at `%s'\n", + GNUNET_i2s (peer), + path); + return GNUNET_NO; + } + return GNUNET_OK; +} + + +/** + * Iterator over all message queues to clean up. + * + * @param cls NULL + * @param target unused + * @param value the queue to destroy + * @return #GNUNET_OK to continue to iterate + */ +static int +get_queue_delete_it (void *cls, + const struct GNUNET_PeerIdentity *target, + void *value) +{ + struct Queue *queue = value; + + (void) cls; + (void) target; + queue_destroy (queue); + return GNUNET_OK; +} + + +/** + * Shutdown the UNIX communicator. + * + * @param cls NULL (always) + */ +static void +do_shutdown (void *cls) +{ + if (NULL != read_task) + { + GNUNET_SCHEDULER_cancel (read_task); + read_task = NULL; + } + if (NULL != write_task) + { + GNUNET_SCHEDULER_cancel (write_task); + write_task = NULL; + } + if (NULL != unix_sock) + { + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (unix_sock)); + unix_sock = NULL; + } + GNUNET_CONTAINER_multipeermap_iterate (queue_map, + &get_queue_delete_it, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (queue_map); + if (NULL != ai) + { + GNUNET_TRANSPORT_communicator_address_remove (ai); + ai = NULL; + } + if (NULL != ch) + { + GNUNET_TRANSPORT_communicator_disconnect (ch); + ch = NULL; + } + if (NULL != stats) + { + GNUNET_STATISTICS_destroy (stats, + GNUNET_NO); + stats = NULL; + } +} + + +/** + * Setup communicator and launch network interactions. + * + * @param cls NULL (always) + * @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) +{ + char *unix_socket_path; + struct sockaddr_un *un; + socklen_t un_len; + char *my_addr; + (void) cls; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + COMMUNICATOR_CONFIG_SECTION, + "UNIXPATH", + &unix_socket_path)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + COMMUNICATOR_CONFIG_SECTION, + "UNIXPATH"); + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + COMMUNICATOR_CONFIG_SECTION, + "MAX_QUEUE_LENGTH", + &max_queue_length)) + max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; + + un = unix_address_to_sockaddr (unix_socket_path, + &un_len); + if (NULL == un) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to setup UNIX domain socket address with path `%s'\n", + unix_socket_path); + GNUNET_free (unix_socket_path); + return; + } + unix_sock = GNUNET_NETWORK_socket_create (AF_UNIX, + SOCK_DGRAM, + 0); + if (NULL == unix_sock) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "socket"); + GNUNET_free (un); + GNUNET_free (unix_socket_path); + return; + } + if ( ('\0' != un->sun_path[0]) && + (GNUNET_OK != + GNUNET_DISK_directory_create_for_file (un->sun_path)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Cannot create path to `%s'\n"), + un->sun_path); + GNUNET_NETWORK_socket_close (unix_sock); + unix_sock = NULL; + GNUNET_free (un); + GNUNET_free (unix_socket_path); + return; + } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (unix_sock, + (const struct sockaddr *) un, + un_len)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "bind", + un->sun_path); + GNUNET_NETWORK_socket_close (unix_sock); + unix_sock = NULL; + GNUNET_free (un); + GNUNET_free (unix_socket_path); + return; + } + GNUNET_free (un); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Bound to `%s'\n", + unix_socket_path); + stats = GNUNET_STATISTICS_create ("C-UNIX", + cfg); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, + NULL); + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); + queue_map = GNUNET_CONTAINER_multipeermap_create (10, + GNUNET_NO); + ch = GNUNET_TRANSPORT_communicator_connect (cfg, + COMMUNICATOR_CONFIG_SECTION, + COMMUNICATOR_ADDRESS_PREFIX, + 65535, + &mq_init, + NULL); + if (NULL == ch) + { + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + GNUNET_free (unix_socket_path); + return; + } + GNUNET_asprintf (&my_addr, + "%s-%s", + COMMUNICATOR_ADDRESS_PREFIX, + unix_socket_path); + ai = GNUNET_TRANSPORT_communicator_address_add (ch, + my_addr, + GNUNET_ATS_NET_LOOPBACK, + GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_free (my_addr); + GNUNET_free (unix_socket_path); + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); +} + + +/** + * The main function for the UNIX communicator. + * + * @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) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + int ret; + + if (GNUNET_OK != + GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) + return 2; + + ret = + (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, + "gnunet-communicator-unix", + _("GNUnet UNIX domain socket communicator"), + options, + &run, + NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; +} + + +#if defined(LINUX) && defined(__GLIBC__) +#include <malloc.h> + +/** + * MINIMIZE heap size (way below 128k) since this process doesn't need much. + */ +void __attribute__ ((constructor)) +GNUNET_ARM_memory_init () +{ + mallopt (M_TRIM_THRESHOLD, 4 * 1024); + mallopt (M_TOP_PAD, 1 * 1024); + malloc_trim (0); +} +#endif + +/* end of gnunet-communicator-unix.c */ diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c new file mode 100644 index 000000000..8cbca3188 --- /dev/null +++ b/src/transport/gnunet-service-tng.c @@ -0,0 +1,719 @@ +/* + This file is part of GNUnet. + Copyright (C) 2010-2016, 2018 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/>. + */ +/** + * @file transport/gnunet-service-transport.c + * @brief main for gnunet-service-transport + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_statistics_service.h" +#include "gnunet_transport_service.h" +#include "gnunet_peerinfo_service.h" +#include "gnunet_ats_service.h" +#include "gnunet-service-transport.h" +#include "transport.h" + + +/** + * How many messages can we have pending for a given client process + * before we start to drop incoming messages? We typically should + * have only one client and so this would be the primary buffer for + * messages, so the number should be chosen rather generously. + * + * The expectation here is that most of the time the queue is large + * enough so that a drop is virtually never required. Note that + * this value must be about as large as 'TOTAL_MSGS' in the + * 'test_transport_api_reliability.c', otherwise that testcase may + * fail. + */ +#define MAX_PENDING (128 * 1024) + + +/** + * What type of client is the `struct TransportClient` about? + */ +enum ClientType +{ + /** + * We do not know yet (client is fresh). + */ + CT_NONE = 0, + + /** + * Is the CORE service, we need to forward traffic to it. + */ + CT_CORE = 1, + + /** + * It is a monitor, forward monitor data. + */ + CT_MONITOR = 2, + + /** + * It is a communicator, use for communication. + */ + CT_COMMUNICATOR = 3 +}; + + +/** + * Client connected to the transport service. + */ +struct TransportClient +{ + + /** + * Kept in a DLL. + */ + struct TransportClient *next; + + /** + * Kept in a DLL. + */ + struct TransportClient *prev; + + /** + * Handle to the client. + */ + struct GNUNET_SERVICE_Client *client; + + /** + * Message queue to the client. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * What type of client is this? + */ + enum ClientType type; + + union + { + + /** + * Peer identity to monitor the addresses of. + * Zero to monitor all neighbours. Valid if + * @e type is #CT_MONITOR. + */ + struct GNUNET_PeerIdentity monitor_peer; + + /** + * If @e type is #CT_COMMUNICATOR, this communicator + * supports communicating using these addresses. + */ + const char *address_prefix; + + } details; + +}; + + +/** + * Head of linked list of all clients to this service. + */ +static struct TransportClient *clients_head; + +/** + * Tail of linked list of all clients to this service. + */ +static struct TransportClient *clients_tail; + +/** + * Statistics handle. + */ +struct GNUNET_STATISTICS_Handle *GST_stats; + +/** + * Configuration handle. + */ +const struct GNUNET_CONFIGURATION_Handle *GST_cfg; + +/** + * Configuration handle. + */ +struct GNUNET_PeerIdentity GST_my_identity; + +/** + * Handle to peerinfo service. + */ +struct GNUNET_PEERINFO_Handle *GST_peerinfo; + +/** + * Our private key. + */ +struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; + + +/** + * Called whenever a client connects. Allocates our + * data structures associated with that client. + * + * @param cls closure, NULL + * @param client identification of the client + * @param mq message queue for the client + * @return our `struct TransportClient` + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + struct TransportClient *tc; + + tc = GNUNET_new (struct TransportClient); + tc->client = client; + tc->mq = mq; + GNUNET_CONTAINER_DLL_insert (clients_head, + clients_tail, + tc); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p connected\n", + tc); + return tc; +} + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure, NULL + * @param client identification of the client + * @param app_ctx our `struct TransportClient` + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + struct TransportClient *tc = app_ctx; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p disconnected, cleaning up.\n", + tc); + GNUNET_CONTAINER_DLL_remove (clients_head, + clients_tail, + tc); + switch (tc->type) + { + case CT_NONE: + break; + case CT_CORE: + break; + case CT_MONITOR: + break; + case CT_COMMUNICATOR: + break; + } + GNUNET_free (tc); +} + + +/** + * Initialize a "CORE" client. We got a start message from this + * client, so add it to the list of clients for broadcasting of + * inbound messages. + * + * @param cls the client + * @param start the start message that was sent + */ +static void +handle_client_start (void *cls, + const struct StartMessage *start) +{ + struct TransportClient *tc = cls; + const struct GNUNET_MessageHeader *hello; + uint32_t options; + + options = ntohl (start->options); + if ( (0 != (1 & options)) && + (0 != + memcmp (&start->self, + &GST_my_identity, + sizeof (struct GNUNET_PeerIdentity)) ) ) + { + /* client thinks this is a different peer, reject */ + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_CORE; +#if 0 + hello = GST_hello_get (); + if (NULL != hello) + unicast (tc, + hello, + GNUNET_NO); +#endif + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client sent us a HELLO. Check the request. + * + * @param cls the client + * @param message the HELLO message + */ +static int +check_client_hello (void *cls, + const struct GNUNET_MessageHeader *message) +{ + (void) cls; + return GNUNET_OK; /* FIXME: check here? */ +} + + +/** + * Client sent us a HELLO. Process the request. + * + * @param cls the client + * @param message the HELLO message + */ +static void +handle_client_hello (void *cls, + const struct GNUNET_MessageHeader *message) +{ + struct TransportClient *tc = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received HELLO message\n"); + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static int +check_client_send (void *cls, + const struct OutboundMessage *obm) +{ + uint16_t size; + const struct GNUNET_MessageHeader *obmm; + + (void) cls; + size = ntohs (obm->header.size) - sizeof (struct OutboundMessage); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; + if (size != ntohs (obmm->size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static void +handle_client_send (void *cls, + const struct OutboundMessage *obm) +{ + struct TransportClient *tc = cls; + const struct GNUNET_MessageHeader *obmm; + + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; +} + + +/** + * Communicator started. Test message is well-formed. + * + * @param cls the client + * @param cam the send message that was sent + */ +static int +check_communicator_available (void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (cam->header.size) - sizeof (*cam); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + addr = (const char *) &cam[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Communicator started. Process the request. + * + * @param cls the client + * @param cam the send message that was sent + */ +static void +handle_communicator_available (void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) +{ + struct TransportClient *tc = cls; + uint16_t size; + + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_COMMUNICATOR; + size = ntohs (cam->header.size) - sizeof (*cam); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]); + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Address of our peer added. Test message is well-formed. + * + * @param cls the client + * @param aam the send message that was sent + */ +static int +check_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *aam) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (aam->header.size) - sizeof (*aam); + if (0 == size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + addr = (const char *) &cam[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Address of our peer added. Process the request. + * + * @param cls the client + * @param aam the send message that was sent + */ +static void +handle_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *aam) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Address of our peer deleted. Process the request. + * + * @param cls the client + * @param dam the send message that was sent + */ +static void +handle_del_address (void *cls, + const struct GNUNET_TRANSPORT_DelAddressMessage *dam) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static int +check_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *im) +{ + uint16_t size; + const struct GNUNET_MessageHeader *obmm; + + (void) cls; + size = ntohs (im->header.size) - sizeof (*im); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + obmm = (const struct GNUNET_MessageHeader *) &im[1]; + if (size != ntohs (obmm->size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Incoming meessage. Process the request. + * + * @param cls the client + * @param im the send message that was received + */ +static void +handle_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *im) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * New queue became available. Check message. + * + * @param cls the client + * @param aqm the send message that was sent + */ +static int +check_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (aqm->header.size) - sizeof (*aqm); + if (0 == size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + addr = (const char *) &aqm[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * New queue became available. Process the request. + * + * @param cls the client + * @param aqm the send message that was sent + */ +static void +handle_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Queue to a peer went down. Process the request. + * + * @param cls the client + * @param dqm the send message that was sent + */ +static void +handle_del_queue_message (void *cls, + const struct GNUNET_TRANSPORT_DelQueueMessage *dqm) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Message was transmitted. Process the request. + * + * @param cls the client + * @param sma the send message that was sent + */ +static void +handle_send_message_ack (void *cls, + const struct GNUNET_TRANSPORT_SendMessageToAck *sma) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Function called when the service shuts down. Unloads our plugins + * and cancels pending validations. + * + * @param cls closure, unused + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + + if (NULL != GST_stats) + { + GNUNET_STATISTICS_destroy (GST_stats, + GNUNET_NO); + GST_stats = NULL; + } + if (NULL != GST_my_private_key) + { + GNUNET_free (GST_my_private_key); + GST_my_private_key = NULL; + } +} + + +/** + * Initiate transport service. + * + * @param cls closure + * @param c configuration to use + * @param service the initialized service + */ +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *service) +{ + /* setup globals */ + GST_cfg = c; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (c, + "transport", + "HELLO_EXPIRATION", + &hello_expiration)) + { + hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; + } + GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); + if (NULL == GST_my_private_key) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + _("Transport service is lacking key configuration settings. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key, + &GST_my_identity.public_key); + GNUNET_log(GNUNET_ERROR_TYPE_INFO, + "My identity is `%s'\n", + GNUNET_i2s_full (&GST_my_identity)); + + GST_stats = GNUNET_STATISTICS_create ("transport", + GST_cfg); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + /* start subsystems */ +} + + +/** + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("transport", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + /* communication with core */ + GNUNET_MQ_hd_fixed_size (client_start, + GNUNET_MESSAGE_TYPE_TRANSPORT_START, + struct StartMessage, + NULL), + GNUNET_MQ_hd_var_size (client_hello, + GNUNET_MESSAGE_TYPE_HELLO, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_var_size (client_send, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, + struct OutboundMessage, + NULL), + /* communication with communicators */ + GNUNET_MQ_hd_var_size (communicator_available, + GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, + struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, + NULL), + GNUNET_MQ_hd_var_size (add_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, + struct GNUNET_TRANSPORT_AddAddressMessage, + NULL), + GNUNET_MQ_hd_fixed_size (del_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, + struct GNUNET_TRANSPORT_DelAddressMessage, + NULL), + GNUNET_MQ_hd_var_size (incoming_msg, + GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, + struct GNUNET_TRANSPORT_IncomingMessage, + NULL), + GNUNET_MQ_hd_var_size (add_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, + struct GNUNET_TRANSPORT_AddQueueMessage, + NULL), + GNUNET_MQ_hd_fixed_size (del_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, + struct GNUNET_TRANSPORT_DelQueueMessage, + NULL), + GNUNET_MQ_hd_fixed_size (send_message_ack, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, + struct GNUNET_TRANSPORT_SendMessageToAck, + NULL), + GNUNET_MQ_handler_end ()); + + +/* end of file gnunet-service-transport.c */ diff --git a/src/transport/transport.h b/src/transport/transport.h index e68536bcc..1b46213cf 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -11,7 +11,7 @@ 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/>. */ @@ -94,7 +94,7 @@ struct StartMessage /** * 0: no options - * 1: The 'self' field should be checked + * 1: The @e self field should be checked * 2: this client is interested in payload traffic */ uint32_t options; @@ -404,6 +404,7 @@ struct ValidationIterateResponseMessage struct GNUNET_TIME_AbsoluteNBO next_validation; }; + /** * Message from the library to the transport service * asking for binary addresses known for a peer. @@ -654,6 +655,22 @@ struct TransportPluginMonitorMessage /* *********************** TNG messages ***************** */ /** + * Communicator goes online. Note which addresses it can + * work with. + */ +struct GNUNET_TRANSPORT_CommunicatorAvailableMessage +{ + + /** + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR. + */ + struct GNUNET_MessageHeader header; + + /* Followed by the address prefix of the communicator */ +}; + + +/** * Add address to the list. */ struct GNUNET_TRANSPORT_AddAddressMessage @@ -678,7 +695,7 @@ struct GNUNET_TRANSPORT_AddAddressMessage * An `enum GNUNET_ATS_Network_Type` in NBO. */ uint32_t nt; - + /* followed by UTF-8 encoded, 0-terminated human-readable address */ }; @@ -717,12 +734,12 @@ struct GNUNET_TRANSPORT_IncomingMessage * Do we use flow control or not? */ uint32_t fc_on GNUNET_PACKED; - + /** * 64-bit number to identify the matching ACK. */ uint64_t fc_id GNUNET_PACKED; - + /** * Sender identifier. */ @@ -748,12 +765,12 @@ struct GNUNET_TRANSPORT_IncomingMessageAck * Reserved (0) */ uint32_t reserved GNUNET_PACKED; - + /** * Which message is being ACKed? */ uint64_t fc_id GNUNET_PACKED; - + /** * Sender identifier of the original message. */ @@ -769,7 +786,7 @@ struct GNUNET_TRANSPORT_AddQueueMessage { /** - * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE. + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP. */ struct GNUNET_MessageHeader header; @@ -787,7 +804,7 @@ struct GNUNET_TRANSPORT_AddQueueMessage * An `enum GNUNET_ATS_Network_Type` in NBO. */ uint32_t nt; - + /* followed by UTF-8 encoded, 0-terminated human-readable address */ }; @@ -799,7 +816,7 @@ struct GNUNET_TRANSPORT_DelQueueMessage { /** - * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE. + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN. */ struct GNUNET_MessageHeader header; @@ -828,9 +845,9 @@ struct GNUNET_TRANSPORT_CreateQueue struct GNUNET_MessageHeader header; /** - * Always zero. + * Unique ID for the request. */ - uint32_t reserved GNUNET_PACKED; + uint32_t request_id GNUNET_PACKED; /** * Receiver that can be addressed via the queue. @@ -842,6 +859,24 @@ struct GNUNET_TRANSPORT_CreateQueue /** + * Transport tells communicator that it wants a new queue. + */ +struct GNUNET_TRANSPORT_CreateQueueResponse +{ + + /** + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK or #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL. + */ + struct GNUNET_MessageHeader header; + + /** + * Unique ID for the request. + */ + uint32_t request_id GNUNET_PACKED; +}; + + +/** * Inform communicator about transport's desire to send a message. */ struct GNUNET_TRANSPORT_SendMessageTo @@ -861,7 +896,7 @@ struct GNUNET_TRANSPORT_SendMessageTo * Message ID, used for flow control. */ uint64_t mid GNUNET_PACKED; - + /** * Receiver identifier. */ @@ -891,7 +926,7 @@ struct GNUNET_TRANSPORT_SendMessageToAck * Message ID of the original message. */ uint64_t mid GNUNET_PACKED; - + /** * Receiver identifier. */ diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c index d446516bd..3a68c6eba 100644 --- a/src/transport/transport_api2_communication.c +++ b/src/transport/transport_api2_communication.c @@ -90,6 +90,11 @@ struct AckPending struct AckPending *prev; /** + * Communicator this entry belongs to. + */ + struct GNUNET_TRANSPORT_CommunicatorHandle *ch; + + /** * Which peer is this about? */ struct GNUNET_PeerIdentity receiver; @@ -134,17 +139,17 @@ struct GNUNET_TRANSPORT_CommunicatorHandle /** * DLL of messages awaiting transmission confirmation (ack). */ - struct AckPending *ac_tail; + struct AckPending *ap_tail; /** * DLL of queues we offer. */ - struct QueueHandle *queue_head; + struct GNUNET_TRANSPORT_QueueHandle *queue_head; /** * DLL of queues we offer. */ - struct QueueHandle *queue_tail; + struct GNUNET_TRANSPORT_QueueHandle *queue_tail; /** * Our configuration. @@ -152,9 +157,14 @@ struct GNUNET_TRANSPORT_CommunicatorHandle const struct GNUNET_CONFIGURATION_Handle *cfg; /** - * Name of the communicator. + * Config section to use. + */ + const char *config_section; + + /** + * Address prefix to use. */ - const char *name; + const char *addr_prefix; /** * Function to call when the transport service wants us to initiate @@ -168,6 +178,11 @@ struct GNUNET_TRANSPORT_CommunicatorHandle void *mq_init_cls; /** + * Queue to talk to the transport service. + */ + struct GNUNET_MQ_Handle *mq; + + /** * Maximum permissable queue length. */ unsigned long long max_queue_length; @@ -202,6 +217,17 @@ struct GNUNET_TRANSPORT_CommunicatorHandle */ struct GNUNET_TRANSPORT_QueueHandle { + + /** + * Kept in a DLL. + */ + struct GNUNET_TRANSPORT_QueueHandle *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_TRANSPORT_QueueHandle *prev; + /** * Handle this queue belongs to. */ @@ -308,7 +334,7 @@ send_add_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai) env = GNUNET_MQ_msg_extra (aam, strlen (ai->address) + 1, GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS); - aam->expiration = GNUNET_TIME_relative_to_nbo (ai->expiration); + aam->expiration = GNUNET_TIME_relative_hton (ai->expiration); aam->nt = htonl ((uint32_t) ai->nt); memcpy (&aam[1], ai->address, @@ -334,7 +360,7 @@ send_del_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai) return; env = GNUNET_MQ_msg (dam, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS); - dam.aid = htonl (ai->aid); + dam->aid = htonl (ai->aid); GNUNET_MQ_send (ai->ch->mq, env); } @@ -352,18 +378,18 @@ send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh) struct GNUNET_MQ_Envelope *env; struct GNUNET_TRANSPORT_AddQueueMessage *aqm; - if (NULL == ai->ch->mq) + if (NULL == qh->ch->mq) return; env = GNUNET_MQ_msg_extra (aqm, - strlen (ai->address) + 1, - GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE); - aqm.receiver = qh->peer; - aqm.nt = htonl ((uint32_t) qh->nt); - aqm.qid = htonl (qh->qid); + strlen (qh->address) + 1, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP); + aqm->receiver = qh->peer; + aqm->nt = htonl ((uint32_t) qh->nt); + aqm->qid = htonl (qh->queue_id); memcpy (&aqm[1], - ai->address, - strlen (ai->address) + 1); - GNUNET_MQ_send (ai->ch->mq, + qh->address, + strlen (qh->address) + 1); + GNUNET_MQ_send (qh->ch->mq, env); } @@ -380,13 +406,13 @@ send_del_queue (struct GNUNET_TRANSPORT_QueueHandle *qh) struct GNUNET_MQ_Envelope *env; struct GNUNET_TRANSPORT_DelQueueMessage *dqm; - if (NULL == ai->ch->mq) + if (NULL == qh->ch->mq) return; env = GNUNET_MQ_msg (dqm, - GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE); - dqm.qid = htonl (qh->qid); - dqm.receiver = qh->peer; - GNUNET_MQ_send (ai->ch->mq, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN); + dqm->qid = htonl (qh->queue_id); + dqm->receiver = qh->peer; + GNUNET_MQ_send (qh->ch->mq, env); } @@ -444,7 +470,8 @@ error_handler (void *cls, struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "MQ failure, reconnecting to transport service.\n"); + "MQ failure %d, reconnecting to transport service.\n", + error); disconnect (ch); /* TODO: maybe do this with exponential backoff/delay */ reconnect (ch); @@ -460,7 +487,7 @@ error_handler (void *cls, */ static void handle_incoming_ack (void *cls, - struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack) + const struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack) { struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; @@ -470,7 +497,7 @@ handle_incoming_ack (void *cls, { if ( (fc->id == incoming_ack->fc_id) && (0 == memcmp (&fc->sender, - incoming_ack->sender, + &incoming_ack->sender, sizeof (struct GNUNET_PeerIdentity))) ) { GNUNET_CONTAINER_DLL_remove (ch->fc_head, @@ -499,11 +526,12 @@ handle_incoming_ack (void *cls, */ static int check_create_queue (void *cls, - struct GNUNET_TRANSPORT_CreateQueue *cq) + const struct GNUNET_TRANSPORT_CreateQueue *cq) { uint16_t len = ntohs (cq->header.size) - sizeof (*cq); const char *addr = (const char *) &cq[1]; + (void) cls; if ( (0 == len) || ('\0' != addr[len-1]) ) { @@ -522,11 +550,13 @@ check_create_queue (void *cls, */ static void handle_create_queue (void *cls, - struct GNUNET_TRANSPORT_CreateQueue *cq) + const struct GNUNET_TRANSPORT_CreateQueue *cq) { struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; const char *addr = (const char *) &cq[1]; - + struct GNUNET_TRANSPORT_CreateQueueResponse *cqr; + struct GNUNET_MQ_Envelope *env; + if (GNUNET_OK != ch->mq_init (ch->mq_init_cls, &cq->receiver, @@ -535,8 +565,17 @@ handle_create_queue (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address `%s' invalid for this communicator\n", addr); - // TODO: do we notify the transport!? + env = GNUNET_MQ_msg (cqr, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL); } + else + { + env = GNUNET_MQ_msg (cqr, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK); + } + cqr->request_id = cq->request_id; + GNUNET_MQ_send (ch->mq, + env); } @@ -550,11 +589,12 @@ handle_create_queue (void *cls, */ static int check_send_msg (void *cls, - struct GNUNET_TRANSPORT_SendMessageTo *smt) + const struct GNUNET_TRANSPORT_SendMessageTo *smt) { uint16_t len = ntohs (smt->header.size) - sizeof (*smt); const struct GNUNET_MessageHeader *mh = (const struct GNUNET_MessageHeader *) &smt[1]; + (void) cls; if (ntohs (mh->size) != len) { GNUNET_break (0); @@ -584,9 +624,9 @@ send_ack (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK); - ack->status = htonl (GNUNET_OK); - ack->mid = ap->mid; - ack->receiver = ap->receiver; + ack->status = htonl (status); + ack->mid = mid; + ack->receiver = *receiver; GNUNET_MQ_send (ch->mq, env); } @@ -623,18 +663,18 @@ send_ack_cb (void *cls) */ static void handle_send_msg (void *cls, - struct GNUNET_TRANSPORT_SendMessageTo *smt) + const struct GNUNET_TRANSPORT_SendMessageTo *smt) { struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; const struct GNUNET_MessageHeader *mh; struct GNUNET_MQ_Envelope *env; struct AckPending *ap; - struct QueueHandle *qh; + struct GNUNET_TRANSPORT_QueueHandle *qh; for (qh = ch->queue_head;NULL != qh; qh = qh->next) if ( (qh->queue_id == smt->qid) && (0 == memcmp (&qh->peer, - &smt->target, + &smt->receiver, sizeof (struct GNUNET_PeerIdentity))) ) break; if (NULL == qh) @@ -653,7 +693,7 @@ handle_send_msg (void *cls, ap->receiver = smt->receiver; ap->mid = smt->mid; GNUNET_CONTAINER_DLL_insert (ch->ap_head, - cp->ap_tail, + ch->ap_tail, ap); mh = (const struct GNUNET_MessageHeader *) &smt[1]; env = GNUNET_MQ_msg_copy (mh); @@ -679,7 +719,7 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) struct GNUNET_TRANSPORT_IncomingMessageAck, ch), GNUNET_MQ_hd_var_size (create_queue, - GNUNET_MESSAGE_TYPE_TRANSPORT_CREATE_QUEUE, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE, struct GNUNET_TRANSPORT_CreateQueue, ch), GNUNET_MQ_hd_var_size (send_msg, @@ -688,12 +728,24 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) ch), GNUNET_MQ_handler_end() }; + struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam; + struct GNUNET_MQ_Envelope *env; - ch->mq = GNUNET_CLIENT_connect (cfg, + ch->mq = GNUNET_CLIENT_connect (ch->cfg, "transport", handlers, &error_handler, ch); + if (NULL == ch->mq) + return; + env = GNUNET_MQ_msg_extra (cam, + strlen (ch->addr_prefix) + 1, + GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR); + memcpy (&cam[1], + ch->addr_prefix, + strlen (ch->addr_prefix) + 1); + GNUNET_MQ_send (ch->mq, + env); for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai; ai = ai->next) @@ -709,7 +761,9 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) * Connect to the transport service. * * @param cfg configuration to use - * @param name name of the communicator that is connecting + * @param config_section section of the configuration to use for options + * @param addr_prefix address prefix for addresses supported by this + * communicator, could be NULL for incoming-only communicators * @param mtu maximum message size supported by communicator, 0 if * sending is not supported, SIZE_MAX for no MTU * @param mq_init function to call to initialize a message queue given @@ -720,7 +774,8 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) */ struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *name, + const char *config_section, + const char *addr_prefix, size_t mtu, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls) @@ -729,14 +784,15 @@ GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle); ch->cfg = cfg; - ch->name = name; + ch->config_section = config_section; + ch->addr_prefix = addr_prefix; ch->mtu = mtu; ch->mq_init = mq_init; ch->mq_init_cls = mq_init_cls; reconnect (ch); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, - name, + config_section, "MAX_QUEUE_LENGTH", &ch->max_queue_length)) ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; @@ -798,32 +854,15 @@ GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandl struct GNUNET_TRANSPORT_IncomingMessage *im; uint16_t msize; - if (NULL == ai->ch->mq) + if (NULL == ch->mq) return GNUNET_SYSERR; - if (NULL != cb) + if ( (NULL == cb) && + (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) ) { - struct FlowControl *fc; - - im->fc_on = htonl (GNUNET_YES); - im->fc_id = ai->ch->fc_gen++; - fc = GNUNET_new (struct FlowControl); - fc->sender = *sender; - fc->id = im->fc_id; - fc->cb = cb; - fc->cb_cls = cb_cls; - GNUNET_CONTAINER_DLL_insert (ch->fc_head, - ch->fc_tail, - fc); - } - else - { - if (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Dropping message: transprot is too slow, queue length %u exceeded\n", - ch->max_queue_length); - return GNUNET_NO; - } + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Dropping message: transprot is too slow, queue length %llu exceeded\n", + ch->max_queue_length); + return GNUNET_NO; } msize = ntohs (msg->size); @@ -839,7 +878,22 @@ GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandl memcpy (&im[1], msg, msize); - GNUNET_MQ_send (ai->ch->mq, + if (NULL != cb) + { + struct FlowControl *fc; + + im->fc_on = htonl (GNUNET_YES); + im->fc_id = ch->fc_gen++; + fc = GNUNET_new (struct FlowControl); + fc->sender = *sender; + fc->id = im->fc_id; + fc->cb = cb; + fc->cb_cls = cb_cls; + GNUNET_CONTAINER_DLL_insert (ch->fc_head, + ch->fc_tail, + fc); + } + GNUNET_MQ_send (ch->mq, env); return GNUNET_OK; } @@ -927,9 +981,9 @@ GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorH ai->address = GNUNET_strdup (address); ai->nt = nt; ai->expiration = expiration; - ai->aid = handle->aid_gen++; - GNUNET_CONTAINER_DLL_insert (handle->ai_head, - handle->ai_tail, + ai->aid = ch->aid_gen++; + GNUNET_CONTAINER_DLL_insert (ch->ai_head, + ch->ai_tail, ai); send_add_address (ai); return ai; diff --git a/src/util/configuration.c b/src/util/configuration.c index 312e0acd3..197c664db 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -138,6 +138,41 @@ GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) /** + * Parse a configuration file @a filename and run the function + * @a cb with the resulting configuration object. Then free the + * configuration object and return the status value from @a cb. + * + * @param filename configuration to parse, NULL for "default" + * @param cb function to run + * @param cb_cls closure for @a cb + * @return #GNUNET_SYSERR if parsing the configuration failed, + * otherwise return value from @a cb. + */ +int +GNUNET_CONFIGURATION_parse_and_run (const char *filename, + GNUNET_CONFIGURATION_Callback cb, + void *cb_cls) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + int ret; + + cfg = GNUNET_CONFIGURATION_create (); + if (GNUNET_OK != + GNUNET_CONFIGURATION_load (cfg, + filename)) + { + GNUNET_break (0); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + ret = cb (cb_cls, + cfg); + GNUNET_CONFIGURATION_destroy (cfg); + return ret; +} + + +/** * De-serializes configuration * * @param cfg configuration to update diff --git a/src/util/disk.c b/src/util/disk.c index e0227be70..dc38d1137 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -2668,28 +2668,19 @@ GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh, /** - * Remove the directory given under @a option in - * section [PATHS] in configuration under @a cfg_filename + * Helper function for #GNUNET_DISK_purge_cfg_dir. * - * @param cfg_filename configuration file to parse - * @param option option with the dir name to purge + * @param cls a `const char *` with the option to purge + * @param cfg our configuration + * @return #GNUNET_OK on success */ -void -GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, - const char *option) +static int +purge_cfg_dir (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - struct GNUNET_CONFIGURATION_Handle *cfg; + const char *option = cls; char *tmpname; - - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_load (cfg, - cfg_filename)) - { - GNUNET_break (0); - GNUNET_CONFIGURATION_destroy (cfg); - return; - } + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", @@ -2699,10 +2690,8 @@ GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "PATHS", option); - GNUNET_CONFIGURATION_destroy (cfg); - return; + return GNUNET_NO; } - GNUNET_CONFIGURATION_destroy (cfg); if (GNUNET_SYSERR == GNUNET_DISK_directory_remove (tmpname)) { @@ -2710,11 +2699,29 @@ GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, "remove", tmpname); GNUNET_free (tmpname); - return; + return GNUNET_OK; } GNUNET_free (tmpname); + return GNUNET_OK; } +/** + * Remove the directory given under @a option in + * section [PATHS] in configuration under @a cfg_filename + * + * @param cfg_filename configuration file to parse + * @param option option with the dir name to purge + */ +void +GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, + const char *option) +{ + GNUNET_break (GNUNET_OK == + GNUNET_CONFIGURATION_parse_and_run (cfg_filename, + &purge_cfg_dir, + (void *) option)); +} + /* end of disk.c */ diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c index d907bd8d9..3b871ce33 100644 --- a/src/util/gnunet-service-resolver.c +++ b/src/util/gnunet-service-resolver.c @@ -364,7 +364,7 @@ lookup_dns_servers (char ***server_addrs) GNUNET_DISK_file_close (fh); return -1; } - if (bytes_read > SIZE_MAX) + if ((size_t) bytes_read > SIZE_MAX) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "/etc/resolv.conf file too large to mmap. " @@ -379,7 +379,7 @@ lookup_dns_servers (char ***server_addrs) *server_addrs = NULL; read_offset = 0; num_dns_servers = 0; - while (read_offset < bytes_read) + while (read_offset < (size_t) bytes_read) { const char *newline; size_t line_len; @@ -648,11 +648,16 @@ try_cache (const char *hostname, struct ResolveCache *pos; struct ResolveCache *next; int found; + int in_hosts; + in_hosts = GNUNET_NO; for (pos = hosts_head; NULL != pos; pos = pos->next) if (0 == strcmp (pos->hostname, hostname)) + { + in_hosts = GNUNET_YES; break; + } if (NULL == pos) { next = cache_head; @@ -673,7 +678,8 @@ try_cache (const char *hostname, hostname); return GNUNET_NO; } - if (cache_head != pos) + if ( (GNUNET_NO == in_hosts) && + (cache_head != pos) ) { /* move result to head to achieve LRU for cache eviction */ GNUNET_CONTAINER_DLL_remove (cache_head, @@ -1313,7 +1319,7 @@ extract_hosts (const char *line, if (NULL != c) line_len = c - line; /* ignore leading whitespace */ - while ( (0 > line_len) && + while ( (0 < line_len) && isspace ((unsigned char) *line) ) { line++; @@ -1382,7 +1388,7 @@ load_etc_hosts (void) GNUNET_DISK_file_close (fh); return; } - if (bytes_read > SIZE_MAX) + if ((size_t) bytes_read > SIZE_MAX) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "/etc/hosts file too large to mmap. " @@ -1395,7 +1401,7 @@ load_etc_hosts (void) GNUNET_DISK_MAP_TYPE_READ, (size_t) bytes_read); read_offset = 0; - while (read_offset < bytes_read) + while (read_offset < (size_t) bytes_read) { const char *newline; size_t line_len; diff --git a/src/util/service.c b/src/util/service.c index ea34abc6c..b61168570 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -1815,8 +1815,9 @@ GNUNET_SERVICE_run_ (int argc, opt_cfg_filename = GNUNET_strdup (cfg_filename); if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename)) { - if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, - opt_cfg_filename)) + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_load (cfg, + opt_cfg_filename)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration file `%s', exit ...\n"), @@ -1826,8 +1827,9 @@ GNUNET_SERVICE_run_ (int argc, } else { - if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, - NULL)) + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_load (cfg, + NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration, exit ...\n")); |