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
*/
/**
#include "gnunet_applications.h"
#include "gnunet_util_lib.h"
#include "gnunet_cadet_service.h"
+#include "gnunet_core_service.h"
#include "gnunet_peerinfo_service.h"
#include "gnunet_nse_service.h"
#include "gnunet_statistics_service.h"
* it, how did we get its ID, how many pushes (in a timeinterval),
* ...)
*/
+ uint32_t round_pull_req;
};
/**
};
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
/**
* If type is 2 This struct is used to store the attacked peers in a DLL
#endif /* ENABLE_MALICIOUS */
+/**
+ * @brief This number determines the number of slots for files that represent
+ * histograms
+ */
+#define HISTOGRAM_FILE_SLOTS 32
+
+/**
+ * @brief The size (in bytes) a file needs to store the histogram
+ *
+ * Per slot: 1 newline, up to 4 chars,
+ * Additionally: 1 null termination
+ */
+#define SIZE_DUMP_FILE (HISTOGRAM_FILE_SLOTS * 5) + 1
+
/**
* @brief One Sub.
*
unsigned int sampler_size_est_need;
/**
- * Time inverval the do_round task runs in.
+ * Time interval the do_round task runs in.
*/
struct GNUNET_TIME_Relative round_interval;
*/
struct RPS_Sampler *sampler;
+#ifdef TO_FILE_FULL
/**
* Name to log view to
*/
char *file_name_view_log;
+#endif /* TO_FILE_FULL */
#ifdef TO_FILE
+#ifdef TO_FILE_FULL
/**
* Name to log number of observed peers to
*/
char *file_name_observed_log;
+#endif /* TO_FILE_FULL */
/**
* @brief Count the observed peers
* Identifier for the main task that runs periodically.
*/
struct GNUNET_SCHEDULER_Task *do_round_task;
+
+ /* === stats === */
+
+ /**
+ * @brief Counts the executed rounds.
+ */
+ uint32_t num_rounds;
+
+ /**
+ * @brief This array accumulates the number of received pushes per round.
+ *
+ * Number at index i represents the number of rounds with i observed pushes.
+ */
+ uint32_t push_recv[HISTOGRAM_FILE_SLOTS];
+
+ /**
+ * @brief Histogram of deltas between the expected and actual number of
+ * received pushes.
+ *
+ * As half of the entries are expected to be negative, this is shifted by
+ * #HISTOGRAM_FILE_SLOTS/2.
+ */
+ uint32_t push_delta[HISTOGRAM_FILE_SLOTS];
+
+ /**
+ * @brief Number of pull replies with this delay measured in rounds.
+ *
+ * Number at index i represents the number of pull replies with a delay of i
+ * rounds.
+ */
+ uint32_t pull_delays[HISTOGRAM_FILE_SLOTS];
};
*/
struct GNUNET_CADET_Handle *cadet_handle;
+/**
+ * Handle to CORE
+ */
+struct GNUNET_CORE_Handle *core_handle;
+
+/**
+ * @brief PeerMap to keep track of connected peers.
+ */
+struct GNUNET_CONTAINER_MultiPeerMap *map_single_hop;
+
/**
* Our own identity.
*/
static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify_handle;
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
/**
* Type of malicious peer
*
ret = GNUNET_CONTAINER_multipeermap_put (sub->peer_map, peer, ctx,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
GNUNET_assert (GNUNET_OK == ret);
- GNUNET_STATISTICS_set (stats,
- "# known peers",
- GNUNET_CONTAINER_multipeermap_size (sub->peer_map),
- GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "# known peers",
+ GNUNET_CONTAINER_multipeermap_size (sub->peer_map),
+ GNUNET_NO);
+ }
return ctx;
}
* @return a random peer
*/
static const struct GNUNET_PeerIdentity *
-get_random_peer_from_peermap (const struct
- GNUNET_CONTAINER_MultiPeerMap *valid_peers)
+get_random_peer_from_peermap (struct GNUNET_CONTAINER_MultiPeerMap *valid_peers)
{
struct GetRandPeerIteratorCls *iterator_cls;
const struct GNUNET_PeerIdentity *ret;
}
(void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
- GNUNET_STATISTICS_set (stats,
- "# valid peers",
- GNUNET_CONTAINER_multipeermap_size (valid_peers),
- GNUNET_NO);
+ if (valid_peers == msub->valid_peers)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "# valid peers",
+ GNUNET_CONTAINER_multipeermap_size (valid_peers),
+ GNUNET_NO);
+ }
return ret;
}
struct GNUNET_CADET_Channel *
get_channel (struct PeerContext *peer_ctx)
{
- struct GNUNET_PeerIdentity *ctx_peer;
/* There exists a copy-paste-clone in run() */
struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
GNUNET_MQ_hd_fixed_size (peer_check,
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Trying to establish channel to peer %s\n",
GNUNET_i2s (&peer_ctx->peer_id));
- ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity);
- *ctx_peer = peer_ctx->peer_id;
peer_ctx->send_channel_ctx = add_channel_ctx (peer_ctx);
peer_ctx->send_channel_ctx->channel =
GNUNET_CADET_channel_create (cadet_handle,
mq_online_check_successful,
peer_ctx);
GNUNET_MQ_send (mq, ev);
- GNUNET_STATISTICS_update (stats,
- "# pending online checks",
- 1,
- GNUNET_NO);
+ if (peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pending online checks",
+ 1,
+ GNUNET_NO);
+ }
}
sizeof (struct PendingMessage))) )
{
peer_ctx->online_check_pending = NULL;
- GNUNET_STATISTICS_update (stats,
- "# pending online checks",
- -1,
- GNUNET_NO);
+ if (peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pending online checks",
+ -1,
+ GNUNET_NO);
+ }
}
remove_pending_message (peer_ctx->pending_messages_head,
GNUNET_YES);
LOG (GNUNET_ERROR_TYPE_WARNING,
"removing peer from peer_ctx->sub->peer_map failed\n");
}
- GNUNET_STATISTICS_set (stats,
- "# known peers",
- GNUNET_CONTAINER_multipeermap_size (peer_ctx->sub->peer_map),
- GNUNET_NO);
+ if (peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "# known peers",
+ GNUNET_CONTAINER_multipeermap_size (peer_ctx->sub->peer_map),
+ GNUNET_NO);
+ }
GNUNET_free (peer_ctx);
return GNUNET_YES;
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"%s was sent.\n",
pending_msg->type);
- if (0 == strncmp ("PULL REPLY", pending_msg->type, 10))
- GNUNET_STATISTICS_update(stats, "# pull replys sent", 1, GNUNET_NO);
- if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12))
- GNUNET_STATISTICS_update(stats, "# pull requests sent", 1, GNUNET_NO);
- if (0 == strncmp ("PUSH", pending_msg->type, 4))
- GNUNET_STATISTICS_update(stats, "# pushes sent", 1, GNUNET_NO);
+ if (pending_msg->peer_ctx->sub == msub)
+ {
+ if (0 == strncmp ("PULL REPLY", pending_msg->type, 10))
+ GNUNET_STATISTICS_update(stats, "# pull replys sent", 1, GNUNET_NO);
+ if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12))
+ GNUNET_STATISTICS_update(stats, "# pull requests sent", 1, GNUNET_NO);
+ if (0 == strncmp ("PUSH", pending_msg->type, 4))
+ GNUNET_STATISTICS_update(stats, "# pushes sent", 1, GNUNET_NO);
+ if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12) &&
+ NULL != map_single_hop &&
+ GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop,
+ &pending_msg->peer_ctx->peer_id))
+ GNUNET_STATISTICS_update(stats,
+ "# pull requests sent (multi-hop peer)",
+ 1,
+ GNUNET_NO);
+ }
/* Do not cancle message */
remove_pending_message (pending_msg, GNUNET_NO);
}
* #GNUNET_SYSERR if it aborted iteration
*/
static int
-get_valid_peers (const struct GNUNET_CONTAINER_MultiPeerMap *valid_peers,
+get_valid_peers (struct GNUNET_CONTAINER_MultiPeerMap *valid_peers,
PeersIterator iterator,
void *it_cls)
{
if ( (NULL != peer_ctx->recv_channel_ctx) ||
(NULL != peer_ctx->pending_messages_head) ||
- (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
+ (GNUNET_YES == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
{
return GNUNET_NO;
}
const struct GNUNET_PeerIdentity *initiator)
{
struct PeerContext *peer_ctx;
- struct GNUNET_PeerIdentity *ctx_peer;
struct ChannelCtx *channel_ctx;
struct Sub *sub = cls;
peer_ctx = create_or_get_peer_ctx (sub, initiator);
set_peer_online (peer_ctx);
(void) add_valid_peer (&peer_ctx->peer_id, peer_ctx->sub->valid_peers);
- ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity);
- *ctx_peer = *initiator;
channel_ctx = add_channel_ctx (peer_ctx);
channel_ctx->channel = channel;
/* We only accept one incoming channel per peer */
for ( i = 0 ; i < *list_size ; i++ )
{
- if (0 == GNUNET_CRYPTO_cmp_peer_identity (&tmp[i], peer))
+ if (0 == GNUNET_memcmp (&tmp[i], peer))
{
if (i < *list_size -1)
{ /* Not at the last entry -- shift peers left */
*/
static void
insert_in_view_op (void *cls,
- const struct GNUNET_PeerIdentity *peer);
+ const struct GNUNET_PeerIdentity *peer);
/**
* Insert PeerID in #view
(GNUNET_SYSERR == online) ) /* peer is not even known */
{
(void) issue_peer_online_check (sub, peer);
- (void) schedule_operation (peer_ctx, insert_in_view_op, NULL);
+ (void) schedule_operation (peer_ctx, insert_in_view_op, sub);
return GNUNET_NO;
}
/* Open channel towards peer to keep connection open */
indicate_sending_intention (peer_ctx);
ret = View_put (sub->view, peer);
- GNUNET_STATISTICS_set (stats,
- "view size",
- View_size (peer_ctx->sub->view),
- GNUNET_NO);
+ if (peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "view size",
+ View_size (peer_ctx->sub->view),
+ GNUNET_NO);
+ }
return ret;
}
{
struct GNUNET_MQ_Envelope *ev;
struct GNUNET_RPS_CS_DEBUG_ViewReply *out_msg;
+ struct Sub *sub;
if (NULL == view_array)
{
- if (NULL == cli_ctx->sub)
- {
- view_size = View_size (msub->view);
- view_array = View_get_as_array (msub->view);
- }
- else
- {
- view_size = View_size (cli_ctx->sub->view);
- view_array = View_get_as_array (cli_ctx->sub->view);
- }
+ if (NULL == cli_ctx->sub) sub = msub;
+ else sub = cli_ctx->sub;
+ view_size = View_size (sub->view);
+ view_array = View_get_as_array (sub->view);
}
ev = GNUNET_MQ_msg_extra (out_msg,
for (i = 0; i < num_peers; i++)
{
int inserted;
+ if (GNUNET_YES != check_peer_known (sub->peer_map, &ids[i]))
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Peer in history update not known!\n");
+ continue;
+ }
inserted = insert_in_view (sub, &ids[i]);
if (GNUNET_OK == inserted)
{
clients_notify_stream_peer (sub, 1, &ids[i]);
}
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"+%s\t(hist)",
GNUNET_i2s_full (ids));
+#endif /* TO_FILE_FULL */
}
clients_notify_view_update (sub);
}
&peer_array[i],
NULL,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
- GNUNET_STATISTICS_set (stats,
- "# known peers",
- GNUNET_CONTAINER_multipeermap_size (peer_map),
- GNUNET_NO);
+ if (msub->peer_map == peer_map)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "# known peers",
+ GNUNET_CONTAINER_multipeermap_size (peer_map),
+ GNUNET_NO);
+ }
}
}
send_size * sizeof (struct GNUNET_PeerIdentity));
send_message (peer_ctx, ev, "PULL REPLY");
- GNUNET_STATISTICS_update(stats, "# pull reply send issued", 1, GNUNET_NO);
+ if (peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update(stats, "# pull reply send issued", 1, GNUNET_NO);
+ }
// TODO check with send intention: as send_channel is used/opened we indicate
// a sending intention without intending it.
// -> clean peer afterwards?
* messages to it */
//indicate_sending_intention (peer);
}
- #ifdef TO_FILE
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# observed peers in gossip",
+ 1,
+ GNUNET_NO);
+ }
+#ifdef TO_FILE
sub->num_observed_peers++;
GNUNET_CONTAINER_multipeermap_put
(sub->observed_unique_peers,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
uint32_t num_observed_unique_peers =
GNUNET_CONTAINER_multipeermap_size (sub->observed_unique_peers);
+ GNUNET_STATISTICS_set (stats,
+ "# unique peers in gossip",
+ num_observed_unique_peers,
+ GNUNET_NO);
+#ifdef TO_FILE_FULL
to_file (sub->file_name_observed_log,
"%" PRIu32 " %" PRIu32 " %f\n",
sub->num_observed_peers,
num_observed_unique_peers,
1.0*num_observed_unique_peers/sub->num_observed_peers)
- #endif /* TO_FILE */
+#endif /* TO_FILE_FULL */
+#endif /* TO_FILE */
}
schedule_operation (get_peer_ctx (sub->peer_map, peer),
&insert_in_view_op, sub);
}
- GNUNET_STATISTICS_update (stats,
- "# learnd peers",
- 1,
- GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# learnd peers",
+ 1,
+ GNUNET_NO);
+ }
}
remove_peer (struct Sub *sub,
const struct GNUNET_PeerIdentity *peer)
{
- (void) View_remove_peer (sub->view, peer);
- CustomPeerMap_remove_peer (sub->pull_map, peer);
- CustomPeerMap_remove_peer (sub->push_map, peer);
- RPS_sampler_reinitialise_by_value (sub->sampler, peer);
- destroy_peer (get_peer_ctx (sub->peer_map, peer));
+ (void) View_remove_peer (sub->view,
+ peer);
+ CustomPeerMap_remove_peer (sub->pull_map,
+ peer);
+ CustomPeerMap_remove_peer (sub->push_map,
+ peer);
+ RPS_sampler_reinitialise_by_value (sub->sampler,
+ peer);
+ /* We want to destroy the peer now.
+ * Sometimes, it just seems that it's already been removed from the peer_map,
+ * so check the peer_map first. */
+ if (GNUNET_YES == check_peer_known (sub->peer_map,
+ peer))
+ {
+ destroy_peer (get_peer_ctx (sub->peer_map,
+ peer));
+ }
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Going to remove send channel to peer %s\n",
GNUNET_i2s (peer));
- #ifdef ENABLE_MALICIOUS
- if (0 != GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
- (void) destroy_sending_channel (get_peer_ctx (sub->peer_map, peer));
+ #if ENABLE_MALICIOUS
+ if (0 != GNUNET_memcmp (&attacked_peer,
+ peer))
+ (void) destroy_sending_channel (get_peer_ctx (sub->peer_map,
+ peer));
#else /* ENABLE_MALICIOUS */
- (void) destroy_sending_channel (get_peer_ctx (sub->peer_map, peer));
+ (void) destroy_sending_channel (get_peer_ctx (sub->peer_map,
+ peer));
#endif /* ENABLE_MALICIOUS */
}
+ if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (sub->peer_map,
+ peer))
+ {
+ /* Peer was already removed by callback on destroyed channel */
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Peer was removed from our knowledge during cleanup\n");
+ return;
+ }
+
if ( (GNUNET_NO == check_peer_send_intention (get_peer_ctx (sub->peer_map,
peer))) &&
(GNUNET_NO == View_contains_peer (sub->view, peer)) &&
(GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
(GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
- (0 == RPS_sampler_count_id (sub->sampler, peer)) &&
- (GNUNET_NO != check_removable (get_peer_ctx (sub->peer_map, peer))) )
+ (0 == RPS_sampler_count_id (sub->sampler, peer)) &&
+ (GNUNET_YES == check_removable (get_peer_ctx (sub->peer_map, peer))) )
{ /* We can safely remove this peer */
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Going to remove peer %s\n",
channel_ctx->channel = NULL;
remove_channel_ctx (channel_ctx);
if (NULL != peer_ctx &&
- peer_ctx->send_channel_ctx == channel_ctx)
+ peer_ctx->send_channel_ctx == channel_ctx &&
+ GNUNET_YES == check_sending_channel_needed (channel_ctx->peer_ctx))
{
remove_peer (peer_ctx->sub, &peer_ctx->peer_id);
}
"rps",
"FILENAME_VALID_PEERS");
}
+ if (0 != strncmp ("DISABLE", sub->filename_valid_peers, 7))
+ {
+ char *tmp_filename_valid_peers;
+ char str_hash[105];
+
+ GNUNET_snprintf (str_hash,
+ sizeof (str_hash),
+ GNUNET_h2s_full (hash));
+ tmp_filename_valid_peers = sub->filename_valid_peers;
+ GNUNET_asprintf (&sub->filename_valid_peers,
+ "%s%s",
+ tmp_filename_valid_peers,
+ str_hash);
+ GNUNET_free (tmp_filename_valid_peers);
+ }
sub->peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
/* Set up the sampler */
round_interval);
/* Logging of internals */
+#ifdef TO_FILE_FULL
sub->file_name_view_log = store_prefix_file_name (&own_identity, "view");
- #ifdef TO_FILE
+#endif /* TO_FILE_FULL */
+#ifdef TO_FILE
+#ifdef TO_FILE_FULL
sub->file_name_observed_log = store_prefix_file_name (&own_identity,
"observed");
+#endif /* TO_FILE_FULL */
sub->num_observed_peers = 0;
sub->observed_unique_peers = GNUNET_CONTAINER_multipeermap_create (1,
GNUNET_NO);
- #endif /* TO_FILE */
+#endif /* TO_FILE */
/* Set up data structures for gossip */
sub->push_map = CustomPeerMap_create (4);
sub->pull_map = CustomPeerMap_create (4);
sub->view_size_est_min = sampler_size;;
sub->view = View_create (sub->view_size_est_min);
- GNUNET_STATISTICS_set (stats,
- "view size aim",
- sub->view_size_est_min,
- GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "view size aim",
+ sub->view_size_est_min,
+ GNUNET_NO);
+ }
/* Start executing rounds */
sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_round, sub);
}
+#ifdef TO_FILE
+/**
+ * @brief Write all numbers in the given array into the given file
+ *
+ * Single numbers devided by a newline
+ *
+ * @param hist_array[] the array to dump
+ * @param file_name file to dump into
+ */
+static void
+write_histogram_to_file (const uint32_t hist_array[],
+ const char *file_name)
+{
+ char collect_str[SIZE_DUMP_FILE + 1] = "";
+ char *recv_str_iter;
+ char *file_name_full;
+
+ recv_str_iter = collect_str;
+ file_name_full = store_prefix_file_name (&own_identity,
+ file_name);
+ for (uint32_t i = 0; i < HISTOGRAM_FILE_SLOTS; i++)
+ {
+ char collect_str_tmp[8];
+
+ GNUNET_snprintf (collect_str_tmp,
+ sizeof (collect_str_tmp),
+ "%" PRIu32 "\n",
+ hist_array[i]);
+ recv_str_iter = stpncpy (recv_str_iter,
+ collect_str_tmp,
+ 6);
+ }
+ (void) stpcpy (recv_str_iter,
+ "\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Writing push stats to disk\n");
+ to_file_w_len (file_name_full,
+ SIZE_DUMP_FILE,
+ collect_str);
+ GNUNET_free (file_name_full);
+}
+#endif /* TO_FILE */
+
+
/**
* @brief Destroy Sub.
*
/* Disconnect from cadet */
GNUNET_CADET_close_port (sub->cadet_port);
+ sub->cadet_port= NULL;
/* Clean up data structures for peers */
RPS_sampler_destroy (sub->sampler);
peers_terminate (sub);
/* Free leftover data structures */
+#ifdef TO_FILE_FULL
GNUNET_free (sub->file_name_view_log);
sub->file_name_view_log = NULL;
+#endif /* TO_FILE_FULL */
#ifdef TO_FILE
+#ifdef TO_FILE_FULL
GNUNET_free (sub->file_name_observed_log);
sub->file_name_observed_log = NULL;
+#endif /* TO_FILE_FULL */
+
+ /* Write push frequencies to disk */
+ write_histogram_to_file (sub->push_recv,
+ "push_recv");
+
+ /* Write push deltas to disk */
+ write_histogram_to_file (sub->push_delta,
+ "push_delta");
+
+ /* Write pull delays to disk */
+ write_histogram_to_file (sub->pull_delays,
+ "pull_delays");
+
GNUNET_CONTAINER_multipeermap_destroy (sub->observed_unique_peers);
sub->observed_unique_peers = NULL;
#endif /* TO_FILE */
***********************************************************************/
+/***********************************************************************
+ * Core handlers
+***********************************************************************/
+
+/**
+ * @brief Callback on initialisation of Core.
+ *
+ * @param cls - unused
+ * @param my_identity - unused
+ */
+void
+core_init (void *cls,
+ const struct GNUNET_PeerIdentity *my_identity)
+{
+ (void) cls;
+ (void) my_identity;
+
+ map_single_hop = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
+}
+
+
+/**
+ * @brief Callback for core.
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure - unused
+ * @param peer peer identity this notification is about
+ * @return closure given to #core_disconnects as peer_cls
+ */
+void *
+core_connects (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_MQ_Handle *mq)
+{
+ (void) cls;
+ (void) mq;
+
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multipeermap_put (map_single_hop,
+ peer,
+ NULL,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ return NULL;
+}
+
+
+/**
+ * @brief Callback for core.
+ * Method called whenever a peer disconnects.
+ *
+ * @param cls closure - unused
+ * @param peer peer identity this notification is about
+ * @param peer_cls closure given in #core_connects - unused
+ */
+void
+core_disconnects (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ void *peer_cls)
+{
+ (void) cls;
+ (void) peer_cls;
+
+ GNUNET_CONTAINER_multipeermap_remove_all (map_single_hop, peer);
+}
+
+/***********************************************************************
+ * /Core handlers
+***********************************************************************/
+
+
/**
* @brief Destroy the context for a (connected) client
*
//sub->sampler_size_est_need = sub->view_size_est_min;
sub->view_size_est_need = sub->view_size_est_min;
}
- GNUNET_STATISTICS_set (stats, "view size aim", sub->view_size_est_need, GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "view size aim",
+ sub->view_size_est_need,
+ GNUNET_NO);
+ }
/* If the NSE has changed adapt the lists accordingly */
resize_wrapper (sub->sampler, sub->sampler_size_est_need);
i,
GNUNET_i2s (&peers[i]));
- if (NULL != msub) got_peer (msub, &peers[i]);
+ if (NULL != msub) got_peer (msub, &peers[i]); /* Condition needed? */
if (NULL != cli_ctx->sub) got_peer (cli_ctx->sub, &peers[i]);
}
GNUNET_SERVICE_client_continue (cli_ctx->client);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer));
- GNUNET_STATISTICS_update (stats,
- "# pending online checks",
- -1,
- GNUNET_NO);
+ if (channel_ctx->peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pending online checks",
+ -1,
+ GNUNET_NO);
+ }
GNUNET_CADET_receive_done (channel_ctx->channel);
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received PUSH (%s)\n",
GNUNET_i2s (peer));
- GNUNET_STATISTICS_update(stats, "# push message received", 1, GNUNET_NO);
+ if (channel_ctx->peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update(stats, "# push message received", 1, GNUNET_NO);
+ if (NULL != map_single_hop &&
+ GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop,
+ peer))
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# push message received (multi-hop peer)",
+ 1,
+ GNUNET_NO);
+ }
+ }
- #ifdef ENABLE_MALICIOUS
+ #if ENABLE_MALICIOUS
struct AttackedPeer *tmp_att_peer;
if ( (1 == mal_type) ||
(void) msg;
LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer));
- GNUNET_STATISTICS_update(stats, "# pull request message received", 1, GNUNET_NO);
+ if (peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update(stats,
+ "# pull request message received",
+ 1,
+ GNUNET_NO);
+ if (NULL != map_single_hop &&
+ GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop,
+ &peer_ctx->peer_id))
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pull request message received (multi-hop peer)",
+ 1,
+ GNUNET_NO);
+ }
+ }
- #ifdef ENABLE_MALICIOUS
+ #if ENABLE_MALICIOUS
if (1 == mal_type
|| 3 == mal_type)
{ /* Try to maximise representation */
else if (2 == mal_type)
{ /* Try to partition network */
- if (0 == GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
+ if (0 == GNUNET_memcmp (&attacked_peer, peer))
{
send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
}
LOG (GNUNET_ERROR_TYPE_WARNING,
"Received a pull reply from a peer (%s) we didn't request one from!\n",
GNUNET_i2s (&sender_ctx->peer_id));
- GNUNET_STATISTICS_update (stats,
- "# unrequested pull replies",
- 1,
- GNUNET_NO);
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
+ if (sender_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# unrequested pull replies",
+ 1,
+ GNUNET_NO);
+ }
}
return GNUNET_OK;
}
const struct ChannelCtx *channel_ctx = cls;
const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id;
const struct GNUNET_PeerIdentity *peers;
+ struct Sub *sub = channel_ctx->peer_ctx->sub;
uint32_t i;
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
struct AttackedPeer *tmp_att_peer;
#endif /* ENABLE_MALICIOUS */
+ sub->pull_delays[sub->num_rounds - channel_ctx->peer_ctx->round_pull_req]++;
LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (sender));
- GNUNET_STATISTICS_update(stats, "# pull reply messages received", 1, GNUNET_NO);
+ if (channel_ctx->peer_ctx->sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pull reply messages received",
+ 1,
+ GNUNET_NO);
+ if (NULL != map_single_hop &&
+ GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop,
+ &channel_ctx->peer_ctx->peer_id))
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pull reply messages received (multi-hop peer)",
+ 1,
+ GNUNET_NO);
+ }
+ }
- #ifdef ENABLE_MALICIOUS
+ #if ENABLE_MALICIOUS
// We shouldn't even receive pull replies as we're not sending
if (2 == mal_type)
{
i,
GNUNET_i2s (&peers[i]));
- #ifdef ENABLE_MALICIOUS
+ #if ENABLE_MALICIOUS
if ((NULL != att_peer_set) &&
(1 == mal_type || 3 == mal_type))
{ /* Add attacked peer to local list */
}
#endif /* ENABLE_MALICIOUS */
/* Make sure we 'know' about this peer */
- (void) insert_peer (channel_ctx->peer_ctx->sub, &peers[i]);
+ (void) insert_peer (channel_ctx->peer_ctx->sub,
+ &peers[i]);
if (GNUNET_YES == check_peer_valid (channel_ctx->peer_ctx->sub->valid_peers,
&peers[i]))
{
- CustomPeerMap_put (channel_ctx->peer_ctx->sub->pull_map, &peers[i]);
+ CustomPeerMap_put (channel_ctx->peer_ctx->sub->pull_map,
+ &peers[i]);
}
else
{
schedule_operation (channel_ctx->peer_ctx,
insert_in_pull_map,
channel_ctx->peer_ctx->sub); /* cls */
- (void) issue_peer_online_check (channel_ctx->peer_ctx->sub, &peers[i]);
+ (void) issue_peer_online_check (channel_ctx->peer_ctx->sub,
+ &peers[i]);
}
}
- UNSET_PEER_FLAG (get_peer_ctx (channel_ctx->peer_ctx->sub->peer_map, sender),
+ UNSET_PEER_FLAG (get_peer_ctx (channel_ctx->peer_ctx->sub->peer_map,
+ sender),
Peers_PULL_REPLY_PENDING);
- clean_peer (channel_ctx->peer_ctx->sub, sender);
+ clean_peer (channel_ctx->peer_ctx->sub,
+ sender);
GNUNET_break_op (check_peer_known (channel_ctx->peer_ctx->sub->peer_map,
sender));
GNUNET_assert (GNUNET_NO == check_peer_flag (peer_ctx->sub->peer_map,
&peer_ctx->peer_id,
Peers_PULL_REPLY_PENDING));
- SET_PEER_FLAG (peer_ctx, Peers_PULL_REPLY_PENDING);
+ SET_PEER_FLAG (peer_ctx,
+ Peers_PULL_REPLY_PENDING);
+ peer_ctx->round_pull_req = peer_ctx->sub->num_rounds;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Going to send PULL REQUEST to peer %s.\n",
GNUNET_i2s (&peer_ctx->peer_id));
ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST);
- send_message (peer_ctx, ev, "PULL REQUEST");
- GNUNET_STATISTICS_update(stats, "# pull request send issued", 1, GNUNET_NO);
+ send_message (peer_ctx,
+ ev,
+ "PULL REQUEST");
+ if (peer_ctx->sub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pull request send issued",
+ 1,
+ GNUNET_NO);
+ if (NULL != map_single_hop &&
+ GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop,
+ &peer_ctx->peer_id))
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# pull request send issued (multi-hop peer)",
+ 1,
+ GNUNET_NO);
+ }
+ }
}
ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PUSH);
send_message (peer_ctx, ev, "PUSH");
- GNUNET_STATISTICS_update(stats, "# push send issued", 1, GNUNET_NO);
+ if (peer_ctx->sub)
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# push send issued",
+ 1,
+ GNUNET_NO);
+ if (NULL != map_single_hop &&
+ GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (map_single_hop,
+ &peer_ctx->peer_id))
+ {
+ GNUNET_STATISTICS_update (stats,
+ "# push send issued (multi-hop peer)",
+ 1,
+ GNUNET_NO);
+ }
+ }
}
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
/**
uint32_t num_mal_peers_old;
struct Sub *sub = cli_ctx->sub;
+ if (NULL == sub) sub = msub;
/* Do actual logic */
peers = (struct GNUNET_PeerIdentity *) &msg[1];
mal_type = ntohl (msg->type);
mal_peer_set);
/* Substitute do_round () with do_mal_round () */
- if (NULL != sub)
- {
- GNUNET_SCHEDULER_cancel (sub->do_round_task);
- sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, sub);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "do_round_task is NULL, probably in shutdown\n");
- }
+ GNUNET_assert (NULL != sub->do_round_task);
+ GNUNET_SCHEDULER_cancel (sub->do_round_task);
+ sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, sub);
}
else if ( (2 == mal_type) ||
&msg->attacked_peer,
sizeof (struct GNUNET_PeerIdentity));
/* Set the flag of the attacked peer to valid to avoid problems */
- if (NULL != sub &&
- GNUNET_NO == check_peer_known (sub->peer_map, &attacked_peer))
+ if (GNUNET_NO == check_peer_known (sub->peer_map, &attacked_peer))
{
(void) issue_peer_online_check (sub, &attacked_peer);
}
GNUNET_i2s (&attacked_peer));
/* Substitute do_round () with do_mal_round () */
- if (NULL != sub && NULL != sub->do_round_task)
+ if (NULL != sub->do_round_task)
{
/* Probably in shutdown */
GNUNET_SCHEDULER_cancel (sub->do_round_task);
}
#endif /* ENABLE_MALICIOUS */
+
/**
* Send out PUSHes and PULLs, possibly update #view, samplers.
*
struct GNUNET_PeerIdentity *update_peer;
struct Sub *sub = cls;
+ sub->num_rounds++;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Going to execute next round.\n");
- GNUNET_STATISTICS_update(stats, "# rounds", 1, GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_update (stats, "# rounds", 1, GNUNET_NO);
+ }
sub->do_round_task = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Printing view:\n");
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"___ new round ___");
+#endif /* TO_FILE_FULL */
view_array = View_get_as_array (sub->view);
for (i = 0; i < View_size (sub->view); i++)
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"\t%s\n", GNUNET_i2s (&view_array[i]));
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"=%s\t(do round)",
GNUNET_i2s_full (&view_array[i]));
+#endif /* TO_FILE_FULL */
}
/* Seems like recreating is the easiest way of emptying the peermap */
View_clear (sub->view);
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"--- emptied ---");
+#endif /* TO_FILE_FULL */
first_border = GNUNET_MIN (ceil (alpha * sub->view_size_est_need),
CustomPeerMap_size (sub->push_map));
1,
CustomPeerMap_get_peer_by_index (sub->push_map, permut[i]));
}
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"+%s\t(push list)",
GNUNET_i2s_full (&view_array[i]));
+#endif /* TO_FILE_FULL */
// TODO change the peer_flags accordingly
}
GNUNET_free (permut);
CustomPeerMap_get_peer_by_index (sub->pull_map,
permut[i - first_border]));
}
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"+%s\t(pull list)",
GNUNET_i2s_full (&view_array[i]));
+#endif /* TO_FILE_FULL */
// TODO change the peer_flags accordingly
}
GNUNET_free (permut);
/* Clean peers that were removed from the view */
for (i = 0; i < peers_to_clean_size; i++)
{
+#ifdef TO_FILE_FULL
to_file (sub->file_name_view_log,
"-%s",
GNUNET_i2s_full (&peers_to_clean[i]));
+#endif /* TO_FILE_FULL */
clean_peer (sub, &peers_to_clean[i]);
}
clients_notify_view_update (sub);
} else {
LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
- GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO);
- if (CustomPeerMap_size (sub->push_map) > alpha * View_size (sub->view) &&
- !(0 >= CustomPeerMap_size (sub->pull_map)))
- GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes", 1, GNUNET_NO);
- if (CustomPeerMap_size (sub->push_map) > alpha * View_size (sub->view) &&
- (0 >= CustomPeerMap_size (sub->pull_map)))
- GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes, no pull replies", 1, GNUNET_NO);
- if (0 >= CustomPeerMap_size (sub->push_map) &&
- !(0 >= CustomPeerMap_size (sub->pull_map)))
- GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes", 1, GNUNET_NO);
- if (0 >= CustomPeerMap_size (sub->push_map) &&
- (0 >= CustomPeerMap_size (sub->pull_map)))
- GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes, no pull replies", 1, GNUNET_NO);
- if (0 >= CustomPeerMap_size (sub->pull_map) &&
- CustomPeerMap_size (sub->push_map) > alpha * View_size (sub->view) &&
- 0 >= CustomPeerMap_size (sub->push_map))
- GNUNET_STATISTICS_update(stats, "# rounds blocked - no pull replies", 1, GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO);
+ if (CustomPeerMap_size (sub->push_map) > alpha * sub->view_size_est_need &&
+ !(0 >= CustomPeerMap_size (sub->pull_map)))
+ GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes", 1, GNUNET_NO);
+ if (CustomPeerMap_size (sub->push_map) > alpha * sub->view_size_est_need &&
+ (0 >= CustomPeerMap_size (sub->pull_map)))
+ GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes, no pull replies", 1, GNUNET_NO);
+ if (0 >= CustomPeerMap_size (sub->push_map) &&
+ !(0 >= CustomPeerMap_size (sub->pull_map)))
+ GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes", 1, GNUNET_NO);
+ if (0 >= CustomPeerMap_size (sub->push_map) &&
+ (0 >= CustomPeerMap_size (sub->pull_map)))
+ GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes, no pull replies", 1, GNUNET_NO);
+ if (0 >= CustomPeerMap_size (sub->pull_map) &&
+ CustomPeerMap_size (sub->push_map) > alpha * sub->view_size_est_need &&
+ 0 >= CustomPeerMap_size (sub->push_map))
+ GNUNET_STATISTICS_update(stats, "# rounds blocked - no pull replies", 1, GNUNET_NO);
+ }
}
// TODO independent of that also get some peers from CADET_get_peers()?
- GNUNET_STATISTICS_set (stats,
- "# peers in push map at end of round",
- CustomPeerMap_size (sub->push_map),
- GNUNET_NO);
- GNUNET_STATISTICS_set (stats,
- "# peers in pull map at end of round",
- CustomPeerMap_size (sub->pull_map),
- GNUNET_NO);
- GNUNET_STATISTICS_set (stats,
- "# peers in view at end of round",
- View_size (sub->view),
- GNUNET_NO);
+ if (CustomPeerMap_size (sub->push_map) < HISTOGRAM_FILE_SLOTS)
+ {
+ sub->push_recv[CustomPeerMap_size (sub->push_map)]++;
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Push map size too big for histogram (%u, %u)\n",
+ CustomPeerMap_size (sub->push_map),
+ HISTOGRAM_FILE_SLOTS);
+ }
+ // FIXME check bounds of histogram
+ sub->push_delta[(int32_t) (CustomPeerMap_size (sub->push_map) -
+ (alpha * sub->view_size_est_need)) +
+ (HISTOGRAM_FILE_SLOTS/2)]++;
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "# peers in push map at end of round",
+ CustomPeerMap_size (sub->push_map),
+ GNUNET_NO);
+ GNUNET_STATISTICS_set (stats,
+ "# peers in pull map at end of round",
+ CustomPeerMap_size (sub->pull_map),
+ GNUNET_NO);
+ GNUNET_STATISTICS_set (stats,
+ "# peers in view at end of round",
+ View_size (sub->view),
+ GNUNET_NO);
+ GNUNET_STATISTICS_set (stats,
+ "# expected pushes",
+ alpha * sub->view_size_est_need,
+ GNUNET_NO);
+ GNUNET_STATISTICS_set (stats,
+ "delta expected - received pushes",
+ CustomPeerMap_size (sub->push_map) - (alpha * sub->view_size_est_need),
+ GNUNET_NO);
+ }
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (sub->view%u) = %.2f)\n",
CustomPeerMap_clear (sub->push_map);
CustomPeerMap_clear (sub->pull_map);
- GNUNET_STATISTICS_set (stats,
- "view size",
- View_size(sub->view),
- GNUNET_NO);
+ if (sub == msub)
+ {
+ GNUNET_STATISTICS_set (stats,
+ "view size",
+ View_size(sub->view),
+ GNUNET_NO);
+ }
struct GNUNET_TIME_Relative time_next_round;
GNUNET_PEERINFO_disconnect (peerinfo_handle);
peerinfo_handle = NULL;
GNUNET_NSE_disconnect (nse);
+ if (NULL != map_single_hop)
+ {
+ /* core_init was called - core was initialised */
+ /* disconnect first, so no callback tries to access missing peermap */
+ GNUNET_CORE_disconnect (core_handle);
+ core_handle = NULL;
+ GNUNET_CONTAINER_multipeermap_destroy (map_single_hop);
+ map_single_hop = NULL;
+ }
if (NULL != stats)
{
}
GNUNET_CADET_disconnect (cadet_handle);
cadet_handle = NULL;
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
struct AttackedPeer *tmp_att_peer;
GNUNET_array_grow (mal_peers,
num_mal_peers,
GNUNET_free (tmp_att_peer);
}
#endif /* ENABLE_MALICIOUS */
+ close_all_files();
}
const struct GNUNET_CONFIGURATION_Handle *c,
struct GNUNET_SERVICE_Handle *service)
{
- char *fn_valid_peers;
struct GNUNET_TIME_Relative round_interval;
long long unsigned int sampler_size;
char hash_port_string[] = GNUNET_APPLICATION_PORT_RPS;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"STARTING SERVICE (rps) for peer [%s]\n",
GNUNET_i2s (&own_identity));
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Malicious execution compiled in.\n");
#endif /* ENABLE_MALICIOUS */
return;
}
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- "rps",
- "FILENAME_VALID_PEERS",
- &fn_valid_peers))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "rps",
- "FILENAME_VALID_PEERS");
- }
-
cadet_handle = GNUNET_CADET_connect (cfg);
GNUNET_assert (NULL != cadet_handle);
+ core_handle = GNUNET_CORE_connect (cfg,
+ NULL, /* cls */
+ core_init, /* init */
+ core_connects, /* connects */
+ core_disconnects, /* disconnects */
+ NULL); /* handlers */
+ GNUNET_assert (NULL != core_handle);
alpha = 0.45;
GNUNET_MESSAGE_TYPE_RPS_CS_SEED,
struct GNUNET_RPS_CS_SeedMessage,
NULL),
-#ifdef ENABLE_MALICIOUS
+#if ENABLE_MALICIOUS
GNUNET_MQ_hd_var_size (client_act_malicious,
GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS,
struct GNUNET_RPS_CS_ActMaliciousMessage,