123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- /*
- This file is part of GNUnet.
- (C) 2012,2013 Christian Grothoff (and other contributing authors)
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, 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
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
- /**
- * @file experimentation/gnunet-daemon-experimentation_experiments.c
- * @brief experimentation daemon: experiment management
- * @author Christian Grothoff
- * @author Matthias Wachs
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "gnunet_core_service.h"
- #include "gnunet_statistics_service.h"
- #include "gnunet-daemon-experimentation.h"
- /**
- * Hashmap containing valid experiment issuers.
- */
- struct GNUNET_CONTAINER_MultiHashMap *valid_issuers;
- /**
- * Hashmap containing valid experiments
- */
- static struct GNUNET_CONTAINER_MultiHashMap *experiments;
- /**
- * Verify experiment signature
- *
- * @param i issuer
- * @param e experiment
- * @return #GNUNET_OK or #GNUNET_SYSERR
- */
- static int
- experiment_verify (struct Issuer *i, struct Experiment *e)
- {
- GNUNET_assert (NULL != i);
- GNUNET_assert (NULL != e);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Verification: to be implemented\n");
- return GNUNET_OK;
- }
- static int
- free_experiment (void *cls,
- const struct GNUNET_HashCode * key,
- void *value)
- {
- struct Experiment *e = value;
- GNUNET_break (0 == GNUNET_CONTAINER_multihashmap_remove (experiments, key, value));
- GNUNET_free_non_null (e->description);
- GNUNET_free_non_null (e->name);
- GNUNET_free (e);
- return GNUNET_OK;
- }
- /**
- * Free issuer element
- *
- * @param cls unused
- * @param key the key
- * @param value the issuer element to free
- * @return GNUNET_OK to continue
- */
- static int
- free_issuer (void *cls,
- const struct GNUNET_HashCode * key,
- void *value)
- {
- struct Issuer *i = value;
- GNUNET_break (0 == GNUNET_CONTAINER_multihashmap_remove (valid_issuers,
- key,
- i));
- GNUNET_free (i);
- return GNUNET_OK;
- }
- /**
- * Is peer a valid issuer
- *
- * @return #GNUNET_YES or #GNUNET_NO
- */
- int
- GED_experiments_issuer_accepted (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id)
- {
- struct GNUNET_HashCode hash;
- GNUNET_CRYPTO_hash (issuer_id, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), &hash);
- if (GNUNET_CONTAINER_multihashmap_contains (valid_issuers, &hash))
- return GNUNET_YES;
- return GNUNET_NO;
- }
- /**
- * Get the key under which the given experiment is stored in the
- * experiment map.
- */
- static void
- get_experiment_key (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
- const char *name,
- const struct GNUNET_TIME_Absolute version,
- struct GNUNET_HashCode *key)
- {
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_HashCode),
- issuer, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
- name, strlen (name),
- &version, sizeof (version),
- NULL, 0));
- }
- /**
- * Find an experiment based on issuer name and version
- *
- * @param issuer the issuer
- * @param name experiment name
- * @param version experiment version
- * @return the experiment or NULL if not found
- */
- struct Experiment *
- GED_experiments_find (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
- const char *name,
- const struct GNUNET_TIME_Absolute version)
- {
- struct GNUNET_HashCode hc;
- get_experiment_key (issuer,
- name,
- version,
- &hc);
- return GNUNET_CONTAINER_multihashmap_get (experiments,
- &hc);
- }
- struct GetCtx
- {
- struct Node *n;
- GNUNET_EXPERIMENTATION_experiments_get_cb get_cb;
- struct GNUNET_CRYPTO_EddsaPublicKey *issuer;
- };
- static int
- get_it (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
- {
- struct GetCtx *get_ctx = cls;
- struct Experiment *e = value;
- if (0 == memcmp (&e->issuer,
- get_ctx->issuer,
- sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
- get_ctx->get_cb (get_ctx->n, e);
- return GNUNET_OK;
- }
- void
- GED_experiments_get (struct Node *n,
- struct GNUNET_CRYPTO_EddsaPublicKey *issuer,
- GNUNET_EXPERIMENTATION_experiments_get_cb get_cb)
- {
- struct GetCtx get_ctx;
- GNUNET_assert (NULL != n);
- GNUNET_assert (NULL != experiments);
- GNUNET_assert (NULL != get_cb);
- get_ctx.n = n;
- get_ctx.get_cb = get_cb;
- get_ctx.issuer = issuer;
- GNUNET_CONTAINER_multihashmap_iterate (experiments,
- &get_it, &get_ctx);
- get_cb (n, NULL); // FIXME: ugly, end is easily signalled as we return: synchronous API!
- }
- /**
- * Add a new experiment
- */
- int
- GNUNET_EXPERIMENTATION_experiments_add (struct Issuer *i,
- const char *name,
- const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id,
- struct GNUNET_TIME_Absolute version,
- char *description,
- uint32_t required_capabilities,
- struct GNUNET_TIME_Absolute start,
- struct GNUNET_TIME_Relative frequency,
- struct GNUNET_TIME_Relative duration,
- struct GNUNET_TIME_Absolute stop)
- {
- struct Experiment *e;
- struct GNUNET_HashCode hc;
- e = GNUNET_new (struct Experiment);
- e->name = GNUNET_strdup (name);
- e->issuer = *issuer_id;
- e->version = version;
- if (NULL != description)
- e->description = GNUNET_strdup (description);
- e->required_capabilities = required_capabilities;
- e->start = start;
- e->frequency = frequency;
- e->duration = duration;
- e->stop = stop;
- /* verify experiment */
- if (GNUNET_SYSERR == experiment_verify (i, e))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Experiment signature is invalid\n"),
- name);
- GNUNET_free (e);
- GNUNET_free_non_null (e->name);
- GNUNET_free_non_null (e->description);
- return GNUNET_SYSERR;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu sec. \n"),
- e->name,
- GNUNET_STRINGS_absolute_time_to_string (start),
- GNUNET_STRINGS_absolute_time_to_string (stop),
- (long long unsigned int) frequency.rel_value_us / 1000000LL,
- (long long unsigned int) duration.rel_value_us / 1000000LL);
- get_experiment_key (&e->issuer,
- name,
- version,
- &hc);
- GNUNET_CONTAINER_multihashmap_put (experiments,
- &hc,
- e,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- GNUNET_STATISTICS_set (GED_stats,
- "# experiments",
- GNUNET_CONTAINER_multihashmap_size (experiments), GNUNET_NO);
- return GNUNET_OK;
- }
- /**
- * Parse a configuration section containing experiments
- *
- * @param cls configuration handle
- * @param name section name
- */
- static void
- exp_file_iterator (void *cls,
- const char *name)
- {
- struct GNUNET_CONFIGURATION_Handle *exp = cls;
- struct Issuer *i;
- char *val;
- unsigned long long number;
- /* Experiment values */
- struct GNUNET_CRYPTO_EddsaPublicKey issuer;
- struct GNUNET_TIME_Absolute version;
- char *description;
- uint32_t required_capabilities;
- struct GNUNET_TIME_Absolute start ;
- struct GNUNET_TIME_Absolute stop;
- struct GNUNET_TIME_Relative frequency;
- struct GNUNET_TIME_Relative duration;
- struct GNUNET_HashCode phash;
- /* Mandatory fields */
- /* Issuer */
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (exp, name, "ISSUER", &val))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Issuer missing\n"), name);
- return;
- }
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_public_key_from_string (val,
- strlen (val),
- &issuer))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Issuer invalid\n"), name);
- GNUNET_free (val);
- return;
- }
- GNUNET_CRYPTO_hash (&issuer, sizeof (issuer), &phash);
- if (NULL == (i = GNUNET_CONTAINER_multihashmap_get (valid_issuers, &phash)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Issuer not accepted!\n"), name);
- GNUNET_free (val);
- return;
- }
- GNUNET_free (val);
- /* Version */
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "VERSION", &number))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Version missing or invalid \n"), name);
- return;
- }
- version.abs_value_us = number; // FIXME: what is this supposed to be? Version != TIME!???
- /* Required capabilities */
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "CAPABILITIES", &number))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Required capabilities missing \n"), name);
- return;
- }
- if (number > UINT32_MAX)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Experiment `%s': Required capabilities invalid \n"), name);
- return;
- }
- required_capabilities = number;
- /* Optional fields */
- /* Description */
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (exp, name, "DESCRIPTION", &description))
- description = NULL;
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "START", (long long unsigned int *) &start.abs_value_us))
- start = GNUNET_TIME_UNIT_ZERO_ABS;
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (exp, name, "FREQUENCY", &frequency))
- frequency = EXP_DEFAULT_EXP_FREQ;
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (exp, name, "DURATION", &duration))
- duration = EXP_DEFAULT_EXP_DUR;
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "STOP", (long long unsigned int *)&stop.abs_value_us))
- stop = GNUNET_TIME_UNIT_FOREVER_ABS;
- GNUNET_EXPERIMENTATION_experiments_add (i, name, &issuer, version,
- description, required_capabilities,
- start, frequency, duration, stop);
- GNUNET_free_non_null (description);
- }
- /**
- * Load experiments from file
- *
- * @param file source file
- */
- static void
- load_file (const char * file)
- {
- struct GNUNET_CONFIGURATION_Handle *exp = GNUNET_CONFIGURATION_create();
- if (NULL == exp)
- return;
- if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (exp, file))
- {
- GNUNET_CONFIGURATION_destroy (exp);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to parse file `%s'\n"),
- file);
- return;
- }
- GNUNET_CONFIGURATION_iterate_sections (exp, &exp_file_iterator, exp);
- GNUNET_CONFIGURATION_destroy (exp);
- }
- /**
- * Start experiments management
- */
- int
- GED_experiments_start ()
- {
- struct Issuer *i;
- char *issuers;
- char *file;
- char *pos;
- struct GNUNET_CRYPTO_EddsaPublicKey issuer_ID;
- struct GNUNET_HashCode hash;
- /* Load valid issuer */
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_string (GED_cfg,
- "EXPERIMENTATION",
- "ISSUERS",
- &issuers))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("No valid experiment issuers configured! Set value to public keys of issuers! Exiting.\n"));
- GED_experiments_stop ();
- return GNUNET_SYSERR;
- }
- valid_issuers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
- for (pos = strtok (issuers, " "); pos != NULL; pos = strtok (NULL, " "))
- {
- if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_public_key_from_string (pos,
- strlen (pos),
- &issuer_ID))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "EXPERIMENTATION",
- "ISSUERS",
- _("Invalid value for public key\n"));
- GED_experiments_stop ();
- GNUNET_free (issuers);
- return GNUNET_SYSERR;
- }
- i = GNUNET_new (struct Issuer);
- i->pubkey = issuer_ID;
- GNUNET_CRYPTO_hash( &issuer_ID, sizeof (issuer_ID), &hash);
- GNUNET_CONTAINER_multihashmap_put (valid_issuers,
- &hash,
- i,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
- }
- GNUNET_free (issuers);
- if (0 == GNUNET_CONTAINER_multihashmap_size (valid_issuers))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("No valid experiment issuers configured! Set value to public keys of issuers! Exiting.\n"));
- GED_experiments_stop ();
- return GNUNET_SYSERR;
- }
- GNUNET_STATISTICS_set (GED_stats,
- "# issuer",
- GNUNET_CONTAINER_multihashmap_size (valid_issuers),
- GNUNET_NO);
- experiments = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
- /* Load experiments from file */
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_string (GED_cfg,
- "EXPERIMENTATION",
- "EXPERIMENTS",
- &file))
- return GNUNET_OK;
- if (GNUNET_YES != GNUNET_DISK_file_test (file))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Cannot read experiments file `%s'\n"), file);
- GNUNET_free (file);
- return GNUNET_OK;
- }
- load_file (file);
- GNUNET_free (file);
- return GNUNET_OK;
- }
- /**
- * Stop experiments management
- */
- void
- GED_experiments_stop ()
- {
- if (NULL != valid_issuers)
- {
- GNUNET_CONTAINER_multihashmap_iterate (valid_issuers, &free_issuer, NULL);
- GNUNET_CONTAINER_multihashmap_destroy (valid_issuers);
- }
- valid_issuers = NULL;
- if (NULL != experiments)
- {
- GNUNET_CONTAINER_multihashmap_iterate (experiments, &free_experiment, NULL);
- GNUNET_CONTAINER_multihashmap_destroy (experiments);
- }
- experiments = NULL;
- }
- /* end of gnunet-daemon-experimentation_experiments.c */
|