123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2012, 2013 Christian Grothoff
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file regex/gnunet-daemon-regexprofiler.c
- * @brief daemon that uses cadet to announce a regular expression. Used in
- * conjunction with gnunet-regex-profiler to announce regexes on several peers
- * without the need to explicitly connect to the cadet service running on the
- * peer from within the profiler.
- * @author Maximilian Szengel
- * @author Bartlomiej Polot
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "regex_internal_lib.h"
- #include "regex_test_lib.h"
- #include "gnunet_dht_service.h"
- #include "gnunet_statistics_service.h"
- /**
- * Return value from 'main'.
- */
- static int global_ret;
- /**
- * Configuration we use.
- */
- static const struct GNUNET_CONFIGURATION_Handle *cfg;
- /**
- * Handle to the statistics service.
- */
- static struct GNUNET_STATISTICS_Handle *stats_handle;
- /**
- * Peer's dht handle.
- */
- static struct GNUNET_DHT_Handle *dht_handle;
- /**
- * Peer's regex announce handle.
- */
- static struct REGEX_INTERNAL_Announcement *announce_handle;
- /**
- * Periodically reannounce regex.
- */
- static struct GNUNET_SCHEDULER_Task *reannounce_task;
- /**
- * What's the maximum reannounce period.
- */
- static struct GNUNET_TIME_Relative reannounce_period_max;
- /**
- * Maximal path compression length for regex announcing.
- */
- static unsigned long long max_path_compression;
- /**
- * Name of the file containing policies that this peer should announce. One
- * policy per line.
- */
- static char *policy_filename;
- /**
- * Prefix to add before every regex we're announcing.
- */
- static char *regex_prefix;
- /**
- * Regex with prefix.
- */
- static char *rx_with_pfx;
- /**
- * How many put rounds should we do.
- */
- static unsigned int rounds = 3;
- /**
- * Private key for this peer.
- */
- static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
- /**
- * Task run during shutdown.
- *
- * @param cls unused
- */
- static void
- shutdown_task (void *cls)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
- if (NULL != announce_handle)
- {
- REGEX_INTERNAL_announce_cancel (announce_handle);
- announce_handle = NULL;
- }
- if (NULL != reannounce_task)
- {
- GNUNET_free_nz (GNUNET_SCHEDULER_cancel (reannounce_task));
- reannounce_task = NULL;
- }
- if (NULL != dht_handle)
- {
- GNUNET_DHT_disconnect (dht_handle);
- dht_handle = NULL;
- }
- GNUNET_free (my_private_key);
- my_private_key = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Daemon for %s shutting down\n",
- policy_filename);
- }
- /**
- * Announce a previously announced regex re-using cached data.
- *
- * @param cls Closure (regex to announce if needed).
- */
- static void
- reannounce_regex (void *cls)
- {
- char *regex = cls;
- struct GNUNET_TIME_Relative random_delay;
- reannounce_task = NULL;
- if (0 == rounds--)
- {
- global_ret = 0;
- GNUNET_SCHEDULER_shutdown ();
- GNUNET_free (regex);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Announcing regex: %s\n", regex);
- GNUNET_STATISTICS_update (stats_handle, "# regexes announced", 1, GNUNET_NO);
- if ((NULL == announce_handle) && (NULL != regex))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "First time, creating regex: %s\n",
- regex);
- announce_handle = REGEX_INTERNAL_announce (dht_handle,
- my_private_key,
- regex,
- (unsigned
- int) max_path_compression,
- stats_handle);
- }
- else
- {
- GNUNET_assert (NULL != announce_handle);
- REGEX_INTERNAL_reannounce (announce_handle);
- }
- random_delay =
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS,
- GNUNET_CRYPTO_random_u32 (
- GNUNET_CRYPTO_QUALITY_WEAK,
- reannounce_period_max.rel_value_us));
- reannounce_task = GNUNET_SCHEDULER_add_delayed (random_delay,
- &reannounce_regex, cls);
- }
- /**
- * Announce the given regular expression using regex and the path compression
- * length read from config.
- *
- * @param regex regular expression to announce on this peer's cadet.
- */
- static void
- announce_regex (const char *regex)
- {
- char *copy;
- if ((NULL == regex) || (0 == strlen (regex)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot announce empty regex\n");
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Daemon for %s starting\n",
- policy_filename);
- GNUNET_assert (NULL == reannounce_task);
- copy = GNUNET_strdup (regex);
- reannounce_task = GNUNET_SCHEDULER_add_now (&reannounce_regex,
- (void *) copy);
- }
- /**
- * Scan through the policy_dir looking for the n-th filename.
- *
- * @param cls Closure (target number n).
- * @param filename complete filename (absolute path).
- * @return GNUNET_OK to continue to iterate,
- * GNUNET_NO to stop when found
- */
- static int
- scan (void *cls, const char *filename)
- {
- long n = (long) cls;
- static long c = 0;
- if (c == n)
- {
- policy_filename = GNUNET_strdup (filename);
- return GNUNET_NO;
- }
- c++;
- return GNUNET_OK;
- }
- /**
- * @brief Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @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 GNUNET_UNUSED,
- const char *cfgfile GNUNET_UNUSED,
- const struct GNUNET_CONFIGURATION_Handle *cfg_)
- {
- char *regex = NULL;
- char **components;
- char *policy_dir;
- long long unsigned int peer_id;
- cfg = cfg_;
- my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
- GNUNET_assert (NULL != my_private_key);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER",
- "MAX_PATH_COMPRESSION",
- &max_path_compression))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _
- (
- "%s service is lacking key configuration settings (%s). Exiting.\n"),
- "regexprofiler", "max_path_compression");
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER",
- "POLICY_DIR", &policy_dir))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REGEXPROFILER",
- "POLICY_DIR");
- global_ret = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
- "PEERID", &peer_id))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "TESTBED", "PEERID");
- global_ret = GNUNET_SYSERR;
- GNUNET_free (policy_dir);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER",
- "REGEX_PREFIX", ®ex_prefix))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REGEXPROFILER",
- "REGEX_PREFIX");
- global_ret = GNUNET_SYSERR;
- GNUNET_free (policy_dir);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER",
- "REANNOUNCE_PERIOD_MAX",
- &reannounce_period_max))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "reannounce_period_max not given. Using 10 minutes.\n");
- reannounce_period_max =
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10);
- }
- stats_handle = GNUNET_STATISTICS_create ("regexprofiler", cfg);
- dht_handle = GNUNET_DHT_connect (cfg, 1);
- if (NULL == dht_handle)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not acquire dht handle. Exiting.\n");
- global_ret = GNUNET_SYSERR;
- GNUNET_free (policy_dir);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- /* Read regexes from policy files */
- GNUNET_assert (-1 != GNUNET_DISK_directory_scan (policy_dir, &scan,
- (void *) (long) peer_id));
- if (NULL == (components = REGEX_TEST_read_from_file (policy_filename)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Policy file %s contains no policies. Exiting.\n",
- policy_filename);
- global_ret = GNUNET_SYSERR;
- GNUNET_free (policy_dir);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- GNUNET_free (policy_dir);
- regex = REGEX_TEST_combine (components, 16);
- REGEX_TEST_free_from_file (components);
- /* Announcing regexes from policy_filename */
- GNUNET_asprintf (&rx_with_pfx,
- "%s(%s)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*",
- regex_prefix,
- regex);
- announce_regex (rx_with_pfx);
- GNUNET_free (regex);
- GNUNET_free (rx_with_pfx);
- /* Scheduled the task to clean up when shutdown is called */
- GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
- NULL);
- }
- /**
- * The main function of the regexprofiler service.
- *
- * @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
- };
- if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
- return 2;
- return (GNUNET_OK ==
- GNUNET_PROGRAM_run (argc, argv, "regexprofiler",
- gettext_noop
- (
- "Daemon to announce regular expressions for the peer using cadet."),
- options, &run, NULL)) ? global_ret : 1;
- }
- #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-daemon-regexprofiler.c */
|