Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / rps / gnunet-service-rps.c
index eb538e9b5e1aa7b0ba1801b9ae623d03199c39c3..adcfe7d02fa6e539f9911d735f111e64ab1551a4 100644 (file)
@@ -95,7 +95,7 @@ struct ReplyCls
   /**
    * The client handle to send the reply to
    */
-  struct GNUNET_SERVER_Client *client;
+  struct ClientContext *cli_ctx;
 };
 
 
@@ -120,6 +120,11 @@ struct ClientContext
    */
   struct ReplyCls *rep_cls_head;
   struct ReplyCls *rep_cls_tail;
+
+  /**
+   * The client handle to send the reply to
+   */
+  struct GNUNET_SERVICE_Client *client;
 };
 
 /**
@@ -394,7 +399,7 @@ rem_from_list (struct GNUNET_PeerIdentity **peer_list,
     {
       if (i < *list_size -1)
       { /* Not at the last entry -- shift peers left */
-        GNUNET_memcpy (&tmp[i], &tmp[i +1],
+        memmove (&tmp[i], &tmp[i +1],
                 ((*list_size) - i -1) * sizeof (struct GNUNET_PeerIdentity));
       }
       /* Remove last entry (should be now useless PeerID) */
@@ -556,7 +561,7 @@ est_request_rate()
   if ( 1 < req_counter)
   {
     /* Shift last request deltas to the right */
-    GNUNET_memcpy (&request_deltas[1],
+    memmove (&request_deltas[1],
         request_deltas,
         (req_counter - 1) * sizeof (struct GNUNET_TIME_Relative));
 
@@ -771,7 +776,7 @@ check_sending_channel_needed (const struct GNUNET_PeerIdentity *peer)
 static void
 remove_peer (const struct GNUNET_PeerIdentity *peer)
 {
-  View_remove_peer (peer);
+  (void) View_remove_peer (peer);
   CustomPeerMap_remove_peer (pull_map, peer);
   CustomPeerMap_remove_peer (push_map, peer);
   RPS_sampler_reinitialise_by_value (prot_sampler, peer);
@@ -792,11 +797,14 @@ clean_peer (const struct GNUNET_PeerIdentity *peer)
 {
   if (GNUNET_NO == check_sending_channel_needed (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))
-      Peers_destroy_sending_channel (peer);
+      (void) Peers_destroy_sending_channel (peer);
     #else /* ENABLE_MALICIOUS */
-    Peers_destroy_sending_channel (peer);
+    (void) Peers_destroy_sending_channel (peer);
     #endif /* ENABLE_MALICIOUS */
   }
 
@@ -805,12 +813,15 @@ clean_peer (const struct GNUNET_PeerIdentity *peer)
        (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
        (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
        (0 == RPS_sampler_count_id (prot_sampler,   peer)) &&
-       (0 == RPS_sampler_count_id (client_sampler, peer)) )
-  { /* We can safely remov this peer */
+       (0 == RPS_sampler_count_id (client_sampler, peer)) &&
+       (GNUNET_NO != Peers_check_removable (peer)) )
+  { /* We can safely remove this peer */
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Going to remove peer %s\n",
+        GNUNET_i2s (peer));
     remove_peer (peer);
     return;
   }
-  Peers_clean_peer (peer);
 }
 
 /**
@@ -818,6 +829,8 @@ clean_peer (const struct GNUNET_PeerIdentity *peer)
  *
  * Removes peer completely from our knowledge if the send_channel was destroyed
  * Otherwise simply delete the recv_channel
+ * Also check if the knowledge about this peer is still needed.
+ * If not, remove this peer from our knowledge.
  *
  * @param cls The closure
  * @param channel The channel being closed
@@ -911,9 +924,12 @@ destroy_reply_cls (struct ReplyCls *rep_cls)
 {
   struct ClientContext *cli_ctx;
 
-  cli_ctx = GNUNET_SERVER_client_get_user_context (rep_cls->client,
-                                                   struct ClientContext);
+  cli_ctx = rep_cls->cli_ctx;
   GNUNET_assert (NULL != cli_ctx);
+  if (NULL != rep_cls->req_handle)
+  {
+    RPS_sampler_request_cancel (rep_cls->req_handle);
+  }
   GNUNET_CONTAINER_DLL_remove (cli_ctx->rep_cls_head,
                                cli_ctx->rep_cls_tail,
                                rep_cls);
@@ -925,10 +941,6 @@ static void
 destroy_cli_ctx (struct ClientContext *cli_ctx)
 {
   GNUNET_assert (NULL != cli_ctx);
-  if (NULL != cli_ctx->mq)
-  {
-    GNUNET_MQ_destroy (cli_ctx->mq);
-  }
   if (NULL != cli_ctx->rep_cls_head)
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -989,10 +1001,10 @@ client_respond (void *cls,
                 struct GNUNET_PeerIdentity *peer_ids,
                 uint32_t num_peers)
 {
+  struct ReplyCls *reply_cls = cls;
   uint32_t i;
   struct GNUNET_MQ_Envelope *ev;
   struct GNUNET_RPS_CS_ReplyMessage *out_msg;
-  struct ReplyCls *reply_cls = (struct ReplyCls *) cls;
   uint32_t size_needed;
   struct ClientContext *cli_ctx;
 
@@ -1024,9 +1036,9 @@ client_respond (void *cls,
           num_peers * sizeof (struct GNUNET_PeerIdentity));
   GNUNET_free (peer_ids);
 
-  cli_ctx = GNUNET_SERVER_client_get_user_context (reply_cls->client,
-                                                   struct ClientContext);
+  cli_ctx = reply_cls->cli_ctx;
   GNUNET_assert (NULL != cli_ctx);
+  reply_cls->req_handle = NULL;
   destroy_reply_cls (reply_cls);
   GNUNET_MQ_send (cli_ctx->mq, ev);
 }
@@ -1041,17 +1053,13 @@ client_respond (void *cls,
  */
 static void
 handle_client_request (void *cls,
-                       struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
+                       const struct GNUNET_RPS_CS_RequestMessage *msg)
 {
-  struct GNUNET_RPS_CS_RequestMessage *msg;
+  struct ClientContext *cli_ctx = cls;
   uint32_t num_peers;
   uint32_t size_needed;
   struct ReplyCls *reply_cls;
   uint32_t i;
-  struct ClientContext *cli_ctx;
-
-  msg = (struct GNUNET_RPS_CS_RequestMessage *) message;
 
   num_peers = ntohl (msg->num_peers);
   size_needed = sizeof (struct GNUNET_RPS_CS_RequestMessage) +
@@ -1061,7 +1069,7 @@ handle_client_request (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Message received from client has size larger than expected\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVICE_client_drop (cli_ctx->client);
     return;
   }
 
@@ -1074,19 +1082,17 @@ handle_client_request (void *cls,
 
   reply_cls = GNUNET_new (struct ReplyCls);
   reply_cls->id = ntohl (msg->id);
-  reply_cls->client = client;
+  reply_cls->cli_ctx = cli_ctx;
   reply_cls->req_handle = RPS_sampler_get_n_rand_peers (client_sampler,
                                                         client_respond,
                                                         reply_cls,
                                                         num_peers);
 
-  cli_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientContext);
   GNUNET_assert (NULL != cli_ctx);
   GNUNET_CONTAINER_DLL_insert (cli_ctx->rep_cls_head,
                                cli_ctx->rep_cls_tail,
                                reply_cls);
-  GNUNET_SERVER_receive_done (client,
-                             GNUNET_OK);
+  GNUNET_SERVICE_client_continue (cli_ctx->client);
 }
 
 
@@ -1099,15 +1105,12 @@ handle_client_request (void *cls,
  */
 static void
 handle_client_request_cancel (void *cls,
-                              struct GNUNET_SERVER_Client *client,
-                              const struct GNUNET_MessageHeader *message)
+                          const struct GNUNET_RPS_CS_RequestCancelMessage *msg)
 {
-  struct GNUNET_RPS_CS_RequestCancelMessage *msg =
-    (struct GNUNET_RPS_CS_RequestCancelMessage *) message;
-  struct ClientContext *cli_ctx;
+  struct ClientContext *cli_ctx = cls;
   struct ReplyCls *rep_cls;
 
-  cli_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientContext);
+  GNUNET_assert (NULL != cli_ctx);
   GNUNET_assert (NULL != cli_ctx->rep_cls_head);
   rep_cls = cli_ctx->rep_cls_head;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -1119,8 +1122,34 @@ handle_client_request_cancel (void *cls,
   GNUNET_assert (rep_cls->id == ntohl (msg->id));
   RPS_sampler_request_cancel (rep_cls->req_handle);
   destroy_reply_cls (rep_cls);
-  GNUNET_SERVER_receive_done (client,
-                             GNUNET_OK);
+  GNUNET_SERVICE_client_continue (cli_ctx->client);
+}
+
+
+/**
+ * @brief This function is called, when the client seeds peers.
+ * It verifies that @a msg is well-formed.
+ *
+ * @param cls the closure (#ClientContext)
+ * @param msg the message
+ * @return #GNUNET_OK if @a msg is well-formed
+ */
+static int
+check_client_seed (void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
+{
+  struct ClientContext *cli_ctx = cls;
+  uint16_t msize = ntohs (msg->header.size);
+  uint32_t num_peers = ntohl (msg->num_peers);
+
+  msize -= sizeof (struct GNUNET_RPS_CS_SeedMessage);
+  if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
+       (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cli_ctx->client);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
 }
 
 
@@ -1133,36 +1162,18 @@ handle_client_request_cancel (void *cls,
  */
 static void
 handle_client_seed (void *cls,
-                    struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
+                    const struct GNUNET_RPS_CS_SeedMessage *msg)
 {
-  struct GNUNET_RPS_CS_SeedMessage *in_msg;
+  struct ClientContext *cli_ctx = cls;
   struct GNUNET_PeerIdentity *peers;
   uint32_t num_peers;
   uint32_t i;
 
-  if (sizeof (struct GNUNET_RPS_CS_SeedMessage) > ntohs (message->size))
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client,
-                                GNUNET_SYSERR);
-  }
-
-  in_msg = (struct GNUNET_RPS_CS_SeedMessage *) message;
-  num_peers = ntohl (in_msg->num_peers);
-  peers = (struct GNUNET_PeerIdentity *) &in_msg[1];
+  num_peers = ntohl (msg->num_peers);
+  peers = (struct GNUNET_PeerIdentity *) &msg[1];
   //peers = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
   //GNUNET_memcpy (peers, &in_msg[1], num_peers * sizeof (struct GNUNET_PeerIdentity));
 
-  if ((ntohs (message->size) - sizeof (struct GNUNET_RPS_CS_SeedMessage)) /
-      sizeof (struct GNUNET_PeerIdentity) != num_peers)
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client,
-                                GNUNET_SYSERR);
-    return;
-  }
-
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Client seeded peers:\n");
   print_peer_list (peers, num_peers);
@@ -1175,17 +1186,33 @@ handle_client_seed (void *cls,
          GNUNET_i2s (&peers[i]));
 
     got_peer (&peers[i]);
-
-    //RPS_sampler_update (prot_sampler,   &peers[i]);
-    //RPS_sampler_update (client_sampler, &peers[i]);
   }
 
   ////GNUNET_free (peers);
 
-  GNUNET_SERVER_receive_done (client,
-                             GNUNET_OK);
+  GNUNET_SERVICE_client_continue (cli_ctx->client);
 }
 
+/**
+ * Handle a CHECK_LIVE message from another peer.
+ *
+ * This does nothing. But without calling #GNUNET_CADET_receive_done()
+ * the channel is blocked for all other communication.
+ *
+ * @param cls Closure
+ * @param channel The channel the CHECK was received over
+ * @param channel_ctx The context associated with this channel
+ * @param msg The message header
+ */
+static int
+handle_peer_check (void *cls,
+                 struct GNUNET_CADET_Channel *channel,
+                 void **channel_ctx,
+                 const struct GNUNET_MessageHeader *msg)
+{
+  GNUNET_CADET_receive_done (channel);
+  return GNUNET_OK;
+}
 
 /**
  * Handle a PUSH message from another peer.
@@ -1216,14 +1243,14 @@ handle_peer_push (void *cls,
        "Received PUSH (%s)\n",
        GNUNET_i2s (peer));
 
-#ifdef ENABLE_MALICIOUS
+  #ifdef ENABLE_MALICIOUS
   struct AttackedPeer *tmp_att_peer;
 
-  tmp_att_peer = GNUNET_new (struct AttackedPeer);
-  GNUNET_memcpy (&tmp_att_peer->peer_id, peer, sizeof (struct GNUNET_PeerIdentity));
-  if (1 == mal_type
-      || 3 == mal_type)
+  if ( (1 == mal_type) ||
+       (3 == mal_type) )
   { /* Try to maximise representation */
+    tmp_att_peer = GNUNET_new (struct AttackedPeer);
+    GNUNET_memcpy (&tmp_att_peer->peer_id, peer, sizeof (struct GNUNET_PeerIdentity));
     if (NULL == att_peer_set)
       att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
     if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
@@ -1234,19 +1261,16 @@ handle_peer_push (void *cls,
                                    tmp_att_peer);
       add_peer_array_to_set (peer, 1, att_peer_set);
     }
+    GNUNET_CADET_receive_done (channel);
     return GNUNET_OK;
   }
 
 
   else if (2 == mal_type)
   { /* We attack one single well-known peer - simply ignore */
+    GNUNET_CADET_receive_done (channel);
     return GNUNET_OK;
   }
-  else
-  {
-    GNUNET_free (tmp_att_peer);
-  }
-
   #endif /* ENABLE_MALICIOUS */
 
   /* Add the sending peer to the push_map */
@@ -1288,6 +1312,7 @@ handle_peer_pull_request (void *cls,
       || 3 == mal_type)
   { /* Try to maximise representation */
     send_pull_reply (peer, mal_peers, num_mal_peers);
+    GNUNET_CADET_receive_done (channel);
     return GNUNET_OK;
   }
 
@@ -1297,6 +1322,7 @@ handle_peer_pull_request (void *cls,
     {
       send_pull_reply (peer, mal_peers, num_mal_peers);
     }
+    GNUNET_CADET_receive_done (channel);
     return GNUNET_OK;
   }
   #endif /* ENABLE_MALICIOUS */
@@ -1368,8 +1394,8 @@ handle_peer_pull_reply (void *cls,
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
         "Received a pull reply from a peer we didn't request one from!\n");
-    GNUNET_break_op (0);
     GNUNET_CADET_receive_done (channel);
+    GNUNET_break_op (0);
     return GNUNET_OK;
   }
 
@@ -1377,7 +1403,10 @@ handle_peer_pull_reply (void *cls,
   #ifdef ENABLE_MALICIOUS
   // We shouldn't even receive pull replies as we're not sending
   if (2 == mal_type)
+  {
+    GNUNET_CADET_receive_done (channel);
     return GNUNET_OK;
+  }
   #endif /* ENABLE_MALICIOUS */
 
   /* Do actual logic */
@@ -1466,7 +1495,9 @@ compute_rand_delay (struct GNUNET_TIME_Relative mean,
     LOG (GNUNET_ERROR_TYPE_WARNING,
          "Not accepting spread of 0\n");
     GNUNET_break (0);
+    GNUNET_assert (0);
   }
+  GNUNET_assert (0 != mean.rel_value_us);
 
   /* Compute random time value between spread * mean and spread * mean */
   half_interval = GNUNET_TIME_relative_divide (mean, spread);
@@ -1477,7 +1508,7 @@ compute_rand_delay (struct GNUNET_TIME_Relative mean,
    * via multiplying round_interval with a 'fraction' (0 to value)/value
    */
   rand_delay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_rand_delay);
-  ret = GNUNET_TIME_relative_multiply (mean,  rand_delay);
+  ret = GNUNET_TIME_relative_saturating_multiply (mean,  rand_delay);
   ret = GNUNET_TIME_relative_divide   (ret, max_rand_delay);
   ret = GNUNET_TIME_relative_add      (ret, half_interval);
 
@@ -1537,8 +1568,40 @@ do_round (void *cls);
 static void
 do_mal_round (void *cls);
 
-
 #ifdef ENABLE_MALICIOUS
+
+
+/**
+ * @brief This function is called, when the client tells us to act malicious.
+ * It verifies that @a msg is well-formed.
+ *
+ * @param cls the closure (#ClientContext)
+ * @param msg the message
+ * @return #GNUNET_OK if @a msg is well-formed
+ */
+static int
+check_client_act_malicious (void *cls,
+                            const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
+{
+  struct ClientContext *cli_ctx = cls;
+  uint16_t msize = ntohs (msg->header.size);
+  uint32_t num_peers = ntohl (msg->num_peers);
+
+  msize -= sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage);
+  if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
+       (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+        "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
+        ntohl (msg->num_peers),
+        (msize / sizeof (struct GNUNET_PeerIdentity)));
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cli_ctx->client);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
 /**
  * Turn RPS service to act malicious.
  *
@@ -1548,49 +1611,29 @@ do_mal_round (void *cls);
  */
 static void
 handle_client_act_malicious (void *cls,
-                             struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *msg)
+                             const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
 {
-  struct GNUNET_RPS_CS_ActMaliciousMessage *in_msg;
+  struct ClientContext *cli_ctx = cls;
   struct GNUNET_PeerIdentity *peers;
   uint32_t num_mal_peers_sent;
   uint32_t num_mal_peers_old;
 
-  /* Check for protocol violation */
-  if (sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage) > ntohs (msg->size))
-  {
-    GNUNET_break_op (0);
-  }
-
-  in_msg = (struct GNUNET_RPS_CS_ActMaliciousMessage *) msg;
-  if ((ntohs (msg->size) - sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage)) /
-      sizeof (struct GNUNET_PeerIdentity) != ntohl (in_msg->num_peers))
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-        "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
-        ntohl (in_msg->num_peers),
-        (ntohs (msg->size) - sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage)) /
-            sizeof (struct GNUNET_PeerIdentity));
-    GNUNET_break_op (0);
-  }
-
-
   /* Do actual logic */
   peers = (struct GNUNET_PeerIdentity *) &msg[1];
-  mal_type = ntohl (in_msg->type);
+  mal_type = ntohl (msg->type);
   if (NULL == mal_peer_set)
     mal_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Now acting malicious type %" PRIu32 ", got %" PRIu32 " peers.\n",
        mal_type,
-       ntohl (in_msg->num_peers));
+       ntohl (msg->num_peers));
 
   if (1 == mal_type)
   { /* Try to maximise representation */
     /* Add other malicious peers to those we already know */
 
-    num_mal_peers_sent = ntohl (in_msg->num_peers);
+    num_mal_peers_sent = ntohl (msg->num_peers);
     num_mal_peers_old = num_mal_peers;
     GNUNET_array_grow (mal_peers,
                        num_mal_peers,
@@ -1614,7 +1657,7 @@ handle_client_act_malicious (void *cls,
   { /* Try to partition the network */
     /* Add other malicious peers to those we already know */
 
-    num_mal_peers_sent = ntohl (in_msg->num_peers) - 1;
+    num_mal_peers_sent = ntohl (msg->num_peers) - 1;
     num_mal_peers_old = num_mal_peers;
     GNUNET_array_grow (mal_peers,
                        num_mal_peers,
@@ -1634,7 +1677,7 @@ handle_client_act_malicious (void *cls,
 
     /* Store the one attacked peer */
     GNUNET_memcpy (&attacked_peer,
-            &in_msg->attacked_peer,
+            &msg->attacked_peer,
             sizeof (struct GNUNET_PeerIdentity));
     /* Set the flag of the attacked peer to valid to avoid problems */
     if (GNUNET_NO == Peers_check_peer_known (&attacked_peer))
@@ -1661,9 +1704,9 @@ handle_client_act_malicious (void *cls,
   else
   {
     GNUNET_break (0);
+    GNUNET_SERVICE_client_continue (cli_ctx->client);
   }
-  GNUNET_SERVER_receive_done (client,
-                             GNUNET_OK);
+  GNUNET_SERVICE_client_continue (cli_ctx->client);
 }
 
 
@@ -1960,12 +2003,11 @@ do_round (void *cls)
       to_file (file_name_view_log,
                "-%s",
                GNUNET_i2s_full (&peers_to_clean[i]));
-      Peers_clean_peer (&peers_to_clean[i]);
+      clean_peer (&peers_to_clean[i]);
       //peer_destroy_channel_send (sender);
     }
 
     GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
-    peers_to_clean = NULL;
   }
   else
   {
@@ -1989,7 +2031,7 @@ do_round (void *cls)
          "Updating with peer %s from push list\n",
          GNUNET_i2s (update_peer));
     insert_in_sampler (NULL, update_peer);
-    Peers_clean_peer (update_peer); /* This cleans only if it is not in the view */
+    clean_peer (update_peer); /* This cleans only if it is not in the view */
     //peer_destroy_channel_send (sender);
   }
 
@@ -2000,7 +2042,7 @@ do_round (void *cls)
          GNUNET_i2s (CustomPeerMap_get_peer_by_index (pull_map, i)));
     insert_in_sampler (NULL, CustomPeerMap_get_peer_by_index (pull_map, i));
     /* This cleans only if it is not in the view */
-    Peers_clean_peer (CustomPeerMap_get_peer_by_index (pull_map, i));
+    clean_peer (CustomPeerMap_get_peer_by_index (pull_map, i));
     //peer_destroy_channel_send (sender);
   }
 
@@ -2020,10 +2062,6 @@ do_round (void *cls)
 }
 
 
-static void
-rps_start (struct GNUNET_SERVER_Handle *server);
-
-
 /**
  * This is called from GNUNET_CADET_get_peers().
  *
@@ -2105,8 +2143,32 @@ process_peerinfo_peers (void *cls,
 static void
 shutdown_task (void *cls)
 {
+  struct ClientContext *client_ctx;
+  struct ReplyCls *reply_cls;
+
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "RPS is going down\n");
+
+  /* Clean all clients */
+  for (client_ctx = cli_ctx_head;
+       NULL != cli_ctx_head;
+       client_ctx = cli_ctx_head)
+  {
+    /* Clean pending requests to the sampler */
+    for (reply_cls = client_ctx->rep_cls_head;
+         NULL != client_ctx->rep_cls_head;
+         reply_cls = client_ctx->rep_cls_head)
+    {
+      RPS_sampler_request_cancel (reply_cls->req_handle);
+      GNUNET_CONTAINER_DLL_remove (client_ctx->rep_cls_head,
+                                   client_ctx->rep_cls_tail,
+                                   reply_cls);
+      GNUNET_free (reply_cls);
+    }
+    GNUNET_MQ_destroy (client_ctx->mq);
+    GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx);
+    GNUNET_free (client_ctx);
+  }
   GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle);
   GNUNET_PEERINFO_disconnect (peerinfo_handle);
 
@@ -2143,108 +2205,82 @@ shutdown_task (void *cls)
 
 
 /**
- * @brief Get informed about a connecting client.
+ * Handle client connecting to the service.
  *
- * @param cls unused
- * @param client the client that connects
- */
-static void
-handle_client_connect (void *cls,
-                       struct GNUNET_SERVER_Client *client)
+ * @param cls NULL
+ * @param client the new client
+ * @param mq the message queue of @a client
+ * @return @a client
+ */
+static void *
+client_connect_cb (void *cls,
+                   struct GNUNET_SERVICE_Client *client,
+                   struct GNUNET_MQ_Handle *mq)
 {
   struct ClientContext *cli_ctx;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Client connected\n");
   if (NULL == client)
-    return; /* Server was destroyed before a client connected. Shutting down */
+    return client; /* Server was destroyed before a client connected. Shutting down */
   cli_ctx = GNUNET_new (struct ClientContext);
-  cli_ctx->mq = GNUNET_MQ_queue_for_server_client (client);
-  GNUNET_SERVER_client_set_user_context (client, cli_ctx);
+  cli_ctx->mq = GNUNET_SERVICE_client_get_mq (client);
+  cli_ctx->client = client;
   GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
                                cli_ctx_tail,
                                cli_ctx);
+  return cli_ctx;
 }
 
 /**
- * A client disconnected.  Remove all of its data structure entries.
+ * Callback called when a client disconnected from the service
  *
- * @param cls closure, NULL
- * @param client identification of the client
+ * @param cls closure for the service
+ * @param c the client that disconnected
+ * @param internal_cls should be equal to @a c
  */
 static void
-handle_client_disconnect (void *cls,
-                                           struct GNUNET_SERVER_Client *client)
+client_disconnect_cb (void *cls,
+                      struct GNUNET_SERVICE_Client *client,
+                      void *internal_cls)
 {
-  struct ClientContext *cli_ctx;
+  struct ClientContext *cli_ctx = internal_cls;
 
+  GNUNET_assert (client == cli_ctx->client);
   if (NULL == client)
-  {/* shutdown task */
+  {/* shutdown task - destroy all clients */
     while (NULL != cli_ctx_head)
       destroy_cli_ctx (cli_ctx_head);
   }
   else
-  {
-    cli_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientContext);
+  { /* destroy this client */
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Client disconnected. Destroy its context.\n");
     destroy_cli_ctx (cli_ctx);
   }
 }
 
 
 /**
- * Actually start the service.
- */
-  static void
-rps_start (struct GNUNET_SERVER_Handle *server)
-{
-  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
-    {&handle_client_request,        NULL, GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST,
-      sizeof (struct GNUNET_RPS_CS_RequestMessage)},
-    {&handle_client_request_cancel, NULL, GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST_CANCEL,
-      sizeof (struct GNUNET_RPS_CS_RequestCancelMessage)},
-    {&handle_client_seed,           NULL, GNUNET_MESSAGE_TYPE_RPS_CS_SEED, 0},
-    #ifdef ENABLE_MALICIOUS
-    {&handle_client_act_malicious,  NULL, GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS , 0},
-    #endif /* ENABLE_MALICIOUS */
-    {NULL, NULL, 0, 0}
-  };
-
-  GNUNET_SERVER_add_handlers (server, handlers);
-  GNUNET_SERVER_connect_notify (server,
-                                &handle_client_connect,
-                                NULL);
-  GNUNET_SERVER_disconnect_notify (server,
-                                   &handle_client_disconnect,
-                                   NULL);
-  LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
-
-
-  do_round_task = GNUNET_SCHEDULER_add_now (&do_round, NULL);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled first round\n");
-
-  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
-                                NULL);
-}
-
-
-/**
- * Process statistics requests.
+ * Handle random peer sampling clients.
  *
  * @param cls closure
- * @param server the initialized server
  * @param c configuration to use
+ * @param service the initialized service
  */
 static void
 run (void *cls,
-     struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *service)
 {
   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
-    {&handle_peer_push        , GNUNET_MESSAGE_TYPE_RPS_PP_PUSH        ,
+    {&handle_peer_check       , GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
+      sizeof (struct GNUNET_MessageHeader)},
+    {&handle_peer_push        , GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
       sizeof (struct GNUNET_MessageHeader)},
     {&handle_peer_pull_request, GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
       sizeof (struct GNUNET_MessageHeader)},
-    {&handle_peer_pull_reply  , GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY  , 0},
+    {&handle_peer_pull_reply  , GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY, 0},
     {NULL, 0, 0}
   };
 
@@ -2358,7 +2394,7 @@ run (void *cls,
   struct GNUNET_TIME_Relative half_round_interval;
   struct GNUNET_TIME_Relative  max_round_interval;
 
-  half_round_interval = GNUNET_TIME_relative_multiply (round_interval, .5);
+  half_round_interval = GNUNET_TIME_relative_divide (round_interval, 2);
   max_round_interval = GNUNET_TIME_relative_add (round_interval, half_round_interval);
 
   prot_sampler =   RPS_sampler_init     (sampler_size_est_need, max_round_interval);
@@ -2369,8 +2405,8 @@ run (void *cls,
   pull_map = CustomPeerMap_create (4);
 
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
-  GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, NULL);
+  //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
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting stored valid peers\n");
@@ -2381,26 +2417,43 @@ run (void *cls,
                                                    process_peerinfo_peers,
                                                    NULL);
 
-  rps_start (server);
+  LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
+
+  do_round_task = GNUNET_SCHEDULER_add_now (&do_round, NULL);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled first round\n");
+
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
 }
 
 
 /**
- * The main function for the rps service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  return (GNUNET_OK ==
-          GNUNET_SERVICE_run (argc,
-                              argv,
-                              "rps",
-                             GNUNET_SERVICE_OPTION_NONE,
-                             &run, NULL)) ? 0 : 1;
-}
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("rps",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_fixed_size (client_request,
+   GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST,
+   struct GNUNET_RPS_CS_RequestMessage,
+   NULL),
+ GNUNET_MQ_hd_fixed_size (client_request_cancel,
+   GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST_CANCEL,
+   struct GNUNET_RPS_CS_RequestCancelMessage,
+   NULL),
+ GNUNET_MQ_hd_var_size (client_seed,
+   GNUNET_MESSAGE_TYPE_RPS_CS_SEED,
+   struct GNUNET_RPS_CS_SeedMessage,
+   NULL),
+#ifdef ENABLE_MALICIOUS
+ GNUNET_MQ_hd_var_size (client_act_malicious,
+   GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS,
+   struct GNUNET_RPS_CS_ActMaliciousMessage,
+   NULL),
+#endif /* ENABLE_MALICIOUS */
+ GNUNET_MQ_handler_end());
 
 /* end of gnunet-service-rps.c */