/** * Store content in DHT. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void process_dht_put_content (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct PutOperator *po = cls; po->dht_qe = NULL; if (key == NULL) { po->zero_anonymity_count_estimate = po->current_offset - 1; po->current_offset = 0; po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po); return; } po->zero_anonymity_count_estimate = GNUNET_MAX (po->current_offset, po->zero_anonymity_count_estimate); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Retrieved block `%s' of type %u for DHT PUT\n", GNUNET_h2s (key), type); po->dht_put = GNUNET_DHT_put (GSF_dht, key, DEFAULT_PUT_REPLICATION, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, type, size, data, expiration, GNUNET_TIME_UNIT_FOREVER_REL, &delay_dht_put_blocks, po); }
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_HashCode hash; char *data; size_t data_size = 42; GNUNET_assert (ok == 1); OKPP; die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &end_badly, NULL); memset (&hash, 42, sizeof (struct GNUNET_HashCode)); data = GNUNET_malloc (data_size); memset (data, 43, data_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_put!\n"); dht_handle = GNUNET_DHT_connect (cfg, 100); GNUNET_assert (dht_handle != NULL); GNUNET_DHT_put (dht_handle, &hash, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST, data_size, data, GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT), &test_get, NULL); GNUNET_free (data); }
/** * Periodically announce self id in the DHT * * @param cls closure * @param tc task context */ static void announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_HashCode phash; const struct GNUNET_HELLO_Message *hello; size_t size; struct GNUNET_TIME_Absolute expiration; struct GNUNET_TIME_Relative retry_time; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { announce_id_task = NULL; return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n"); /* TODO * - Set data expiration in function of X * - Adapt X to churn */ hello = GCH_get_mine (); if (NULL == hello || (size = GNUNET_HELLO_size (hello)) == 0) { /* Peerinfo gave us no hello yet, try again in a second. */ announce_id_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &announce_id, cls); LOG (GNUNET_ERROR_TYPE_DEBUG, " no hello, waiting!\n"); GNUNET_STATISTICS_update (stats, "# DHT announce skipped (no hello)", 1, GNUNET_NO); return; } expiration = GNUNET_HELLO_get_last_expiration (hello); retry_time = GNUNET_TIME_absolute_get_remaining (expiration); LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size); GNUNET_STATISTICS_update (stats, "# DHT announce", 1, GNUNET_NO); memset (&phash, 0, sizeof (phash)); memcpy (&phash, &my_full_id, sizeof (my_full_id)); GNUNET_DHT_put (dht_handle, /* DHT handle */ &phash, /* Key to use */ dht_replication_level, /* Replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ size, /* Size of the data */ (const char *) hello, /* Data itself */ expiration, /* Data expiration */ retry_time, /* Retry time */ NULL, /* Continuation */ NULL); /* Continuation closure */ announce_id_task = GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls); }
/** * 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 c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_TIME_Relative timeout; struct GNUNET_TIME_Absolute expiration; GNUNET_HashCode key; cfg = c; if ((query_key == NULL) || (data == NULL)) { FPRINTF (stderr, "%s", _("Must provide KEY and DATA for DHT put!\n")); ret = 1; return; } dht_handle = GNUNET_DHT_connect (cfg, 1); if (dht_handle == NULL) { FPRINTF (stderr, _("Could not connect to %s service!\n"), "DHT"); ret = 1; return; } else if (verbose) FPRINTF (stderr, _("Connected to %s service!\n"), "DHT"); if (query_type == GNUNET_BLOCK_TYPE_ANY) /* Type of data not set */ query_type = GNUNET_BLOCK_TYPE_TEST; GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key); timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, timeout_request); expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, expiration_seconds)); if (verbose) FPRINTF (stderr, _("Issuing put request for `%s' with data `%s'!\n"), query_key, data); GNUNET_DHT_put (dht_handle, &key, replication, GNUNET_DHT_RO_NONE, query_type, strlen (data), data, expiration, timeout, &message_sent_cont, NULL); }
/** * Function used to put all records successively into the DHT. * * @param cls the closure (NULL) * @param key the public key of the authority (ours) * @param expiration lifetime of the namestore entry * @param name the name of the records * @param rd_count the number of records in data * @param rd the record data * @param signature the signature for the record data */ static void put_gns_record(void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, struct GNUNET_TIME_Absolute expiration, const char *name, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { struct GNSNameRecordBlock *nrb; struct GNUNET_CRYPTO_ShortHashCode name_hash; struct GNUNET_CRYPTO_ShortHashCode zhash; GNUNET_HashCode xor_hash; GNUNET_HashCode name_hash_double; GNUNET_HashCode zone_hash_double; uint32_t rd_payload_length; char* nrb_data = NULL; size_t namelen; /* we're done */ if (NULL == name) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Zone iteration finished. Rescheduling put in %ds\n", dht_max_update_interval); zone_update_taskid = GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_multiply( GNUNET_TIME_UNIT_SECONDS, dht_max_update_interval ), &update_zone_dht_start, NULL); return; } namelen = strlen(name) + 1; if (signature == NULL) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No signature for %s record data provided! Skipping...\n", name); zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_next, NULL); return; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Putting records for %s into the DHT\n", name); rd_payload_length = GNUNET_NAMESTORE_records_get_size (rd_count, rd); nrb = GNUNET_malloc(rd_payload_length + namelen + sizeof(struct GNSNameRecordBlock)); nrb->signature = *signature; nrb->public_key = *key; nrb->rd_count = htonl(rd_count); memcpy(&nrb[1], name, namelen); nrb_data = (char*)&nrb[1]; nrb_data += namelen; rd_payload_length += sizeof(struct GNSNameRecordBlock) + namelen; if (-1 == GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_payload_length, nrb_data)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed! Skipping...\n"); GNUNET_free(nrb); zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_next, NULL); return; } /* * calculate DHT key: H(name) xor H(pubkey) */ GNUNET_CRYPTO_short_hash(key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zhash); GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash); GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double); GNUNET_CRYPTO_short_hash_double (&zhash, &zone_hash_double); GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "zone identity: %s\n", GNUNET_h2s (&zone_hash_double)); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "putting records for %s under key: %s with size %d\n", name, GNUNET_h2s (&xor_hash), rd_payload_length); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT req to %d\n", DHT_OPERATION_TIMEOUT.rel_value); /* FIXME: keep return value to possibly cancel? */ GNUNET_DHT_put (dht_handle, &xor_hash, DHT_GNS_REPLICATION_LEVEL, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, rd_payload_length, (char*)nrb, expiration, DHT_OPERATION_TIMEOUT, &record_dht_put, NULL); //cls for cont num_public_records++; /** * Reschedule periodic put */ zone_update_taskid = GNUNET_SCHEDULER_add_delayed (record_put_interval, &update_zone_dht_next, NULL); GNUNET_free(nrb); }
/** * Regex callback iterator to store own service description in the DHT. * * @param cls closure. * @param key hash for current state. * @param proof proof for current state. * @param accepting #GNUNET_YES if this is an accepting state, #GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ static void regex_iterator (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { struct REGEX_INTERNAL_Announcement *h = cls; struct RegexBlock *block; size_t size; unsigned int i; LOG (GNUNET_ERROR_TYPE_INFO, "DHT PUT for state %s with proof `%s' and %u edges:\n", GNUNET_h2s (key), proof, num_edges); for (i = 0; i < num_edges; i++) { LOG (GNUNET_ERROR_TYPE_INFO, "Edge %u `%s' towards %s\n", i, edges[i].label, GNUNET_h2s (&edges[i].destination)); } if (GNUNET_YES == accepting) { struct RegexAcceptBlock ab; LOG (GNUNET_ERROR_TYPE_INFO, "State %s is accepting, putting own id\n", GNUNET_h2s (key)); size = sizeof (struct RegexAcceptBlock); ab.purpose.size = ntohl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_HashCode)); ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT); ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION)); ab.key = *key; GNUNET_CRYPTO_eddsa_key_get_public (h->priv, &ab.peer.public_key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (h->priv, &ab.purpose, &ab.signature)); GNUNET_STATISTICS_update (h->stats, "# regex accepting blocks stored", 1, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, "# regex accepting block bytes stored", sizeof (struct RegexAcceptBlock), GNUNET_NO); (void) GNUNET_DHT_put (h->dht, key, DHT_REPLICATION, DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_BLOCK_TYPE_REGEX_ACCEPT, size, &ab, GNUNET_TIME_relative_to_absolute (DHT_TTL), NULL, NULL); } block = REGEX_BLOCK_create (proof, num_edges, edges, accepting, &size); (void) GNUNET_DHT_put (h->dht, key, DHT_REPLICATION, DHT_OPT, GNUNET_BLOCK_TYPE_REGEX, size, block, GNUNET_TIME_relative_to_absolute (DHT_TTL), NULL, NULL); GNUNET_STATISTICS_update (h->stats, "# regex blocks stored", 1, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, "# regex block bytes stored", size, GNUNET_NO); GNUNET_free (block); }
/** * Periodically announce self id in the DHT * * @param cls closure */ static void announce_id (void *cls) { struct GNUNET_HashCode phash; const struct GNUNET_HELLO_Message *hello; size_t size; struct GNUNET_TIME_Absolute expiration; struct GNUNET_TIME_Relative next_put; hello = GCH_get_mine (); size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; if (0 == size) { expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), announce_delay); announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); } else { expiration = GNUNET_HELLO_get_last_expiration (hello); announce_delay = GNUNET_TIME_UNIT_SECONDS; } /* Call again in id_announce_time, unless HELLO expires first, * but wait at least 1s. */ next_put = GNUNET_TIME_absolute_get_remaining (expiration); next_put = GNUNET_TIME_relative_min (next_put, id_announce_time); next_put = GNUNET_TIME_relative_max (next_put, GNUNET_TIME_UNIT_SECONDS); announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, &announce_id, cls); GNUNET_STATISTICS_update (stats, "# DHT announce", 1, GNUNET_NO); memset (&phash, 0, sizeof (phash)); GNUNET_memcpy (&phash, &my_full_id, sizeof (my_full_id)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Announcing my HELLO (%u bytes) in the DHT\n", size); GNUNET_DHT_put (dht_handle, /* DHT handle */ &phash, /* Key to use */ dht_replication_level, /* Replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ size, /* Size of the data */ (const char *) hello, /* Data itself */ expiration, /* Data expiration */ NULL, /* Continuation */ NULL); /* Continuation closure */ }