* those peer from sending their messages at a later duration. So
* every peer should receive the same nearest peer message, and from
* this can calculate the expected number of peers in the network.
- *
- * TODO:
- * - generate proof-of-work asynchronously, store it on disk & load it back
- * - handle messages for future round (one into the future, see FIXME)
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_nse_service.h"
#include "nse.h"
+/**
+ * Send messages on connect.
+ */
+#define SEND_ON_CONNECT GNUNET_YES
+
+/**
+ * Should we generate a histogram with the time stamps of when we received
+ * NSE messages to disk? (for performance evaluation only, not useful in
+ * production)
+ */
+#define ENABLE_HISTOGRAM GNUNET_YES
+
/**
* Over how many values do we calculate the weighted average?
*/
/**
* Amount of work required (W-bit collisions) for NSE proofs, in collision-bits.
*/
-#define NSE_WORK_REQUIRED 0
+static unsigned long long nse_work_required;
/**
* Interval for sending network size estimation flood requests.
*/
-#define GNUNET_NSE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
+static struct GNUNET_TIME_Relative gnunet_nse_interval;
+
+/**
+ * Interval between proof find runs.
+ */
+static struct GNUNET_TIME_Relative proof_find_delay;
+
+
+#if ENABLE_HISTOGRAM
+static struct GNUNET_BIO_WriteHandle *wh;
+#endif
/**
/**
* Did we receive or send a message about the previous round
- * to this peer yet?
+ * to this peer yet? GNUNET_YES if the previous round has
+ * been taken care of.
*/
int previous_round;
};
*/
static uint32_t hop_count_max;
+/**
+ * Message for the next round, if we got any.
+ */
+static struct GNUNET_NSE_FloodMessage next_message;
+
/**
* Array of recent size estimate messages.
*/
*/
static GNUNET_SCHEDULER_TaskIdentifier flood_task;
+/**
+ * Task scheduled to compute our proof.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier proof_task;
+
/**
* Notification context, simplifies client broadcasts.
*/
mean = 0.0;
sum = 0.0;
sumweight = 0.0;
- for (i=0;i<estimate_count; i++)
+ for (i = 0; i < estimate_count; i++)
{
- val = htonl (size_estimate_messages[(estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE].matching_bits);
- weight = estimate_count + 1 - i;
+ val = htonl (size_estimate_messages[(estimate_index - i + HISTORY_SIZE)
+ % HISTORY_SIZE].matching_bits);
+ weight = 1; /* was: estimate_count + 1 - i; */
temp = weight + sumweight;
q = val - mean;
em->header.type
= htons (GNUNET_MESSAGE_TYPE_NSE_ESTIMATE);
em->reserved = htonl (0);
- em->size_estimate = mean - 0.5;
+ em->timestamp = GNUNET_TIME_absolute_hton(GNUNET_TIME_absolute_get());
+ em->size_estimate = mean - 1.0/3.0;
em->std_deviation = std_dev;
GNUNET_STATISTICS_set (stats,
"# nodes in the network (estimate)",
- (uint64_t) pow (2, mean - 0.5), GNUNET_NO);
+ (uint64_t) pow (2, mean - 1.0/3.0), GNUNET_NO);
}
const struct GNUNET_MessageHeader *message)
{
struct GNUNET_NSE_ClientMessage em;
+
#if DEBUG_NSE
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
"Received START message from client\n");
get_matching_bits_delay (uint32_t matching_bits)
{
/* Calculated as: S + f/2 - (f / pi) * (atan(x - p'))*/
- // S is next_timestamp
- // f is frequency (GNUNET_NSE_INTERVAL)
+ // S is next_timestamp (ignored in return value)
+ // f is frequency (gnunet_nse_interval)
// x is matching_bits
// p' is current_size_estimate
- return ((double) GNUNET_NSE_INTERVAL.rel_value / (double) 2)
- - ((GNUNET_NSE_INTERVAL.rel_value / M_PI) * atan (matching_bits - current_size_estimate));
+ return ((double) gnunet_nse_interval.rel_value / (double) 2.0)
+ - ((gnunet_nse_interval.rel_value / M_PI) * atan (matching_bits - current_size_estimate));
}
/* previous round is randomized between 0 and 50 ms */
ret.rel_value = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
50);
+#if DEBUG_NSE
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Transmitting previous round behind schedule in %llu ms\n",
+ (unsigned long long) ret.rel_value);
+#endif
return ret;
case 0:
/* current round is based on best-known matching_bits */
dist_delay = get_matching_bits_delay (matching_bits);
dist_delay += get_delay_randomization (matching_bits).rel_value;
ret.rel_value = (uint64_t) dist_delay;
+#if DEBUG_NSE
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "For round %llu, delay for %u matching bits is %llu ms\n",
+ (unsigned long long) current_timestamp.abs_value,
+ (unsigned int) matching_bits,
+ (unsigned long long) ret.rel_value);
+#endif
/* now consider round start time and add delay to it */
tgt = GNUNET_TIME_absolute_add (current_timestamp, ret);
return GNUNET_TIME_absolute_get_remaining (tgt);
return 0;
}
GNUNET_assert (size >= sizeof (struct GNUNET_NSE_FloodMessage));
-#if DEBUG_NSE > 1
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Sending size estimate to `%s'\n",
- GNUNET_i2s (&peer_entry->id));
-#endif
idx = estimate_index;
- if (peer_entry->previous_round == GNUNET_YES)
+ if (peer_entry->previous_round == GNUNET_NO)
{
- idx = (idx + HISTORY_SIZE -1) % HISTORY_SIZE;
- peer_entry->previous_round = GNUNET_NO;
+ idx = (idx + HISTORY_SIZE - 1) % HISTORY_SIZE;
+ peer_entry->previous_round = GNUNET_YES;
peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (get_transmit_delay (0),
&transmit_task,
peer_entry);
}
+ if ( (ntohl (size_estimate_messages[idx].hop_count) == 0) &&
+ (GNUNET_SCHEDULER_NO_TASK != proof_task) )
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# flood messages not generated (no proof yet)",
+ 1,
+ GNUNET_NO);
+ return 0;
+ }
+#if DEBUG_NSE
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "In round %llu, sending to `%s' estimate with %u bits\n",
+ (unsigned long long) GNUNET_TIME_absolute_ntoh (size_estimate_messages[idx].timestamp).abs_value,
+ GNUNET_i2s (&peer_entry->id),
+ (unsigned int) ntohl (size_estimate_messages[idx].matching_bits));
+#endif
+ if (ntohl (size_estimate_messages[idx].hop_count) == 0)
+ GNUNET_STATISTICS_update (stats,
+ "# flood messages started",
+ 1,
+ GNUNET_NO);
+ GNUNET_STATISTICS_update (stats,
+ "# flood messages transmitted",
+ 1,
+ GNUNET_NO);
memcpy (buf,
&size_estimate_messages[idx],
sizeof (struct GNUNET_NSE_FloodMessage));
}
current_timestamp = next_timestamp;
next_timestamp = GNUNET_TIME_absolute_add (current_timestamp,
- GNUNET_NSE_INTERVAL);
+ gnunet_nse_interval);
estimate_index = (estimate_index + 1) % HISTORY_SIZE;
if (estimate_count < HISTORY_SIZE)
estimate_count++;
- setup_flood_message (estimate_index, current_timestamp);
+ if (next_timestamp.abs_value ==
+ GNUNET_TIME_absolute_ntoh (next_message.timestamp).abs_value)
+ {
+ /* we received a message for this round way early, use it! */
+ size_estimate_messages[estimate_index] = next_message;
+ size_estimate_messages[estimate_index].hop_count
+ = htonl (1 + ntohl (next_message.hop_count));
+ }
+ else
+ setup_flood_message (estimate_index, current_timestamp);
+ next_message.matching_bits = htonl (0); /* reset for 'next' round */
hop_count_max = 0;
- for (i=0;i<HISTORY_SIZE;i++)
+ for (i = 0; i < HISTORY_SIZE; i++)
hop_count_max = GNUNET_MAX (ntohl (size_estimate_messages[i].hop_count),
hop_count_max);
GNUNET_CONTAINER_multihashmap_iterate (peers,
pkey,
sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
GNUNET_CRYPTO_hash (buf, sizeof (buf), &result);
- return (count_leading_zeroes (&result) >= NSE_WORK_REQUIRED) ? GNUNET_YES : GNUNET_NO;
+ return (count_leading_zeroes (&result) >= nse_work_required) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Write our current proof to disk.
+ */
+static void
+write_proof ()
+{
+ char *proof;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "NSE", "PROOFFILE",
+ &proof))
+ return;
+ if (sizeof (my_proof) !=
+ GNUNET_DISK_fn_write (proof,
+ &my_proof,
+ sizeof (my_proof),
+ GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "write",
+ proof);
+ GNUNET_free (proof);
+
}
/**
- * Given a public key, find an integer such that the hash of the key
- * concatenated with the integer has NSE_WORK_REQUIRED leading 0
- * bits. FIXME: this is a synchronous function... bad
+ * Find our proof of work.
*
- * @param pkey the public key
- * @return 64 bit number that satisfies the requirements
+ * @param cls closure (unused)
+ * @param tc task context
*/
-static uint64_t
-find_proof_of_work(const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey)
+static void
+find_proof (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
+#define ROUND_SIZE 10
uint64_t counter;
char buf[sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sizeof(uint64_t)];
GNUNET_HashCode result;
+ unsigned int i;
+ proof_task = GNUNET_SCHEDULER_NO_TASK;
memcpy (&buf[sizeof(uint64_t)],
- pkey,
+ &my_public_key,
sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- counter = 0;
- while (counter != UINT64_MAX)
+ i = 0;
+ counter = my_proof;
+ while ( (counter != UINT64_MAX) && (i < ROUND_SIZE) )
{
memcpy (buf,
&counter,
sizeof(uint64_t));
GNUNET_CRYPTO_hash (buf, sizeof (buf), &result);
- if (NSE_WORK_REQUIRED <= count_leading_zeroes(&result))
- break;
+ if (nse_work_required <= count_leading_zeroes(&result))
+ {
+ my_proof = counter;
+#if DEBUG_NSE
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Proof of work found: %llu!\n",
+ (unsigned long long) GNUNET_ntohll (counter));
+#endif
+ for (i=0;i<HISTORY_SIZE;i++)
+ if (ntohl (size_estimate_messages[i].hop_count) == 0)
+ {
+ size_estimate_messages[i].proof_of_work = my_proof;
+ GNUNET_CRYPTO_rsa_sign (my_private_key,
+ &size_estimate_messages[i].purpose,
+ &size_estimate_messages[i].signature);
+ }
+ write_proof ();
+ return;
+ }
counter++;
+ i++;
}
- return counter;
+ if (my_proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE))
+ {
+#if DEBUG_NSE
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Testing proofs currently at %llu\n",
+ (unsigned long long) counter);
+#endif
+ /* remember progress every 100 rounds */
+ my_proof = counter;
+ write_proof ();
+ }
+ else
+ {
+ my_proof = counter;
+ }
+ proof_task = GNUNET_SCHEDULER_add_delayed (proof_find_delay,
+ &find_proof,
+ NULL);
}
check_proof_of_work (&incoming_flood->pkey,
incoming_flood->proof_of_work))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Proof of work invalid: %llu!\n"),
+ (unsigned long long) GNUNET_ntohll (incoming_flood->proof_of_work));
GNUNET_break_op (0);
return GNUNET_NO;
}
return GNUNET_OK; /* already active */
if (peer_entry == exclude)
return GNUNET_OK; /* trigger of the update */
- if (peer_entry->previous_round == GNUNET_YES)
+ if (peer_entry->previous_round == GNUNET_NO)
{
/* still stuck in previous round, no point to update, check that
we are active here though... */
+#if SEND_ON_CONNECT
GNUNET_break (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK);
+#endif
return GNUNET_OK;
}
if (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK)
uint32_t matching_bits;
unsigned int idx;
+#if ENABLE_HISTOGRAM
+ if (NULL != wh)
+ GNUNET_BIO_write_int64 (wh, GNUNET_TIME_absolute_get ().abs_value);
+#endif
incoming_flood = (const struct GNUNET_NSE_FloodMessage *) message;
GNUNET_STATISTICS_update (stats,
"# flood messages received",
1,
GNUNET_NO);
matching_bits = ntohl (incoming_flood->matching_bits);
+#if DEBUG_NSE
+ {
+ char origin[5];
+ char pred[5];
+ struct GNUNET_PeerIdentity os;
+
+ GNUNET_CRYPTO_hash (&incoming_flood->pkey,
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &os.hashPubKey);
+ GNUNET_snprintf (origin, sizeof (origin),
+ "%s",
+ GNUNET_i2s (&os));
+ GNUNET_snprintf (pred, sizeof (pred),
+ "%s",
+ GNUNET_i2s (peer));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Flood at %llu from `%s' via `%s' at `%s' with bits %u\n",
+ (unsigned long long) GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp).abs_value,
+ origin,
+ pred,
+ GNUNET_i2s (&my_identity),
+ (unsigned int) matching_bits);
+ }
+#endif
+
peer_entry = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
if (NULL == peer_entry)
{
GNUNET_break (0);
return GNUNET_OK;
}
+
ts = GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp);
+
if (ts.abs_value == current_timestamp.abs_value)
idx = estimate_index;
- else if (ts.abs_value == current_timestamp.abs_value - GNUNET_NSE_INTERVAL.rel_value)
+ else if (ts.abs_value == current_timestamp.abs_value - gnunet_nse_interval.rel_value)
idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE;
- else if (ts.abs_value == next_timestamp.abs_value - GNUNET_NSE_INTERVAL.rel_value)
+ else if (ts.abs_value == next_timestamp.abs_value - gnunet_nse_interval.rel_value)
{
+ if (matching_bits <= ntohl (next_message.matching_bits))
+ return GNUNET_OK; /* ignore, simply too early/late */
if (GNUNET_YES !=
verify_message_crypto (incoming_flood))
{
GNUNET_break_op (0);
return GNUNET_OK;
}
- /* FIXME: keep in special 'future' buffer until next round starts for us! */
- GNUNET_break (0); /* not implemented */
+ next_message = *incoming_flood;
return GNUNET_OK;
}
else
"# flood messages discarded (clock skew too large)",
1,
GNUNET_NO);
- GNUNET_break_op (0);
return GNUNET_OK;
}
if (0 == (memcmp (peer, &my_identity, sizeof(struct GNUNET_PeerIdentity))))
/* cancel transmission from us to this peer for this round */
if (idx == estimate_index)
{
- if (peer_entry->previous_round == GNUNET_NO)
+ if (peer_entry->previous_round == GNUNET_YES)
{
/* cancel any activity for current round */
if (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK;
- peer_entry->previous_round = GNUNET_NO;
}
if (peer_entry->th != NULL)
{
else
{
/* cancel previous round only */
- peer_entry->previous_round = GNUNET_NO;
- }
-
+ peer_entry->previous_round = GNUNET_YES;
+ }
}
if (matching_bits <= ntohl (size_estimate_messages[idx].matching_bits))
{
+ if ( (idx < estimate_index) &&
+ (peer_entry->previous_round == GNUNET_YES) )
+ peer_entry->previous_round = GNUNET_NO;
+ /* push back our result now, that peer is spreading bad information... */
+ if (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
+ peer_entry->transmit_task = GNUNET_SCHEDULER_add_now (&transmit_task,
+ peer_entry);
/* Not closer than our most recent message, no need to do work here */
GNUNET_STATISTICS_update (stats,
"# flood messages ignored (had closer already)",
{
struct NSEPeerEntry *peer_entry;
+ #if DEBUG_NSE
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Peer `%s' connected to us\n",
+ GNUNET_i2s (peer));
+#endif
peer_entry = GNUNET_malloc(sizeof(struct NSEPeerEntry));
peer_entry->id = *peer;
GNUNET_CONTAINER_multihashmap_put (peers,
&peer->hashPubKey,
peer_entry,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+#if SEND_ON_CONNECT
peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1),
&transmit_task,
peer_entry);
+#endif
}
{
struct NSEPeerEntry *pos;
- pos = GNUNET_CONTAINER_multihashmap_get (peers,
+ #if DEBUG_NSE
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Peer `%s' disconnected from us\n",
+ GNUNET_i2s (peer));
+#endif
+ pos = GNUNET_CONTAINER_multihashmap_get (peers,
&peer->hashPubKey);
if (NULL == pos)
{
GNUNET_SCHEDULER_cancel (flood_task);
flood_task = GNUNET_SCHEDULER_NO_TASK;
}
+ if (proof_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (proof_task);
+ proof_task = GNUNET_SCHEDULER_NO_TASK;
+ write_proof (); /* remember progress */
+ }
if (nc != NULL)
{
GNUNET_SERVER_notification_context_destroy (nc);
GNUNET_CONTAINER_multihashmap_destroy (peers);
peers = NULL;
}
+ if (my_private_key != NULL)
+ {
+ GNUNET_CRYPTO_rsa_key_free (my_private_key);
+ my_private_key = NULL;
+ }
+#if ENABLE_HISTOGRAM
+ if (wh != NULL)
+ {
+ GNUNET_BIO_write_close (wh);
+ wh = NULL;
+ }
+#endif
}
GNUNET_SCHEDULER_shutdown ();
return;
}
- my_identity = *identity;
- my_public_key = *publicKey;
-
+ GNUNET_assert (0 == memcmp (&my_identity, identity, sizeof (struct GNUNET_PeerIdentity)));
now = GNUNET_TIME_absolute_get ();
- current_timestamp.abs_value = (now.abs_value / GNUNET_NSE_INTERVAL.rel_value) * GNUNET_NSE_INTERVAL.rel_value;
- next_timestamp.abs_value = current_timestamp.abs_value + GNUNET_NSE_INTERVAL.rel_value;
+ current_timestamp.abs_value = (now.abs_value / gnunet_nse_interval.rel_value) * gnunet_nse_interval.rel_value;
+ next_timestamp.abs_value = current_timestamp.abs_value + gnunet_nse_interval.rel_value;
- for (i=0;i<HISTORY_SIZE;i++)
+ for (i = 0; i < HISTORY_SIZE; i++)
{
- prev_time.abs_value = current_timestamp.abs_value - (HISTORY_SIZE - i - 1) * GNUNET_NSE_INTERVAL.rel_value;
+ prev_time.abs_value = current_timestamp.abs_value - (HISTORY_SIZE - i - 1) * gnunet_nse_interval.rel_value;
setup_flood_message (i, prev_time);
}
estimate_index = HISTORY_SIZE - 1;
flood_task
= GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_timestamp),
&update_flood_message, NULL);
- my_proof = find_proof_of_work (&my_public_key);
}
const struct GNUNET_CONFIGURATION_Handle *c)
{
char *keyfile;
+ char *proof;
static const struct GNUNET_SERVER_MessageHandler handlers[] =
{
{ NULL, 0, 0 }
};
cfg = c;
+
+ if ( (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (cfg,
+ "NSE", "INTERVAL",
+ &gnunet_nse_interval)) ||
+ (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (cfg,
+ "NSE", "WORKDELAY",
+ &proof_find_delay)) ||
+ (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "NSE", "WORKBITS",
+ &nse_work_required)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _ ("NSE service is lacking key configuration settings. Exiting.\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (nse_work_required >= sizeof (GNUNET_HashCode) * 8)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Invalid work requirement for NSE service. Exiting.\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
"GNUNETD", "HOSTKEY",
GNUNET_SCHEDULER_shutdown ();
return;
}
+ GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
+ GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &my_identity.hashPubKey);
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "NSE", "PROOFFILE",
+ &proof))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _ ("NSE service is lacking key configuration settings. Exiting.\n"));
+ if (my_private_key != NULL)
+ {
+ GNUNET_CRYPTO_rsa_key_free (my_private_key);
+ my_private_key = NULL;
+ }
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if ( (GNUNET_YES != GNUNET_DISK_file_test (proof)) ||
+ (sizeof (my_proof) !=
+ GNUNET_DISK_fn_read (proof,
+ &my_proof,
+ sizeof (my_proof))) )
+ my_proof = 0;
+ GNUNET_free (proof);
+ proof_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
+ &find_proof,
+ NULL);
+
peers = GNUNET_CONTAINER_multihashmap_create (128);
GNUNET_SERVER_add_handlers (server, handlers);
nc = GNUNET_SERVER_notification_context_create (server, 1);
core_handlers); /* Register these handlers */
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
&shutdown_task, NULL);
+#if ENABLE_HISTOGRAM
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "NSE", "HISTOGRAM",
+ &proof))
+ {
+ wh = GNUNET_BIO_write_open (proof);
+ GNUNET_free (proof);
+ }
+#endif
if (coreAPI == NULL)
{
GNUNET_SCHEDULER_shutdown ();