+ return 0;
+}
+
+/**
+ * Initialise given RPSPeer
+ */
+static void default_init_peer (struct RPSPeer *rps_peer)
+{
+ rps_peer->num_ids_to_request = 1;
+}
+
+/**
+ * Callback to call on receipt of a reply
+ *
+ * @param cls closure
+ * @param n number of peers
+ * @param recv_peers the received peers
+ */
+static void
+default_reply_handle (void *cls,
+ uint64_t n,
+ const struct GNUNET_PeerIdentity *recv_peers)
+{
+ struct RPSPeer *rps_peer;
+ struct PendingReply *pending_rep = (struct PendingReply *) cls;
+ unsigned int i;
+
+ rps_peer = pending_rep->rps_peer;
+ GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
+ rps_peer->pending_rep_tail,
+ pending_rep);
+ rps_peer->num_pending_reps--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "[%s] got %" PRIu64 " peers:\n",
+ GNUNET_i2s (rps_peer->peer_id),
+ n);
+
+ for (i = 0; i < n; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%u: %s\n",
+ i,
+ GNUNET_i2s (&recv_peers[i]));
+
+ rps_peer->num_recv_ids++;
+ }
+
+ if (0 == evaluate () && HAVE_QUICK_QUIT == cur_test_run.have_quick_quit)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test succeeded before timeout\n");
+ GNUNET_assert (NULL != shutdown_task);
+ GNUNET_SCHEDULER_cancel (shutdown_task);
+ shutdown_task = GNUNET_SCHEDULER_add_now (&shutdown_op, NULL);
+ GNUNET_assert (NULL!= shutdown_task);
+ }
+}
+
+/**
+ * Request random peers.
+ */
+static void
+request_peers (void *cls)
+{
+ struct PendingRequest *pending_req = cls;
+ struct RPSPeer *rps_peer;
+ struct PendingReply *pending_rep;
+
+ if (GNUNET_YES == in_shutdown)
+ return;
+ rps_peer = pending_req->rps_peer;
+ GNUNET_assert (1 <= rps_peer->num_pending_reqs);
+ GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
+ rps_peer->pending_req_tail,
+ pending_req);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requesting one peer\n");
+ pending_rep = GNUNET_new (struct PendingReply);
+ pending_rep->rps_peer = rps_peer;
+ pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
+ 1,
+ cur_test_run.reply_handle,
+ pending_rep);
+ GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_rep_head,
+ rps_peer->pending_rep_tail,
+ pending_rep);
+ rps_peer->num_pending_reps++;
+ rps_peer->num_pending_reqs--;
+}
+
+static void
+cancel_pending_req (struct PendingRequest *pending_req)
+{
+ struct RPSPeer *rps_peer;
+
+ rps_peer = pending_req->rps_peer;
+ GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
+ rps_peer->pending_req_tail,
+ pending_req);
+ rps_peer->num_pending_reqs--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cancelling pending request\n");
+ GNUNET_SCHEDULER_cancel (pending_req->request_task);
+ GNUNET_free (pending_req);
+}
+
+static void
+cancel_request (struct PendingReply *pending_rep)
+{
+ struct RPSPeer *rps_peer;
+
+ rps_peer = pending_rep->rps_peer;
+ GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
+ rps_peer->pending_rep_tail,
+ pending_rep);
+ rps_peer->num_pending_reps--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cancelling request\n");
+ GNUNET_RPS_request_cancel (pending_rep->req_handle);
+ GNUNET_free (pending_rep);
+}
+
+/**
+ * Cancel a request.
+ */
+static void
+cancel_request_cb (void *cls)
+{
+ struct RPSPeer *rps_peer = cls;
+ struct PendingReply *pending_rep;
+
+ if (GNUNET_YES == in_shutdown)
+ return;
+ pending_rep = rps_peer->pending_rep_head;
+ GNUNET_assert (1 <= rps_peer->num_pending_reps);
+ cancel_request (pending_rep);
+}
+
+
+/**
+ * Schedule requests for peer @a rps_peer that have neither been scheduled, nor
+ * issued, nor replied
+ */
+void
+schedule_missing_requests (struct RPSPeer *rps_peer)
+{
+ unsigned int i;
+ struct PendingRequest *pending_req;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Scheduling %u - %u missing requests\n",
+ rps_peer->num_ids_to_request,
+ rps_peer->num_pending_reqs + rps_peer->num_pending_reps);
+ GNUNET_assert (rps_peer->num_pending_reqs + rps_peer->num_pending_reps <=
+ rps_peer->num_ids_to_request);
+ for (i = rps_peer->num_pending_reqs + rps_peer->num_pending_reps;
+ i < rps_peer->num_ids_to_request; i++)
+ {
+ pending_req = GNUNET_new (struct PendingRequest);
+ pending_req->rps_peer = rps_peer;
+ pending_req->request_task = GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
+ cur_test_run.request_interval * i),
+ request_peers,
+ pending_req);
+ GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_req_head,
+ rps_peer->pending_req_tail,
+ pending_req);
+ rps_peer->num_pending_reqs++;
+ }
+}
+
+void
+cancel_pending_req_rep (struct RPSPeer *rps_peer)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Cancelling all (pending) requests.\n");
+ while (NULL != rps_peer->pending_req_head)
+ cancel_pending_req (rps_peer->pending_req_head);
+ GNUNET_assert (0 == rps_peer->num_pending_reqs);
+ while (NULL != rps_peer->pending_rep_head)
+ cancel_request (rps_peer->pending_rep_head);
+ GNUNET_assert (0 == rps_peer->num_pending_reps);