rps: keep track of valid peers in peermap
authorJulius Bünger <buenger@mytum.de>
Thu, 12 May 2016 08:58:24 +0000 (08:58 +0000)
committerJulius Bünger <buenger@mytum.de>
Thu, 12 May 2016 08:58:24 +0000 (08:58 +0000)
src/rps/gnunet-service-rps.c
src/rps/gnunet-service-rps_peers.c
src/rps/gnunet-service-rps_peers.h
src/rps/test_service_rps_peers.c

index 8f25b269daa4c9b31b1f9bf95243f7e5afe423ef..8113e40b6e9e4c86cc86c3357cd3b2232ce4bf8c 100644 (file)
@@ -1385,7 +1385,7 @@ handle_peer_pull_reply (void *cls,
       /* Make sure we 'know' about this peer */
       (void) Peers_insert_peer_check_liveliness (&peers[i]);
 
-      if (GNUNET_YES == Peers_check_peer_flag (&peers[i], Peers_VALID))
+      if (GNUNET_YES == Peers_check_peer_valid (&peers[i]))
       {
         CustomPeerMap_put (pull_map, &peers[i]);
       }
@@ -1694,7 +1694,7 @@ do_mal_round (void *cls)
      * That is one push per round as it will ignore more.
      */
     Peers_insert_peer_check_liveliness (&attacked_peer);
-    if (GNUNET_YES == Peers_check_peer_flag (&attacked_peer, Peers_VALID))
+    if (GNUNET_YES == Peers_check_peer_valid (&attacked_peer))
       send_push (&attacked_peer);
   }
 
@@ -1706,7 +1706,7 @@ do_mal_round (void *cls)
     if (GNUNET_YES == Peers_check_peer_known (&attacked_peer))
     {
       Peers_insert_peer_check_liveliness (&attacked_peer);
-      if (GNUNET_YES == Peers_check_peer_flag (&attacked_peer, Peers_VALID))
+      if (GNUNET_YES == Peers_check_peer_valid (&attacked_peer))
       {
         LOG (GNUNET_ERROR_TYPE_DEBUG,
             "Goding to send push to attacked peer (%s)\n",
@@ -2298,6 +2298,7 @@ run (void *cls,
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
   GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, NULL);
   // TODO send push/pull to each of those peers?
+  // TODO read stored valid peers from last run
 
   peerinfo_notify_handle = GNUNET_PEERINFO_notify (cfg,
                                                    GNUNET_NO,
index 33430e51f7e0e7cd9608b977bd29166e9dc66554..a6cd1b83967ae5ef93b28f771060ea7706802b54 100644 (file)
@@ -203,6 +203,16 @@ struct PeerContext
    */
 };
 
+/**
+ * @brief Hashmap of valid peers.
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
+
+/**
+ * @brief Maximum number of valid peers to keep.
+ * TODO read from config
+ */
+static uint32_t num_valid_peers_max = UINT32_MAX;
 
 /**
  * Set of all peers to keep track of them.
@@ -316,11 +326,113 @@ Peers_check_connected (const struct GNUNET_PeerIdentity *peer)
   return GNUNET_YES;
 }
 
+/**
+ * @brief The closure to #get_rand_peer_iterator.
+ */
+struct GetRandPeerIteratorCls
+{
+  /**
+   * @brief The index of the peer to return.
+   * Will be decreased until 0.
+   * Then current peer is returned.
+   */
+  uint32_t index;
+
+  /**
+   * @brief Pointer to peer to return.
+   */
+  const struct GNUNET_PeerIdentity *peer;
+};
+
+/**
+ * @brief Iterator function for #get_random_peer_from_peermap.
+ *
+ * Implements #GNUNET_CONTAINER_PeerMapIterator.
+ * Decreases the index until the index is null.
+ * Then returns the current peer.
+ *
+ * @param cls the #GetRandPeerIteratorCls containing index and peer
+ * @param peer current peer
+ * @param value unused
+ *
+ * @return  #GNUNET_YES if we should continue to
+ *          iterate,
+ *          #GNUNET_NO if not.
+ */
+static int
+get_rand_peer_iterator (void *cls,
+                        const struct GNUNET_PeerIdentity *peer,
+                        void *value)
+{
+  struct GetRandPeerIteratorCls *iterator_cls = cls;
+  if (0 >= iterator_cls->index)
+  {
+    iterator_cls->peer = peer;
+    return GNUNET_NO;
+  }
+  iterator_cls->index--;
+  return GNUNET_YES;
+}
+
+/**
+ * @brief Get a random peer from @a peer_map
+ *
+ * @param peer_map the peer_map to get the peer from
+ *
+ * @return a random peer
+ */
+static const struct GNUNET_PeerIdentity *
+get_random_peer_from_peermap (const struct
+                              GNUNET_CONTAINER_MultiPeerMap *peer_map)
+{
+  uint32_t rand_index;
+  struct GetRandPeerIteratorCls *iterator_cls;
+  const struct GNUNET_PeerIdentity *ret;
+
+  iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
+  iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+      GNUNET_CONTAINER_multipeermap_size (peer_map));
+  (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
+                                                get_rand_peer_iterator,
+                                                iterator_cls);
+  ret = iterator_cls->peer;
+  GNUNET_free (iterator_cls);
+  return ret;
+}
+
+/**
+ * @brief Add a given @a peer to valid peers.
+ *
+ * If valid peers are already #num_valid_peers_max, delete a peer previously.
+ *
+ * @param peer the peer that is added to the valid peers.
+ *
+ * @return #GNUNET_YES if no other peer had to be removed
+ *         #GNUNET_NO  otherwise
+ */
+static int
+add_valid_peer (const struct GNUNET_PeerIdentity *peer)
+{
+  const struct GNUNET_PeerIdentity *rand_peer;
+  int ret;
+
+  ret = GNUNET_YES;
+  while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
+  {
+    rand_peer = get_random_peer_from_peermap (valid_peers);
+    GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
+    ret = GNUNET_NO;
+  }
+  (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
+      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  return ret;
+}
+
 /**
  * @brief Set the peer flag to living and
  *        call the pending operations on this peer.
  *
- * Also sets the #Peers_VALID flag
+ * Also adds peer to #valid_peers.
  *
  * @param peer_ctx the #PeerContext of the peer to set live
  */
@@ -338,7 +450,7 @@ set_peer_live (struct PeerContext *peer_ctx)
   }
 
   peer = &peer_ctx->peer_id;
-  set_peer_flag (peer_ctx, Peers_VALID);
+  (void) add_valid_peer (peer);
   set_peer_flag (peer_ctx, Peers_ONLINE);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Peer %s is live and valid\n",
@@ -606,8 +718,11 @@ Peers_initialise (struct GNUNET_CADET_Handle *cadet_h,
   cadet_handle = cadet_h;
   own_identity = own_id;
   peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
+  valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
 }
 
+// TODO read stored valid peers
+
 /**
  * @brief Delete storage of peers that was created with #Peers_initialise ()
  */
@@ -623,8 +738,11 @@ Peers_terminate ()
         "Iteration destroying peers was aborted.\n");
   }
   GNUNET_CONTAINER_multipeermap_destroy (peer_map);
+  GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
 }
 
+// TODO store valid peers
+
 /**
  * @brief Add peer to known peers.
  *
@@ -672,7 +790,7 @@ Peers_insert_peer_check_liveliness (const struct GNUNET_PeerIdentity *peer)
     return ret;
   }
   peer_ctx = get_peer_ctx (peer);
-  if (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_VALID))
+  if (GNUNET_NO == Peers_check_peer_valid (peer))
   {
     check_peer_live (peer_ctx);
   }
@@ -875,6 +993,8 @@ Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags
 /**
  * @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
@@ -886,6 +1006,22 @@ 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
  *
index 06e6fa89e9d23be2c448a81204cdead10fe9b6d4..79db8185bbf5c12bd2edd0132898b9b7bba717bb 100644 (file)
@@ -42,11 +42,6 @@ enum Peers_PeerFlags
   /* IN_OWN_SAMPLER_LIST  = 0x04, unneeded? */
   /* IN_OWN_GOSSIP_LIST   = 0x08, unneeded? */
 
-  /**
-   * We set this bit when we can be sure the other peer is/was live.
-   */
-  Peers_VALID                = 0x10,
-
   /**
    * We set this bit when we know the peer is online.
    */
@@ -236,6 +231,8 @@ Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags
 /**
  * @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
@@ -244,6 +241,19 @@ Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags
 int
 Peers_check_peer_known (const struct GNUNET_PeerIdentity *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);
+
 /**
  * @brief Indicate that we want to send to the other peer
  *
index f5191faccfbea3ae2e635248c0a23e797baa9a79..264a63e414e8a78da8ed6a89c4af87d297e5e495 100644 (file)
@@ -93,30 +93,15 @@ check ()
   Peers_insert_peer (&k1);
 
   CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_PULL_REPLY_PENDING));
-  CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_VALID));
   CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_ONLINE));
   CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
 
-  Peers_set_peer_flag (&k1, Peers_VALID);
-  CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_VALID));
   CHECK (GNUNET_NO  == Peers_check_peer_flag (&k1, Peers_ONLINE));
-  Peers_unset_peer_flag (&k1, Peers_VALID);
-  CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_VALID));
 
-  Peers_set_peer_flag (&k1, Peers_VALID);
   Peers_set_peer_flag (&k1, Peers_ONLINE);
-  CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_VALID));
   CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_ONLINE));
-  CHECK (GNUNET_YES == Peers_check_peer_flag (&k1,
-                                              Peers_ONLINE | Peers_VALID));
   CHECK (GNUNET_NO  == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
-  Peers_unset_peer_flag (&k1, Peers_VALID);
-  CHECK (GNUNET_NO  == Peers_check_peer_flag (&k1, Peers_VALID));
   CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_ONLINE));
-  CHECK (GNUNET_YES == Peers_check_peer_flag (&k1,
-                                              Peers_ONLINE | Peers_VALID));
-  CHECK (GNUNET_NO  == Peers_check_peer_flag (&k1,
-                                              Peers_ONLINE & Peers_VALID));
   CHECK (GNUNET_NO  == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
 
   /* Check send intention */