+ GNUNET_free (peer_ctx->send_channel_flags);
+ GNUNET_free (peer_ctx->recv_channel_flags);
+
+ if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
+ }
+ GNUNET_free (peer_ctx);
+ return GNUNET_YES;
+}
+
+
+/**
+ * @brief set flags on a given peer.
+ *
+ * @param peer the peer to set flags on
+ * @param flags the flags
+ */
+void
+Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
+{
+ struct PeerContext *peer_ctx;
+
+ peer_ctx = get_peer_ctx (peer);
+ set_peer_flag (peer_ctx, flags);
+}
+
+
+/**
+ * @brief unset flags on a given peer.
+ *
+ * @param peer the peer to unset flags on
+ * @param flags the flags
+ */
+void
+Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
+{
+ struct PeerContext *peer_ctx;
+
+ peer_ctx = get_peer_ctx (peer);
+ unset_peer_flag (peer_ctx, flags);
+}
+
+
+/**
+ * @brief Check whether flags on a peer are set.
+ *
+ * @param peer the peer to check the flag of
+ * @param flags the flags to check
+ *
+ * @return #GNUNET_SYSERR if peer is not known
+ * #GNUNET_YES if all given flags are set
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
+{
+ struct PeerContext *peer_ctx;
+
+ if (GNUNET_NO == Peers_check_peer_known (peer))
+ {
+ return GNUNET_SYSERR;
+ }
+ peer_ctx = get_peer_ctx (peer);
+ return check_peer_flag_set (peer_ctx, flags);
+}
+
+
+/**
+ * @brief set flags on a given channel.
+ *
+ * @param channel the channel to set flags on
+ * @param flags the flags
+ */
+void
+Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
+{
+ set_channel_flag (channel_flags, flags);
+}
+
+
+/**
+ * @brief unset flags on a given channel.
+ *
+ * @param channel the channel to unset flags on
+ * @param flags the flags
+ */
+void
+Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
+{
+ unset_channel_flag (channel_flags, flags);
+}
+
+
+/**
+ * @brief Check whether flags on a channel are set.
+ *
+ * @param channel the channel to check the flag of
+ * @param flags the flags to check
+ *
+ * @return #GNUNET_YES if all given flags are set
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
+{
+ return check_channel_flag_set (channel_flags, flags);
+}
+
+/**
+ * @brief Get the flags for the channel in @a role for @a peer.
+ *
+ * @param peer Peer to get the channel flags for.
+ * @param role Role of channel to get flags for
+ *
+ * @return The flags.
+ */
+uint32_t *
+Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
+ enum Peers_ChannelRole role)
+{
+ const struct PeerContext *peer_ctx;
+
+ peer_ctx = get_peer_ctx (peer);
+ if (Peers_CHANNEL_ROLE_SENDING == role)
+ {
+ return peer_ctx->send_channel_flags;
+ }
+ else if (Peers_CHANNEL_ROLE_RECEIVING == role)
+ {
+ return peer_ctx->recv_channel_flags;
+ }
+ else
+ {
+ GNUNET_assert (0);
+ }
+}
+
+/**
+ * @brief Check whether we have information about the given peer.
+ *
+ * FIXME probably deprecated. Make this the new _online.
+ *
+ * @param peer peer in question
+ *
+ * @return #GNUNET_YES if peer is known
+ * #GNUNET_NO if peer is not knwon
+ */
+int
+Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
+{
+ return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
+}
+
+
+/**
+ * @brief Check whether @a peer is actually a peer.
+ *
+ * A valid peer is a peer that we know exists eg. we were connected to once.
+ *
+ * @param peer peer in question
+ *
+ * @return #GNUNET_YES if peer is valid
+ * #GNUNET_NO if peer is not valid
+ */
+int
+Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer)
+{
+ return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
+}
+
+
+/**
+ * @brief Indicate that we want to send to the other peer
+ *
+ * This establishes a sending channel
+ *
+ * @param peer the peer to establish channel to
+ */
+void
+Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
+{
+ GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
+ (void) get_channel (peer);
+}
+
+
+/**
+ * @brief Check whether other peer has the intention to send/opened channel
+ * towars us
+ *
+ * @param peer the peer in question
+ *
+ * @return #GNUNET_YES if peer has the intention to send
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
+{
+ const struct PeerContext *peer_ctx;
+
+ peer_ctx = get_peer_ctx (peer);
+ if (NULL != peer_ctx->recv_channel)
+ {
+ return GNUNET_YES;
+ }
+ return GNUNET_NO;
+}
+
+
+/**
+ * Handle the channel a peer opens to us.
+ *
+ * @param cls The closure
+ * @param channel The channel the peer wants to establish
+ * @param initiator The peer's peer ID
+ *
+ * @return initial channel context for the channel
+ * (can be NULL -- that's not an error)
+ */
+void *
+Peers_handle_inbound_channel (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ const struct GNUNET_PeerIdentity *initiator)
+{
+ struct PeerContext *peer_ctx;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "New channel was established to us (Peer %s).\n",
+ GNUNET_i2s (initiator));
+ GNUNET_assert (NULL != channel); /* according to cadet API */
+ /* Make sure we 'know' about this peer */
+ peer_ctx = create_or_get_peer_ctx (initiator);
+ set_peer_live (peer_ctx);
+ /* We only accept one incoming channel per peer */
+ if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
+ {
+ set_channel_flag (peer_ctx->recv_channel_flags,
+ Peers_CHANNEL_ESTABLISHED_TWICE);
+ GNUNET_CADET_channel_destroy (channel);
+ /* return the channel context */
+ return &peer_ctx->peer_id;
+ }
+ peer_ctx->recv_channel = channel;
+ return &peer_ctx->peer_id;
+}
+
+
+/**
+ * @brief Check whether a sending channel towards the given peer exists
+ *
+ * @param peer the peer to check for
+ *
+ * @return #GNUNET_YES if a sending channel towards that peer exists
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
+{
+ struct PeerContext *peer_ctx;
+
+ if (GNUNET_NO == Peers_check_peer_known (peer))
+ { /* If no such peer exists, there is no channel */
+ return GNUNET_NO;
+ }
+ peer_ctx = get_peer_ctx (peer);
+ if (NULL == peer_ctx->send_channel)
+ {
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
+/**
+ * @brief check whether the given channel is the sending channel of the given
+ * peer
+ *
+ * @param peer the peer in question
+ * @param channel the channel to check for
+ * @param role either #Peers_CHANNEL_ROLE_SENDING, or
+ * #Peers_CHANNEL_ROLE_RECEIVING
+ *
+ * @return #GNUNET_YES if the given chennel is the sending channel of the peer
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_CADET_Channel *channel,
+ enum Peers_ChannelRole role)
+{
+ const struct PeerContext *peer_ctx;
+
+ if (GNUNET_NO == Peers_check_peer_known (peer))
+ {
+ return GNUNET_NO;
+ }
+ peer_ctx = get_peer_ctx (peer);
+ if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
+ (channel == peer_ctx->send_channel) )
+ {
+ return GNUNET_YES;
+ }
+ if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
+ (channel == peer_ctx->recv_channel) )
+ {
+ return GNUNET_YES;
+ }
+ return GNUNET_NO;
+}
+
+
+/**
+ * @brief Destroy the send channel of a peer e.g. stop indicating a sending
+ * intention to another peer
+ *
+ * If there is also no channel to receive messages from that peer, remove it
+ * from the peermap.
+ * TODO really?
+ *
+ * @peer the peer identity of the peer whose sending channel to destroy
+ * @return #GNUNET_YES if channel was destroyed
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
+{
+ struct PeerContext *peer_ctx;
+
+ if (GNUNET_NO == Peers_check_peer_known (peer))
+ {
+ return GNUNET_NO;
+ }
+ peer_ctx = get_peer_ctx (peer);
+ if (NULL != peer_ctx->send_channel)
+ {
+ set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
+ GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
+ peer_ctx->send_channel = NULL;
+ (void) Peers_check_connected (peer);
+ return GNUNET_YES;
+ }
+ return GNUNET_NO;
+}
+
+/**
+ * This is called when a channel is destroyed.
+ *
+ * @param cls The closure
+ * @param channel The channel being closed
+ * @param channel_ctx The context associated with this channel
+ */
+void
+Peers_cleanup_destroyed_channel (void *cls,
+ const struct GNUNET_CADET_Channel *channel)
+{
+ struct GNUNET_PeerIdentity *peer = cls;
+ struct PeerContext *peer_ctx;
+
+ if (GNUNET_NO == Peers_check_peer_known (peer))
+ {/* We don't want to implicitly create a context that we're about to kill */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "channel (%s) without associated context was destroyed\n",
+ GNUNET_i2s (peer));
+ return;
+ }
+ peer_ctx = get_peer_ctx (peer);
+
+ /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
+ * flag will be set. In this case simply make sure that the channels are
+ * cleaned. */
+ /* FIXME This distinction seems to be redundant */
+ if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
+ {/* We initiatad the destruction of this particular peer */
+ if (channel == peer_ctx->send_channel)
+ peer_ctx->send_channel = NULL;
+ else if (channel == peer_ctx->recv_channel)
+ peer_ctx->recv_channel = NULL;
+
+ if (NULL != peer_ctx->send_channel)
+ {
+ GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
+ peer_ctx->send_channel = NULL;
+ }
+ if (NULL != peer_ctx->recv_channel)
+ {
+ GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
+ peer_ctx->recv_channel = NULL;
+ }
+ /* Set the #Peers_ONLINE flag accordingly */
+ (void) Peers_check_connected (peer);
+ return;
+ }
+
+ else
+ { /* We did not initiate the destruction of this peer */
+ if (channel == peer_ctx->send_channel)
+ { /* Something (but us) killd the channel - clean up peer */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "send channel (%s) was destroyed - cleaning up\n",
+ GNUNET_i2s (peer));
+ peer_ctx->send_channel = NULL;
+ }
+ else if (channel == peer_ctx->recv_channel)
+ { /* Other peer doesn't want to send us messages anymore */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Peer %s destroyed recv channel - cleaning up channel\n",
+ GNUNET_i2s (peer));
+ peer_ctx->recv_channel = NULL;
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "unknown channel (%s) was destroyed\n",
+ GNUNET_i2s (peer));
+ }
+ }
+ (void) Peers_check_connected (peer);
+}
+
+/**
+ * @brief Send a message to another peer.
+ *
+ * Keeps track about pending messages so they can be properly removed when the
+ * peer is destroyed.
+ *
+ * @param peer receeiver of the message
+ * @param ev envelope of the message
+ * @param type type of the message
+ */
+void
+Peers_send_message (const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_MQ_Envelope *ev,
+ const char *type)
+{
+ struct PendingMessage *pending_msg;
+ struct GNUNET_MQ_Handle *mq;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending message to %s of type %s\n",
+ GNUNET_i2s (peer),
+ type);
+ pending_msg = insert_pending_message (peer, ev, type);
+ mq = get_mq (peer);
+ GNUNET_MQ_notify_sent (ev,
+ mq_notify_sent_cb,
+ pending_msg);
+ GNUNET_MQ_send (mq, ev);
+}
+
+/**
+ * @brief Schedule a operation on given peer
+ *
+ * Avoids scheduling an operation twice.
+ *
+ * @param peer the peer we want to schedule the operation for once it gets live
+ *
+ * @return #GNUNET_YES if the operation was scheduled
+ * #GNUNET_NO otherwise
+ */
+int
+Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
+ const PeerOp peer_op)
+{
+ struct PeerPendingOp pending_op;
+ struct PeerContext *peer_ctx;
+
+ if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
+ {
+ return GNUNET_NO;
+ }
+ GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
+
+ //TODO if LIVE/ONLINE execute immediately
+
+ if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
+ {
+ peer_ctx = get_peer_ctx (peer);
+ pending_op.op = peer_op;
+ pending_op.op_cls = NULL;
+ GNUNET_array_append (peer_ctx->pending_ops,
+ peer_ctx->num_pending_ops,
+ pending_op);
+ return GNUNET_YES;
+ }
+ return GNUNET_NO;
+}
+
+/**
+ * @brief Get the recv_channel of @a peer.
+ * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
+ * messages.
+ *
+ * @param peer The peer to get the recv_channel from.
+ *
+ * @return The recv_channel.
+ */
+struct GNUNET_CADET_Channel *
+Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer)
+{
+ struct PeerContext *peer_ctx;
+
+ GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
+ peer_ctx = get_peer_ctx (peer);
+ return peer_ctx->recv_channel;
+}
+/***********************************************************************
+ * /Old gnunet-service-rps_peers.c
+***********************************************************************/
+
+
+/***********************************************************************
+ * Housekeeping with clients
+***********************************************************************/
+
+/**
+ * Closure used to pass the client and the id to the callback
+ * that replies to a client's request
+ */
+struct ReplyCls
+{
+ /**
+ * DLL
+ */
+ struct ReplyCls *next;
+ struct ReplyCls *prev;
+
+ /**
+ * The identifier of the request
+ */
+ uint32_t id;
+
+ /**
+ * The handle to the request
+ */
+ struct RPS_SamplerRequestHandle *req_handle;
+
+ /**
+ * The client handle to send the reply to
+ */
+ struct ClientContext *cli_ctx;
+};
+
+
+/**
+ * Struct used to store the context of a connected client.
+ */
+struct ClientContext
+{
+ /**
+ * DLL
+ */
+ struct ClientContext *next;
+ struct ClientContext *prev;
+
+ /**
+ * The message queue to communicate with the client.
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * DLL with handles to single requests from the client
+ */
+ struct ReplyCls *rep_cls_head;
+ struct ReplyCls *rep_cls_tail;
+
+ /**
+ * The client handle to send the reply to
+ */
+ struct GNUNET_SERVICE_Client *client;
+};
+
+/**
+ * DLL with all clients currently connected to us
+ */
+struct ClientContext *cli_ctx_head;
+struct ClientContext *cli_ctx_tail;
+
+/***********************************************************************
+ * /Housekeeping with clients
+***********************************************************************/
+
+
+
+
+
+/***********************************************************************
+ * Globals
+***********************************************************************/
+
+/**
+ * Sampler used for the Brahms protocol itself.
+ */
+static struct RPS_Sampler *prot_sampler;
+
+/**
+ * Sampler used for the clients.
+ */
+static struct RPS_Sampler *client_sampler;
+
+/**
+ * Name to log view to
+ */
+static char *file_name_view_log;
+
+/**
+ * The size of sampler we need to be able to satisfy the client's need
+ * of random peers.
+ */
+static unsigned int sampler_size_client_need;
+
+/**
+ * The size of sampler we need to be able to satisfy the Brahms protocol's
+ * need of random peers.
+ *
+ * This is one minimum size the sampler grows to.
+ */
+static unsigned int sampler_size_est_need;
+
+/**
+ * Percentage of total peer number in the view
+ * to send random PUSHes to
+ */
+static float alpha;
+
+/**
+ * Percentage of total peer number in the view
+ * to send random PULLs to
+ */
+static float beta;
+
+/**
+ * Identifier for the main task that runs periodically.
+ */
+static struct GNUNET_SCHEDULER_Task *do_round_task;
+
+/**
+ * Time inverval the do_round task runs in.
+ */
+static struct GNUNET_TIME_Relative round_interval;
+
+/**
+ * List to store peers received through pushes temporary.
+ */
+static struct CustomPeerMap *push_map;
+
+/**
+ * List to store peers received through pulls temporary.
+ */
+static struct CustomPeerMap *pull_map;
+
+/**
+ * Handler to NSE.
+ */
+static struct GNUNET_NSE_Handle *nse;
+
+/**
+ * Handler to CADET.
+ */
+static struct GNUNET_CADET_Handle *cadet_handle;
+
+/**
+ * @brief Port to communicate to other peers.
+ */
+static struct GNUNET_CADET_Port *cadet_port;
+
+/**
+ * Handler to PEERINFO.
+ */
+static struct GNUNET_PEERINFO_Handle *peerinfo_handle;
+
+/**
+ * Handle for cancellation of iteration over peers.
+ */
+static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify_handle;
+
+/**
+ * Request counter.
+ *
+ * Counts how many requets clients already issued.
+ * Only needed in the beginning to check how many of the 64 deltas
+ * we already have
+ */
+static unsigned int req_counter;
+
+/**
+ * Time of the last request we received.
+ *
+ * Used to compute the expected request rate.
+ */
+static struct GNUNET_TIME_Absolute last_request;
+
+/**
+ * Size of #request_deltas.
+ */
+#define REQUEST_DELTAS_SIZE 64
+static unsigned int request_deltas_size = REQUEST_DELTAS_SIZE;
+
+/**
+ * Last 64 deltas between requests
+ */
+static struct GNUNET_TIME_Relative request_deltas[REQUEST_DELTAS_SIZE];
+
+/**
+ * The prediction of the rate of requests
+ */
+static struct GNUNET_TIME_Relative request_rate;
+
+
+#ifdef ENABLE_MALICIOUS
+/**
+ * Type of malicious peer
+ *
+ * 0 Don't act malicious at all - Default
+ * 1 Try to maximise representation
+ * 2 Try to partition the network
+ * 3 Combined attack
+ */
+static uint32_t mal_type;
+
+/**
+ * Other malicious peers
+ */
+static struct GNUNET_PeerIdentity *mal_peers;
+
+/**
+ * Hashmap of malicious peers used as set.
+ * Used to more efficiently check whether we know that peer.
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *mal_peer_set;
+
+/**
+ * Number of other malicious peers
+ */
+static uint32_t num_mal_peers;
+
+
+/**
+ * If type is 2 This struct is used to store the attacked peers in a DLL
+ */
+struct AttackedPeer
+{
+ /**
+ * DLL
+ */
+ struct AttackedPeer *next;
+ struct AttackedPeer *prev;
+
+ /**
+ * PeerID
+ */
+ struct GNUNET_PeerIdentity peer_id;
+};
+
+/**
+ * If type is 2 this is the DLL of attacked peers
+ */
+static struct AttackedPeer *att_peers_head;
+static struct AttackedPeer *att_peers_tail;
+
+/**
+ * This index is used to point to an attacked peer to
+ * implement the round-robin-ish way to select attacked peers.
+ */
+static struct AttackedPeer *att_peer_index;
+
+/**
+ * Hashmap of attacked peers used as set.
+ * Used to more efficiently check whether we know that peer.
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *att_peer_set;