-rps: removing unused counter
[oweals/gnunet.git] / src / rps / gnunet-service-rps.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013-2015 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file rps/gnunet-service-rps.c
23  * @brief rps service implementation
24  * @author Julius Bünger
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_cadet_service.h"
29 #include "gnunet_peerinfo_service.h"
30 #include "gnunet_nse_service.h"
31 #include "rps.h"
32 #include "rps-test_util.h"
33 #include "gnunet-service-rps_sampler.h"
34 #include "gnunet-service-rps_custommap.h"
35 #include "gnunet-service-rps_peers.h"
36 #include "gnunet-service-rps_view.h"
37
38 #include <math.h>
39 #include <inttypes.h>
40
41 #define LOG(kind, ...) GNUNET_log(kind, __VA_ARGS__)
42
43 // TODO modify @brief in every file
44
45 // TODO check for overflows
46
47 // TODO align message structs
48
49 // TODO connect to friends
50
51 // TODO store peers somewhere persistent
52
53 // TODO blacklist? (-> mal peer detection on top of brahms)
54
55 // hist_size_init, hist_size_max
56
57 /**
58  * Our configuration.
59  */
60 static const struct GNUNET_CONFIGURATION_Handle *cfg;
61
62 /**
63  * Our own identity.
64  */
65 static struct GNUNET_PeerIdentity own_identity;
66
67
68 /***********************************************************************
69  * Housekeeping with clients
70 ***********************************************************************/
71
72 /**
73  * Closure used to pass the client and the id to the callback
74  * that replies to a client's request
75  */
76 struct ReplyCls
77 {
78   /**
79    * DLL
80    */
81   struct ReplyCls *next;
82   struct ReplyCls *prev;
83
84   /**
85    * The identifier of the request
86    */
87   uint32_t id;
88
89   /**
90    * The handle to the request
91    */
92   struct RPS_SamplerRequestHandle *req_handle;
93
94   /**
95    * The client handle to send the reply to
96    */
97   struct GNUNET_SERVER_Client *client;
98 };
99
100
101 /**
102  * Struct used to store the context of a connected client.
103  */
104 struct ClientContext
105 {
106   /**
107    * DLL
108    */
109   struct ClientContext *next;
110   struct ClientContext *prev;
111
112   /**
113    * The message queue to communicate with the client.
114    */
115   struct GNUNET_MQ_Handle *mq;
116
117   /**
118    * DLL with handles to single requests from the client
119    */
120   struct ReplyCls *rep_cls_head;
121   struct ReplyCls *rep_cls_tail;
122 };
123
124 /**
125  * DLL with all clients currently connected to us
126  */
127 struct ClientContext *cli_ctx_head;
128 struct ClientContext *cli_ctx_tail;
129
130 /***********************************************************************
131  * /Housekeeping with clients
132 ***********************************************************************/
133
134
135
136
137
138 /***********************************************************************
139  * Globals
140 ***********************************************************************/
141
142 /**
143  * Sampler used for the Brahms protocol itself.
144  */
145 static struct RPS_Sampler *prot_sampler;
146
147 /**
148  * Sampler used for the clients.
149  */
150 static struct RPS_Sampler *client_sampler;
151
152 /**
153  * Name to log view to
154  */
155 static char *file_name_view_log;
156
157 /**
158  * The size of sampler we need to be able to satisfy the client's need
159  * of random peers.
160  */
161 static unsigned int sampler_size_client_need;
162
163 /**
164  * The size of sampler we need to be able to satisfy the Brahms protocol's
165  * need of random peers.
166  *
167  * This is one minimum size the sampler grows to.
168  */
169 static unsigned int sampler_size_est_need;
170
171 /**
172  * Percentage of total peer number in the view
173  * to send random PUSHes to
174  */
175 static float alpha;
176
177 /**
178  * Percentage of total peer number in the view
179  * to send random PULLs to
180  */
181 static float beta;
182
183 /**
184  * Identifier for the main task that runs periodically.
185  */
186 static struct GNUNET_SCHEDULER_Task *do_round_task;
187
188 /**
189  * Time inverval the do_round task runs in.
190  */
191 static struct GNUNET_TIME_Relative round_interval;
192
193 /**
194  * List to store peers received through pushes temporary.
195  */
196 static struct CustomPeerMap *push_map;
197
198 /**
199  * List to store peers received through pulls temporary.
200  */
201 static struct CustomPeerMap *pull_map;
202
203 /**
204  * Handler to NSE.
205  */
206 static struct GNUNET_NSE_Handle *nse;
207
208 /**
209  * Handler to CADET.
210  */
211 static struct GNUNET_CADET_Handle *cadet_handle;
212
213 /**
214  * Handler to PEERINFO.
215  */
216 static struct GNUNET_PEERINFO_Handle *peerinfo_handle;
217
218 /**
219  * Handle for cancellation of iteration over peers.
220  */
221 static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify_handle;
222
223 /**
224  * Request counter.
225  *
226  * Counts how many requets clients already issued.
227  * Only needed in the beginning to check how many of the 64 deltas
228  * we already have
229  */
230 static unsigned int req_counter;
231
232 /**
233  * Time of the last request we received.
234  *
235  * Used to compute the expected request rate.
236  */
237 static struct GNUNET_TIME_Absolute last_request;
238
239 /**
240  * Size of #request_deltas.
241  */
242 #define REQUEST_DELTAS_SIZE 64
243 static unsigned int request_deltas_size = REQUEST_DELTAS_SIZE;
244
245 /**
246  * Last 64 deltas between requests
247  */
248 static struct GNUNET_TIME_Relative request_deltas[REQUEST_DELTAS_SIZE];
249
250 /**
251  * The prediction of the rate of requests
252  */
253 static struct GNUNET_TIME_Relative request_rate;
254
255
256 #ifdef ENABLE_MALICIOUS
257 /**
258  * Type of malicious peer
259  *
260  * 0 Don't act malicious at all - Default
261  * 1 Try to maximise representation
262  * 2 Try to partition the network
263  * 3 Combined attack
264  */
265 static uint32_t mal_type;
266
267 /**
268  * Other malicious peers
269  */
270 static struct GNUNET_PeerIdentity *mal_peers;
271
272 /**
273  * Hashmap of malicious peers used as set.
274  * Used to more efficiently check whether we know that peer.
275  */
276 static struct GNUNET_CONTAINER_MultiPeerMap *mal_peer_set;
277
278 /**
279  * Number of other malicious peers
280  */
281 static uint32_t num_mal_peers;
282
283
284 /**
285  * If type is 2 This struct is used to store the attacked peers in a DLL
286  */
287 struct AttackedPeer
288 {
289   /**
290    * DLL
291    */
292   struct AttackedPeer *next;
293   struct AttackedPeer *prev;
294
295   /**
296    * PeerID
297    */
298   struct GNUNET_PeerIdentity peer_id;
299 };
300
301 /**
302  * If type is 2 this is the DLL of attacked peers
303  */
304 static struct AttackedPeer *att_peers_head;
305 static struct AttackedPeer *att_peers_tail;
306
307 /**
308  * This index is used to point to an attacked peer to
309  * implement the round-robin-ish way to select attacked peers.
310  */
311 static struct AttackedPeer *att_peer_index;
312
313 /**
314  * Hashmap of attacked peers used as set.
315  * Used to more efficiently check whether we know that peer.
316  */
317 static struct GNUNET_CONTAINER_MultiPeerMap *att_peer_set;
318
319 /**
320  * Number of attacked peers
321  */
322 static uint32_t num_attacked_peers;
323
324 /**
325  * If type is 1 this is the attacked peer
326  */
327 static struct GNUNET_PeerIdentity attacked_peer;
328
329 /**
330  * The limit of PUSHes we can send in one round.
331  * This is an assumption of the Brahms protocol and either implemented
332  * via proof of work
333  * or
334  * assumend to be the bandwidth limitation.
335  */
336 static uint32_t push_limit = 10000;
337 #endif /* ENABLE_MALICIOUS */
338
339
340 /***********************************************************************
341  * /Globals
342 ***********************************************************************/
343
344
345 /***********************************************************************
346  * Util functions
347 ***********************************************************************/
348
349
350 /**
351  * Print peerlist to log.
352  */
353 static void
354 print_peer_list (struct GNUNET_PeerIdentity *list,
355                  unsigned int len)
356 {
357   unsigned int i;
358
359   LOG (GNUNET_ERROR_TYPE_DEBUG,
360        "Printing peer list of length %u at %p:\n",
361        len,
362        list);
363   for (i = 0 ; i < len ; i++)
364   {
365     LOG (GNUNET_ERROR_TYPE_DEBUG,
366          "%u. peer: %s\n",
367          i, GNUNET_i2s (&list[i]));
368   }
369 }
370
371
372 /**
373  * Remove peer from list.
374  */
375 static void
376 rem_from_list (struct GNUNET_PeerIdentity **peer_list,
377                unsigned int *list_size,
378                const struct GNUNET_PeerIdentity *peer)
379 {
380   unsigned int i;
381   struct GNUNET_PeerIdentity *tmp;
382
383   tmp = *peer_list;
384
385   LOG (GNUNET_ERROR_TYPE_DEBUG,
386        "Removing peer %s from list at %p\n",
387        GNUNET_i2s (peer),
388        tmp);
389
390   for ( i = 0 ; i < *list_size ; i++ )
391   {
392     if (0 == GNUNET_CRYPTO_cmp_peer_identity (&tmp[i], peer))
393     {
394       if (i < *list_size -1)
395       { /* Not at the last entry -- shift peers left */
396         memcpy (&tmp[i], &tmp[i +1],
397                 ((*list_size) - i -1) * sizeof (struct GNUNET_PeerIdentity));
398       }
399       /* Remove last entry (should be now useless PeerID) */
400       GNUNET_array_grow (tmp, *list_size, (*list_size) -1);
401     }
402   }
403   *peer_list = tmp;
404 }
405
406
407 /**
408  * Sum all time relatives of an array.
409  */
410 static struct GNUNET_TIME_Relative
411 T_relative_sum (const struct GNUNET_TIME_Relative *rel_array,
412                 uint32_t arr_size)
413 {
414   struct GNUNET_TIME_Relative sum;
415   uint32_t i;
416
417   sum = GNUNET_TIME_UNIT_ZERO;
418   for ( i = 0 ; i < arr_size ; i++ )
419   {
420     sum = GNUNET_TIME_relative_add (sum, rel_array[i]);
421   }
422   return sum;
423 }
424
425
426 /**
427  * Compute the average of given time relatives.
428  */
429 static struct GNUNET_TIME_Relative
430 T_relative_avg (const struct GNUNET_TIME_Relative *rel_array,
431                 uint32_t arr_size)
432 {
433   return GNUNET_TIME_relative_divide (T_relative_sum (rel_array,
434                                                       arr_size),
435                                       arr_size);
436 }
437
438
439 /**
440  * Put random peer from sampler into the view as history update.
441  */
442 static void
443 hist_update (void *cls,
444              struct GNUNET_PeerIdentity *ids,
445              uint32_t num_peers)
446 {
447   unsigned int i;
448
449   for (i = 0; i < num_peers; i++)
450   {
451     View_put (&ids[i]);
452     to_file (file_name_view_log,
453              "+%s\t(hist)",
454              GNUNET_i2s_full (ids));
455   }
456 }
457
458
459 /**
460  * Wrapper around #RPS_sampler_resize()
461  *
462  * If we do not have enough sampler elements, double current sampler size
463  * If we have more than enough sampler elements, halv current sampler size
464  */
465 static void
466 resize_wrapper (struct RPS_Sampler *sampler, uint32_t new_size)
467 {
468   unsigned int sampler_size;
469
470   // TODO statistics
471   // TODO respect the min, max
472   sampler_size = RPS_sampler_get_size (sampler);
473   if (sampler_size > new_size * 4)
474   { /* Shrinking */
475     RPS_sampler_resize (sampler, sampler_size / 2);
476   }
477   else if (sampler_size < new_size)
478   { /* Growing */
479     RPS_sampler_resize (sampler, sampler_size * 2);
480   }
481   LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler_size is now %u\n", sampler_size);
482 }
483
484
485 /**
486  * Wrapper around #RPS_sampler_resize() resizing the client sampler
487  */
488 static void
489 client_resize_wrapper ()
490 {
491   uint32_t bigger_size;
492
493   // TODO statistics
494
495   bigger_size = GNUNET_MAX (sampler_size_est_need, sampler_size_client_need);
496
497   // TODO respect the min, max
498   resize_wrapper (client_sampler, bigger_size);
499   LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler_size_client is now %" PRIu32 "\n",
500       bigger_size);
501 }
502
503
504 /**
505  * Estimate request rate
506  *
507  * Called every time we receive a request from the client.
508  */
509 static void
510 est_request_rate()
511 {
512   struct GNUNET_TIME_Relative max_round_duration;
513
514   if (request_deltas_size > req_counter)
515     req_counter++;
516   if ( 1 < req_counter)
517   {
518     /* Shift last request deltas to the right */
519     memcpy (&request_deltas[1],
520         request_deltas,
521         (req_counter - 1) * sizeof (struct GNUNET_TIME_Relative));
522
523     /* Add current delta to beginning */
524     request_deltas[0] =
525         GNUNET_TIME_absolute_get_difference (last_request,
526                                              GNUNET_TIME_absolute_get ());
527     request_rate = T_relative_avg (request_deltas, req_counter);
528     request_rate = (request_rate.rel_value_us < 1) ?
529       GNUNET_TIME_relative_get_unit_ () : request_rate;
530
531     /* Compute the duration a round will maximally take */
532     max_round_duration =
533         GNUNET_TIME_relative_add (round_interval,
534                                   GNUNET_TIME_relative_divide (round_interval, 2));
535
536     /* Set the estimated size the sampler has to have to
537      * satisfy the current client request rate */
538     sampler_size_client_need =
539         max_round_duration.rel_value_us / request_rate.rel_value_us;
540
541     /* Resize the sampler */
542     client_resize_wrapper ();
543   }
544   last_request = GNUNET_TIME_absolute_get ();
545 }
546
547
548 /**
549  * Add all peers in @a peer_array to @a peer_map used as set.
550  *
551  * @param peer_array array containing the peers
552  * @param num_peers number of peers in @peer_array
553  * @param peer_map the peermap to use as set
554  */
555 static void
556 add_peer_array_to_set (const struct GNUNET_PeerIdentity *peer_array,
557                        unsigned int num_peers,
558                        struct GNUNET_CONTAINER_MultiPeerMap *peer_map)
559 {
560   unsigned int i;
561   if (NULL == peer_map)
562   {
563     LOG (GNUNET_ERROR_TYPE_WARNING,
564          "Trying to add peers to non-existing peermap.\n");
565     return;
566   }
567
568   for (i = 0; i < num_peers; i++)
569   {
570     GNUNET_CONTAINER_multipeermap_put (peer_map,
571                                        &peer_array[i],
572                                        NULL,
573                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
574   }
575 }
576
577
578 /**
579  * Send a PULL REPLY to @a peer_id
580  *
581  * @param peer_id the peer to send the reply to.
582  * @param peer_ids the peers to send to @a peer_id
583  * @param num_peer_ids the number of peers to send to @a peer_id
584  */
585 static void
586 send_pull_reply (const struct GNUNET_PeerIdentity *peer_id,
587                  const struct GNUNET_PeerIdentity *peer_ids,
588                  unsigned int num_peer_ids)
589 {
590   uint32_t send_size;
591   struct GNUNET_MQ_Envelope *ev;
592   struct GNUNET_RPS_P2P_PullReplyMessage *out_msg;
593
594   /* Compute actual size */
595   send_size = sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) +
596               num_peer_ids * sizeof (struct GNUNET_PeerIdentity);
597
598   if (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < send_size)
599     /* Compute number of peers to send
600      * If too long, simply truncate */
601     // TODO select random ones via permutation
602     //      or even better: do good protocol design
603     send_size =
604       (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE -
605        sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
606        sizeof (struct GNUNET_PeerIdentity);
607   else
608     send_size = num_peer_ids;
609
610   LOG (GNUNET_ERROR_TYPE_DEBUG,
611       "Going to send PULL REPLY with %u peers to %s\n",
612       send_size, GNUNET_i2s (peer_id));
613
614   ev = GNUNET_MQ_msg_extra (out_msg,
615                             send_size * sizeof (struct GNUNET_PeerIdentity),
616                             GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY);
617   out_msg->num_peers = htonl (send_size);
618   memcpy (&out_msg[1], peer_ids,
619          send_size * sizeof (struct GNUNET_PeerIdentity));
620
621   Peers_send_message (peer_id, ev, "PULL REPLY");
622 }
623
624
625 /**
626  * Insert PeerID in #pull_map
627  *
628  * Called once we know a peer is live.
629  */
630 static void
631 insert_in_pull_map (void *cls,
632                     const struct GNUNET_PeerIdentity *peer)
633 {
634   CustomPeerMap_put (pull_map, peer);
635 }
636
637
638 /**
639  * Insert PeerID in #view
640  *
641  * Called once we know a peer is live.
642  * Implements #PeerOp
643  */
644 static void
645 insert_in_view (void *cls,
646                 const struct GNUNET_PeerIdentity *peer)
647 {
648   GNUNET_assert (GNUNET_YES == Peers_check_peer_flag (peer, Peers_ONLINE));
649   View_put (peer);
650 }
651
652
653 /**
654  * Update sampler with given PeerID.
655  * Implements #PeerOp
656  */
657 static void
658 insert_in_sampler (void *cls,
659                    const struct GNUNET_PeerIdentity *peer)
660 {
661   LOG (GNUNET_ERROR_TYPE_DEBUG,
662        "Updating samplers with peer %s from insert_in_sampler()\n",
663        GNUNET_i2s (peer));
664   RPS_sampler_update (prot_sampler,   peer);
665   RPS_sampler_update (client_sampler, peer);
666   if (0 < RPS_sampler_count_id (prot_sampler, peer))
667   {
668     /* Make sure we 'know' about this peer */
669     (void) Peers_check_peer_live (peer);
670     /* Establish a channel towards that peer to indicate we are going to send
671      * messages to it */
672     Peers_indicate_sending_intention (peer);
673     //Peers_issue_peer_liveliness_check (peer);
674   }
675 }
676
677 /**
678  * @brief If @a peer was unknown, check liveliness and insert it in view and
679  *        sampler
680  *
681  * @param peer peer to insert
682  */
683 static void
684 got_peer (const struct GNUNET_PeerIdentity *peer)
685 {
686   /* If we did not know this peer already, insert it into sampler and view */
687   if (GNUNET_YES == Peers_check_peer_live (peer))
688   {
689     Peers_schedule_operation (peer, insert_in_sampler);
690     Peers_schedule_operation (peer, insert_in_view);
691   }
692 }
693
694 /**
695  * @brief Checks if there is a sending channel and if it is needed
696  *
697  * @param peer the peer whose sending channel is checked
698  * @return GNUNET_YES if sending channel exists and is still needed
699  *         GNUNET_NO  otherwise
700  */
701 static int
702 check_sending_channel_needed (const struct GNUNET_PeerIdentity *peer)
703 {
704   /* struct GNUNET_CADET_Channel *channel; */
705   if (GNUNET_NO == Peers_check_peer_known (peer))
706   {
707     return GNUNET_NO;
708   }
709   if (GNUNET_YES == Peers_check_sending_channel_exists (peer))
710   {
711     if ( (0 < RPS_sampler_count_id (prot_sampler, peer)) ||
712          (GNUNET_YES == View_contains_peer (peer)) ||
713          (GNUNET_YES == CustomPeerMap_contains_peer (push_map, peer)) ||
714          (GNUNET_YES == CustomPeerMap_contains_peer (pull_map, peer)) ||
715          (GNUNET_YES == Peers_check_peer_flag (peer, Peers_PULL_REPLY_PENDING)))
716     { /* If we want to keep the connection to peer open */
717       return GNUNET_YES;
718     }
719     return GNUNET_NO;
720   }
721   return GNUNET_NO;
722 }
723
724 /**
725  * @brief remove peer from our knowledge, the view, push and pull maps and
726  * samplers.
727  *
728  * @param peer the peer to remove
729  */
730 static void
731 remove_peer (const struct GNUNET_PeerIdentity *peer)
732 {
733   View_remove_peer (peer);
734   CustomPeerMap_remove_peer (pull_map, peer);
735   CustomPeerMap_remove_peer (push_map, peer);
736   RPS_sampler_reinitialise_by_value (prot_sampler, peer);
737   RPS_sampler_reinitialise_by_value (client_sampler, peer);
738   Peers_remove_peer (peer);
739 }
740
741
742 /**
743  * @brief Remove data that is not needed anymore.
744  *
745  * If the sending channel is no longer needed it is destroyed.
746  *
747  * @param peer the peer whose data is about to be cleaned
748  */
749 static void
750 clean_peer (const struct GNUNET_PeerIdentity *peer)
751 {
752   if (GNUNET_NO == check_sending_channel_needed (peer))
753   {
754     #ifdef ENABLE_MALICIOUS
755     if (0 != GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
756       Peers_destroy_sending_channel (peer);
757     #else /* ENABLE_MALICIOUS */
758     Peers_destroy_sending_channel (peer);
759     #endif /* ENABLE_MALICIOUS */
760   }
761
762   if ( (GNUNET_NO == Peers_check_peer_send_intention (peer)) &&
763        (GNUNET_NO == View_contains_peer (peer)) &&
764        (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
765        (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
766        (0 == RPS_sampler_count_id (prot_sampler,   peer)) &&
767        (0 == RPS_sampler_count_id (client_sampler, peer)) )
768   { /* We can safely remov this peer */
769     remove_peer (peer);
770     return;
771   }
772   Peers_clean_peer (peer);
773 }
774
775 /**
776  * @brief This is called when a channel is destroyed.
777  *
778  * Removes peer completely from our knowledge if the send_channel was destroyed
779  * Otherwise simply delete the recv_channel
780  *
781  * @param cls The closure
782  * @param channel The channel being closed
783  * @param channel_ctx The context associated with this channel
784  */
785 static void
786 cleanup_destroyed_channel (void *cls,
787                            const struct GNUNET_CADET_Channel *channel,
788                            void *channel_ctx)
789 {
790   struct GNUNET_PeerIdentity *peer;
791
792   peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
793       (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
794        // FIXME wait for cadet to change this function
795
796   if (GNUNET_NO == Peers_check_peer_known (peer))
797   { /* We don't know a context to that peer */
798     LOG (GNUNET_ERROR_TYPE_WARNING,
799          "channel (%s) without associated context was destroyed\n",
800          GNUNET_i2s (peer));
801     return;
802   }
803
804   if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY))
805   { /* We are in the middle of removing that peer from our knowledge. In this
806        case simply make sure that the channels are cleaned. */
807     Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
808     to_file (file_name_view_log,
809              "-%s\t(cleanup channel, ourself)",
810              GNUNET_i2s_full (peer));
811     return;
812   }
813
814   if (GNUNET_YES ==
815       Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING))
816   { /* Channel used for sending was destroyed */
817     /* Possible causes of channel destruction:
818      *  - ourselves  -> cleaning send channel -> clean context
819      *  - other peer -> peer probably went down -> remove
820      */
821     if (GNUNET_YES == Peers_check_channel_flag (channel_ctx, Peers_CHANNEL_CLEAN))
822     { /* We are about to clean the sending channel. Clean the respective
823        * context */
824       Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
825       return;
826     }
827     else
828     { /* Other peer destroyed our sending channel that he is supposed to keep
829        * open. It probably went down. Remove it from our knowledge. */
830       Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
831       remove_peer (peer);
832       return;
833     }
834   }
835   else if (GNUNET_YES ==
836       Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING))
837   { /* Channel used for receiving was destroyed */
838     /* Possible causes of channel destruction:
839      *  - ourselves  -> peer tried to establish channel twice -> clean context
840      *  - other peer -> peer doesn't want to send us data -> clean
841      */
842     if (GNUNET_YES ==
843         Peers_check_channel_flag (channel_ctx, Peers_CHANNEL_ESTABLISHED_TWICE))
844     { /* Other peer tried to establish a channel to us twice. We do not accept
845        * that. Clean the context. */
846       Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
847       return;
848     }
849     else
850     { /* Other peer doesn't want to send us data anymore. We are free to clean
851        * it. */
852       Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
853       clean_peer (peer);
854       return;
855     }
856   }
857   else
858   {
859     LOG (GNUNET_ERROR_TYPE_WARNING,
860         "Destroyed channel is neither sending nor receiving channel\n");
861   }
862 }
863
864 /***********************************************************************
865  * /Util functions
866 ***********************************************************************/
867
868 static void
869 destroy_reply_cls (struct ReplyCls *rep_cls)
870 {
871   struct ClientContext *cli_ctx;
872
873   cli_ctx = GNUNET_SERVER_client_get_user_context (rep_cls->client,
874                                                    struct ClientContext);
875   GNUNET_assert (NULL != cli_ctx);
876   GNUNET_CONTAINER_DLL_remove (cli_ctx->rep_cls_head,
877                                cli_ctx->rep_cls_tail,
878                                rep_cls);
879   GNUNET_free (rep_cls);
880 }
881
882
883 static void
884 destroy_cli_ctx (struct ClientContext *cli_ctx)
885 {
886   GNUNET_assert (NULL != cli_ctx);
887   if (NULL != cli_ctx->mq)
888   {
889     GNUNET_MQ_destroy (cli_ctx->mq);
890   }
891   if (NULL != cli_ctx->rep_cls_head)
892   {
893     LOG (GNUNET_ERROR_TYPE_WARNING,
894          "Trying to destroy the context of a client that still has pending requests. Going to clean those\n");
895     while (NULL != cli_ctx->rep_cls_head)
896       destroy_reply_cls (cli_ctx->rep_cls_head);
897   }
898   GNUNET_CONTAINER_DLL_remove (cli_ctx_head,
899                                cli_ctx_tail,
900                                cli_ctx);
901   GNUNET_free (cli_ctx);
902 }
903
904
905 /**
906  * Function called by NSE.
907  *
908  * Updates sizes of sampler list and view and adapt those lists
909  * accordingly.
910  */
911 static void
912 nse_callback (void *cls,
913               struct GNUNET_TIME_Absolute timestamp,
914               double logestimate, double std_dev)
915 {
916   double estimate;
917   //double scale; // TODO this might go gloabal/config
918
919   LOG (GNUNET_ERROR_TYPE_DEBUG,
920        "Received a ns estimate - logest: %f, std_dev: %f (old_size: %u)\n",
921        logestimate, std_dev, RPS_sampler_get_size (prot_sampler));
922   //scale = .01;
923   estimate = GNUNET_NSE_log_estimate_to_n (logestimate);
924   // GNUNET_NSE_log_estimate_to_n (logestimate);
925   estimate = pow (estimate, 1.0 / 3);
926   // TODO add if std_dev is a number
927   // estimate += (std_dev * scale);
928   if (2 < ceil (estimate))
929   {
930     LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing estimate to %f\n", estimate);
931     sampler_size_est_need = estimate;
932   } else
933     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not using estimate %f\n", estimate);
934
935   /* If the NSE has changed adapt the lists accordingly */
936   resize_wrapper (prot_sampler, sampler_size_est_need);
937   client_resize_wrapper ();
938 }
939
940
941 /**
942  * Callback called once the requested PeerIDs are ready.
943  *
944  * Sends those to the requesting client.
945  */
946 static void
947 client_respond (void *cls,
948                 struct GNUNET_PeerIdentity *peer_ids,
949                 uint32_t num_peers)
950 {
951   uint32_t i;
952   struct GNUNET_MQ_Envelope *ev;
953   struct GNUNET_RPS_CS_ReplyMessage *out_msg;
954   struct ReplyCls *reply_cls = (struct ReplyCls *) cls;
955   uint32_t size_needed;
956   struct ClientContext *cli_ctx;
957
958   GNUNET_assert (NULL != reply_cls);
959   LOG (GNUNET_ERROR_TYPE_DEBUG,
960        "sampler returned %" PRIu32 " peers:\n",
961        num_peers);
962   for (i = 0; i < num_peers; i++)
963   {
964     LOG (GNUNET_ERROR_TYPE_DEBUG,
965          "  %" PRIu32 ": %s\n",
966          i,
967          GNUNET_i2s (&peer_ids[i]));
968   }
969
970   size_needed = sizeof (struct GNUNET_RPS_CS_ReplyMessage) +
971                 num_peers * sizeof (struct GNUNET_PeerIdentity);
972
973   GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= size_needed);
974
975   ev = GNUNET_MQ_msg_extra (out_msg,
976                             num_peers * sizeof (struct GNUNET_PeerIdentity),
977                             GNUNET_MESSAGE_TYPE_RPS_CS_REPLY);
978   out_msg->num_peers = htonl (num_peers);
979   out_msg->id = htonl (reply_cls->id);
980
981   memcpy (&out_msg[1],
982           peer_ids,
983           num_peers * sizeof (struct GNUNET_PeerIdentity));
984   GNUNET_free (peer_ids);
985
986   cli_ctx = GNUNET_SERVER_client_get_user_context (reply_cls->client,
987                                                    struct ClientContext);
988   GNUNET_assert (NULL != cli_ctx);
989   destroy_reply_cls (reply_cls);
990   GNUNET_MQ_send (cli_ctx->mq, ev);
991 }
992
993
994 /**
995  * Handle RPS request from the client.
996  *
997  * @param cls closure
998  * @param client identification of the client
999  * @param message the actual message
1000  */
1001 static void
1002 handle_client_request (void *cls,
1003                        struct GNUNET_SERVER_Client *client,
1004                        const struct GNUNET_MessageHeader *message)
1005 {
1006   struct GNUNET_RPS_CS_RequestMessage *msg;
1007   uint32_t num_peers;
1008   uint32_t size_needed;
1009   struct ReplyCls *reply_cls;
1010   uint32_t i;
1011   struct ClientContext *cli_ctx;
1012
1013   msg = (struct GNUNET_RPS_CS_RequestMessage *) message;
1014
1015   num_peers = ntohl (msg->num_peers);
1016   size_needed = sizeof (struct GNUNET_RPS_CS_RequestMessage) +
1017                 num_peers * sizeof (struct GNUNET_PeerIdentity);
1018
1019   if (GNUNET_SERVER_MAX_MESSAGE_SIZE < size_needed)
1020   {
1021     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1022                 "Message received from client has size larger than expected\n");
1023     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1024     return;
1025   }
1026
1027   for (i = 0 ; i < num_peers ; i++)
1028     est_request_rate();
1029
1030   LOG (GNUNET_ERROR_TYPE_DEBUG,
1031        "Client requested %" PRIu32 " random peer(s).\n",
1032        num_peers);
1033
1034   reply_cls = GNUNET_new (struct ReplyCls);
1035   reply_cls->id = ntohl (msg->id);
1036   reply_cls->client = client;
1037   reply_cls->req_handle = RPS_sampler_get_n_rand_peers (client_sampler,
1038                                                         client_respond,
1039                                                         reply_cls,
1040                                                         num_peers);
1041
1042   cli_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientContext);
1043   GNUNET_assert (NULL != cli_ctx);
1044   GNUNET_CONTAINER_DLL_insert (cli_ctx->rep_cls_head,
1045                                cli_ctx->rep_cls_tail,
1046                                reply_cls);
1047   GNUNET_SERVER_receive_done (client,
1048                               GNUNET_OK);
1049 }
1050
1051
1052 /**
1053  * @brief Handle a message that requests the cancellation of a request
1054  *
1055  * @param cls unused
1056  * @param client the client that requests the cancellation
1057  * @param message the message containing the id of the request
1058  */
1059 static void
1060 handle_client_request_cancel (void *cls,
1061                               struct GNUNET_SERVER_Client *client,
1062                               const struct GNUNET_MessageHeader *message)
1063 {
1064   struct GNUNET_RPS_CS_RequestCancelMessage *msg =
1065     (struct GNUNET_RPS_CS_RequestCancelMessage *) message;
1066   struct ClientContext *cli_ctx;
1067   struct ReplyCls *rep_cls;
1068
1069   cli_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientContext);
1070   GNUNET_assert (NULL != cli_ctx->rep_cls_head);
1071   rep_cls = cli_ctx->rep_cls_head;
1072   LOG (GNUNET_ERROR_TYPE_DEBUG,
1073       "Client cancels request with id %" PRIu32 "\n",
1074       ntohl (msg->id));
1075   while ( (NULL != rep_cls->next) &&
1076           (rep_cls->id != ntohl (msg->id)) )
1077     rep_cls = rep_cls->next;
1078   GNUNET_assert (rep_cls->id == ntohl (msg->id));
1079   RPS_sampler_request_cancel (rep_cls->req_handle);
1080   destroy_reply_cls (rep_cls);
1081   GNUNET_SERVER_receive_done (client,
1082                               GNUNET_OK);
1083 }
1084
1085
1086 /**
1087  * Handle seed from the client.
1088  *
1089  * @param cls closure
1090  * @param client identification of the client
1091  * @param message the actual message
1092  */
1093 static void
1094 handle_client_seed (void *cls,
1095                     struct GNUNET_SERVER_Client *client,
1096                     const struct GNUNET_MessageHeader *message)
1097 {
1098   struct GNUNET_RPS_CS_SeedMessage *in_msg;
1099   struct GNUNET_PeerIdentity *peers;
1100   uint32_t num_peers;
1101   uint32_t i;
1102
1103   if (sizeof (struct GNUNET_RPS_CS_SeedMessage) > ntohs (message->size))
1104   {
1105     GNUNET_break_op (0);
1106     GNUNET_SERVER_receive_done (client,
1107                                 GNUNET_SYSERR);
1108   }
1109
1110   in_msg = (struct GNUNET_RPS_CS_SeedMessage *) message;
1111   num_peers = ntohl (in_msg->num_peers);
1112   peers = (struct GNUNET_PeerIdentity *) &in_msg[1];
1113   //peers = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
1114   //memcpy (peers, &in_msg[1], num_peers * sizeof (struct GNUNET_PeerIdentity));
1115
1116   if ((ntohs (message->size) - sizeof (struct GNUNET_RPS_CS_SeedMessage)) /
1117       sizeof (struct GNUNET_PeerIdentity) != num_peers)
1118   {
1119     GNUNET_break_op (0);
1120     GNUNET_SERVER_receive_done (client,
1121                                 GNUNET_SYSERR);
1122     return;
1123   }
1124
1125   LOG (GNUNET_ERROR_TYPE_DEBUG,
1126        "Client seeded peers:\n");
1127   print_peer_list (peers, num_peers);
1128
1129   for (i = 0; i < num_peers; i++)
1130   {
1131     LOG (GNUNET_ERROR_TYPE_DEBUG,
1132          "Updating samplers with seed %" PRIu32 ": %s\n",
1133          i,
1134          GNUNET_i2s (&peers[i]));
1135
1136     got_peer (&peers[i]);
1137
1138     //RPS_sampler_update (prot_sampler,   &peers[i]);
1139     //RPS_sampler_update (client_sampler, &peers[i]);
1140   }
1141
1142   ////GNUNET_free (peers);
1143
1144   GNUNET_SERVER_receive_done (client,
1145                               GNUNET_OK);
1146 }
1147
1148
1149 /**
1150  * Handle a PUSH message from another peer.
1151  *
1152  * Check the proof of work and store the PeerID
1153  * in the temporary list for pushed PeerIDs.
1154  *
1155  * @param cls Closure
1156  * @param channel The channel the PUSH was received over
1157  * @param channel_ctx The context associated with this channel
1158  * @param msg The message header
1159  */
1160 static int
1161 handle_peer_push (void *cls,
1162                   struct GNUNET_CADET_Channel *channel,
1163                   void **channel_ctx,
1164                   const struct GNUNET_MessageHeader *msg)
1165 {
1166   const struct GNUNET_PeerIdentity *peer;
1167
1168   // (check the proof of work (?))
1169
1170   peer = (const struct GNUNET_PeerIdentity *)
1171     GNUNET_CADET_channel_get_info (channel, GNUNET_CADET_OPTION_PEER);
1172   // FIXME wait for cadet to change this function
1173
1174   LOG (GNUNET_ERROR_TYPE_DEBUG,
1175        "Received PUSH (%s)\n",
1176        GNUNET_i2s (peer));
1177
1178 #ifdef ENABLE_MALICIOUS
1179   struct AttackedPeer *tmp_att_peer;
1180
1181   tmp_att_peer = GNUNET_new (struct AttackedPeer);
1182   memcpy (&tmp_att_peer->peer_id, peer, sizeof (struct GNUNET_PeerIdentity));
1183   if (1 == mal_type
1184       || 3 == mal_type)
1185   { /* Try to maximise representation */
1186     if (NULL == att_peer_set)
1187       att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
1188     if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
1189                                                              peer))
1190     {
1191       GNUNET_CONTAINER_DLL_insert (att_peers_head,
1192                                    att_peers_tail,
1193                                    tmp_att_peer);
1194       add_peer_array_to_set (peer, 1, att_peer_set);
1195     }
1196     return GNUNET_OK;
1197   }
1198
1199
1200   else if (2 == mal_type)
1201   { /* We attack one single well-known peer - simply ignore */
1202     return GNUNET_OK;
1203   }
1204   else
1205   {
1206     GNUNET_free (tmp_att_peer);
1207   }
1208
1209   #endif /* ENABLE_MALICIOUS */
1210
1211   /* Add the sending peer to the push_map */
1212   CustomPeerMap_put (push_map, peer);
1213
1214   GNUNET_CADET_receive_done (channel);
1215   return GNUNET_OK;
1216 }
1217
1218
1219 /**
1220  * Handle PULL REQUEST request message from another peer.
1221  *
1222  * Reply with the view of PeerIDs.
1223  *
1224  * @param cls Closure
1225  * @param channel The channel the PULL REQUEST was received over
1226  * @param channel_ctx The context associated with this channel
1227  * @param msg The message header
1228  */
1229 static int
1230 handle_peer_pull_request (void *cls,
1231                           struct GNUNET_CADET_Channel *channel,
1232                           void **channel_ctx,
1233                           const struct GNUNET_MessageHeader *msg)
1234 {
1235   struct GNUNET_PeerIdentity *peer;
1236   const struct GNUNET_PeerIdentity *view_array;
1237
1238   peer = (struct GNUNET_PeerIdentity *)
1239     GNUNET_CADET_channel_get_info (channel,
1240                                    GNUNET_CADET_OPTION_PEER);
1241   // FIXME wait for cadet to change this function
1242
1243   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer));
1244
1245   #ifdef ENABLE_MALICIOUS
1246   if (1 == mal_type
1247       || 3 == mal_type)
1248   { /* Try to maximise representation */
1249     send_pull_reply (peer, mal_peers, num_mal_peers);
1250     return GNUNET_OK;
1251   }
1252
1253   else if (2 == mal_type)
1254   { /* Try to partition network */
1255     if (0 == GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
1256     {
1257       send_pull_reply (peer, mal_peers, num_mal_peers);
1258     }
1259     return GNUNET_OK;
1260   }
1261   #endif /* ENABLE_MALICIOUS */
1262
1263   view_array = View_get_as_array ();
1264
1265   send_pull_reply (peer, view_array, View_size ());
1266
1267   GNUNET_CADET_receive_done (channel);
1268   return GNUNET_OK;
1269 }
1270
1271
1272 /**
1273  * Handle PULL REPLY message from another peer.
1274  *
1275  * Check whether we sent a corresponding request and
1276  * whether this reply is the first one.
1277  *
1278  * @param cls Closure
1279  * @param channel The channel the PUSH was received over
1280  * @param channel_ctx The context associated with this channel
1281  * @param msg The message header
1282  */
1283 static int
1284 handle_peer_pull_reply (void *cls,
1285                         struct GNUNET_CADET_Channel *channel,
1286                         void **channel_ctx,
1287                         const struct GNUNET_MessageHeader *msg)
1288 {
1289   struct GNUNET_RPS_P2P_PullReplyMessage *in_msg;
1290   struct GNUNET_PeerIdentity *peers;
1291   struct GNUNET_PeerIdentity *sender;
1292   uint32_t i;
1293 #ifdef ENABLE_MALICIOUS
1294   struct AttackedPeer *tmp_att_peer;
1295 #endif /* ENABLE_MALICIOUS */
1296
1297   /* Check for protocol violation */
1298   if (sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) > ntohs (msg->size))
1299   {
1300     GNUNET_break_op (0);
1301     GNUNET_CADET_receive_done (channel);
1302     return GNUNET_SYSERR;
1303   }
1304
1305   in_msg = (struct GNUNET_RPS_P2P_PullReplyMessage *) msg;
1306   if ((ntohs (msg->size) - sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
1307       sizeof (struct GNUNET_PeerIdentity) != ntohl (in_msg->num_peers))
1308   {
1309     LOG (GNUNET_ERROR_TYPE_ERROR,
1310         "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
1311         ntohl (in_msg->num_peers),
1312         (ntohs (msg->size) - sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
1313             sizeof (struct GNUNET_PeerIdentity));
1314     GNUNET_break_op (0);
1315     GNUNET_CADET_receive_done (channel);
1316     return GNUNET_SYSERR;
1317   }
1318
1319   // Guess simply casting isn't the nicest way...
1320   // FIXME wait for cadet to change this function
1321   sender = (struct GNUNET_PeerIdentity *)
1322       GNUNET_CADET_channel_get_info (channel, GNUNET_CADET_OPTION_PEER);
1323
1324   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (sender));
1325
1326   if (GNUNET_YES != Peers_check_peer_flag (sender, Peers_PULL_REPLY_PENDING))
1327   {
1328     LOG (GNUNET_ERROR_TYPE_WARNING,
1329         "Received a pull reply from a peer we didn't request one from!\n");
1330     GNUNET_break_op (0);
1331     GNUNET_CADET_receive_done (channel);
1332     return GNUNET_OK;
1333   }
1334
1335
1336   #ifdef ENABLE_MALICIOUS
1337   // We shouldn't even receive pull replies as we're not sending
1338   if (2 == mal_type)
1339     return GNUNET_OK;
1340   #endif /* ENABLE_MALICIOUS */
1341
1342   /* Do actual logic */
1343   peers = (struct GNUNET_PeerIdentity *) &in_msg[1];
1344
1345   LOG (GNUNET_ERROR_TYPE_DEBUG,
1346        "PULL REPLY received, got following %u peers:\n",
1347        ntohl (in_msg->num_peers));
1348
1349   for (i = 0 ; i < ntohl (in_msg->num_peers) ; i++)
1350   {
1351     LOG (GNUNET_ERROR_TYPE_DEBUG,
1352          "%u. %s\n",
1353          i,
1354          GNUNET_i2s (&peers[i]));
1355
1356     #ifdef ENABLE_MALICIOUS
1357     if ((NULL != att_peer_set) &&
1358         (1 == mal_type || 3 == mal_type))
1359     { /* Add attacked peer to local list */
1360       // TODO check if we sent a request and this was the first reply
1361       if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
1362                                                                &peers[i])
1363           && GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (mal_peer_set,
1364                                                                   &peers[i])
1365           && 0 != GNUNET_CRYPTO_cmp_peer_identity (&peers[i],
1366                                                    &own_identity))
1367       {
1368         tmp_att_peer = GNUNET_new (struct AttackedPeer);
1369         tmp_att_peer->peer_id = peers[i];
1370         GNUNET_CONTAINER_DLL_insert (att_peers_head,
1371                                      att_peers_tail,
1372                                      tmp_att_peer);
1373         add_peer_array_to_set (&peers[i], 1, att_peer_set);
1374       }
1375       continue;
1376     }
1377     #endif /* ENABLE_MALICIOUS */
1378     if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity,
1379                                               &peers[i]))
1380     {
1381       /* Make sure we 'know' about this peer */
1382       (void) Peers_check_peer_live (&peers[i]);
1383
1384       if (GNUNET_YES == Peers_check_peer_valid (&peers[i]))
1385       {
1386         CustomPeerMap_put (pull_map, &peers[i]);
1387       }
1388       else
1389       {
1390         Peers_schedule_operation (&peers[i], insert_in_pull_map);
1391         Peers_issue_peer_liveliness_check (&peers[i]);
1392       }
1393     }
1394   }
1395
1396   Peers_unset_peer_flag (sender, Peers_PULL_REPLY_PENDING);
1397   clean_peer (sender);
1398
1399   GNUNET_CADET_receive_done (channel);
1400   return GNUNET_OK;
1401 }
1402
1403
1404 /**
1405  * Compute a random delay.
1406  * A uniformly distributed value between mean + spread and mean - spread.
1407  *
1408  * For example for mean 4 min and spread 2 the minimum is (4 min - (1/2 * 4 min))
1409  * It would return a random value between 2 and 6 min.
1410  *
1411  * @param mean the mean
1412  * @param spread the inverse amount of deviation from the mean
1413  */
1414 static struct GNUNET_TIME_Relative
1415 compute_rand_delay (struct GNUNET_TIME_Relative mean,
1416                     unsigned int spread)
1417 {
1418   struct GNUNET_TIME_Relative half_interval;
1419   struct GNUNET_TIME_Relative ret;
1420   unsigned int rand_delay;
1421   unsigned int max_rand_delay;
1422
1423   if (0 == spread)
1424   {
1425     LOG (GNUNET_ERROR_TYPE_WARNING,
1426          "Not accepting spread of 0\n");
1427     GNUNET_break (0);
1428   }
1429
1430   /* Compute random time value between spread * mean and spread * mean */
1431   half_interval = GNUNET_TIME_relative_divide (mean, spread);
1432
1433   max_rand_delay = GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us / mean.rel_value_us * (2/spread);
1434   /**
1435    * Compute random value between (0 and 1) * round_interval
1436    * via multiplying round_interval with a 'fraction' (0 to value)/value
1437    */
1438   rand_delay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_rand_delay);
1439   ret = GNUNET_TIME_relative_multiply (mean,  rand_delay);
1440   ret = GNUNET_TIME_relative_divide   (ret, max_rand_delay);
1441   ret = GNUNET_TIME_relative_add      (ret, half_interval);
1442
1443   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == ret.rel_value_us)
1444     LOG (GNUNET_ERROR_TYPE_WARNING,
1445          "Returning FOREVER_REL\n");
1446
1447   return ret;
1448 }
1449
1450
1451 /**
1452  * Send single pull request
1453  *
1454  * @param peer_id the peer to send the pull request to.
1455  */
1456 static void
1457 send_pull_request (const struct GNUNET_PeerIdentity *peer)
1458 {
1459   struct GNUNET_MQ_Envelope *ev;
1460
1461   GNUNET_assert (GNUNET_NO == Peers_check_peer_flag (peer,
1462                                                      Peers_PULL_REPLY_PENDING));
1463   Peers_set_peer_flag (peer, Peers_PULL_REPLY_PENDING);
1464
1465   LOG (GNUNET_ERROR_TYPE_DEBUG,
1466        "Going to send PULL REQUEST to peer %s.\n",
1467        GNUNET_i2s (peer));
1468
1469   ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST);
1470   Peers_send_message (peer, ev, "PULL REQUEST");
1471 }
1472
1473
1474 /**
1475  * Send single push
1476  *
1477  * @param peer_id the peer to send the push to.
1478  */
1479 static void
1480 send_push (const struct GNUNET_PeerIdentity *peer_id)
1481 {
1482   struct GNUNET_MQ_Envelope *ev;
1483
1484   LOG (GNUNET_ERROR_TYPE_DEBUG,
1485        "Going to send PUSH to peer %s.\n",
1486        GNUNET_i2s (peer_id));
1487
1488   ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PUSH);
1489   Peers_send_message (peer_id, ev, "PUSH");
1490 }
1491
1492
1493 static void
1494 do_round (void *cls);
1495
1496 static void
1497 do_mal_round (void *cls);
1498
1499
1500 #ifdef ENABLE_MALICIOUS
1501 /**
1502  * Turn RPS service to act malicious.
1503  *
1504  * @param cls Closure
1505  * @param client The client that sent the message
1506  * @param msg The message header
1507  */
1508 static void
1509 handle_client_act_malicious (void *cls,
1510                              struct GNUNET_SERVER_Client *client,
1511                              const struct GNUNET_MessageHeader *msg)
1512 {
1513   struct GNUNET_RPS_CS_ActMaliciousMessage *in_msg;
1514   struct GNUNET_PeerIdentity *peers;
1515   uint32_t num_mal_peers_sent;
1516   uint32_t num_mal_peers_old;
1517
1518   /* Check for protocol violation */
1519   if (sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage) > ntohs (msg->size))
1520   {
1521     GNUNET_break_op (0);
1522   }
1523
1524   in_msg = (struct GNUNET_RPS_CS_ActMaliciousMessage *) msg;
1525   if ((ntohs (msg->size) - sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage)) /
1526       sizeof (struct GNUNET_PeerIdentity) != ntohl (in_msg->num_peers))
1527   {
1528     LOG (GNUNET_ERROR_TYPE_ERROR,
1529         "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
1530         ntohl (in_msg->num_peers),
1531         (ntohs (msg->size) - sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage)) /
1532             sizeof (struct GNUNET_PeerIdentity));
1533     GNUNET_break_op (0);
1534   }
1535
1536
1537   /* Do actual logic */
1538   peers = (struct GNUNET_PeerIdentity *) &msg[1];
1539   mal_type = ntohl (in_msg->type);
1540   if (NULL == mal_peer_set)
1541     mal_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
1542
1543   LOG (GNUNET_ERROR_TYPE_DEBUG,
1544        "Now acting malicious type %" PRIu32 ", got %" PRIu32 " peers.\n",
1545        mal_type,
1546        ntohl (in_msg->num_peers));
1547
1548   if (1 == mal_type)
1549   { /* Try to maximise representation */
1550     /* Add other malicious peers to those we already know */
1551
1552     num_mal_peers_sent = ntohl (in_msg->num_peers);
1553     num_mal_peers_old = num_mal_peers;
1554     GNUNET_array_grow (mal_peers,
1555                        num_mal_peers,
1556                        num_mal_peers + num_mal_peers_sent);
1557     memcpy (&mal_peers[num_mal_peers_old],
1558             peers,
1559             num_mal_peers_sent * sizeof (struct GNUNET_PeerIdentity));
1560
1561     /* Add all mal peers to mal_peer_set */
1562     add_peer_array_to_set (&mal_peers[num_mal_peers_old],
1563                            num_mal_peers_sent,
1564                            mal_peer_set);
1565
1566     /* Substitute do_round () with do_mal_round () */
1567     GNUNET_SCHEDULER_cancel (do_round_task);
1568     do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, NULL);
1569   }
1570
1571   else if ( (2 == mal_type) ||
1572             (3 == mal_type) )
1573   { /* Try to partition the network */
1574     /* Add other malicious peers to those we already know */
1575
1576     num_mal_peers_sent = ntohl (in_msg->num_peers) - 1;
1577     num_mal_peers_old = num_mal_peers;
1578     GNUNET_array_grow (mal_peers,
1579                        num_mal_peers,
1580                        num_mal_peers + num_mal_peers_sent);
1581     if (NULL != mal_peers &&
1582         0 != num_mal_peers)
1583     {
1584       memcpy (&mal_peers[num_mal_peers_old],
1585               peers,
1586               num_mal_peers_sent * sizeof (struct GNUNET_PeerIdentity));
1587
1588       /* Add all mal peers to mal_peer_set */
1589       add_peer_array_to_set (&mal_peers[num_mal_peers_old],
1590                              num_mal_peers_sent,
1591                              mal_peer_set);
1592     }
1593
1594     /* Store the one attacked peer */
1595     memcpy (&attacked_peer,
1596             &in_msg->attacked_peer,
1597             sizeof (struct GNUNET_PeerIdentity));
1598     /* Set the flag of the attacked peer to valid to avoid problems */
1599     if (GNUNET_NO == Peers_check_peer_known (&attacked_peer))
1600     {
1601       Peers_check_peer_live (&attacked_peer);
1602       Peers_issue_peer_liveliness_check (&attacked_peer);
1603     }
1604
1605     LOG (GNUNET_ERROR_TYPE_DEBUG,
1606          "Attacked peer is %s\n",
1607          GNUNET_i2s (&attacked_peer));
1608
1609     /* Substitute do_round () with do_mal_round () */
1610     GNUNET_SCHEDULER_cancel (do_round_task);
1611     do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, NULL);
1612   }
1613   else if (0 == mal_type)
1614   { /* Stop acting malicious */
1615     GNUNET_array_grow (mal_peers, num_mal_peers, 0);
1616
1617     /* Substitute do_mal_round () with do_round () */
1618     GNUNET_SCHEDULER_cancel (do_round_task);
1619     do_round_task = GNUNET_SCHEDULER_add_now (&do_round, NULL);
1620   }
1621   else
1622   {
1623     GNUNET_break (0);
1624   }
1625   GNUNET_SERVER_receive_done (client,
1626                               GNUNET_OK);
1627 }
1628
1629
1630 /**
1631  * Send out PUSHes and PULLs maliciously.
1632  *
1633  * This is executed regylary.
1634  */
1635 static void
1636 do_mal_round (void *cls)
1637 {
1638   uint32_t num_pushes;
1639   uint32_t i;
1640   struct GNUNET_TIME_Relative time_next_round;
1641   struct AttackedPeer *tmp_att_peer;
1642
1643   LOG (GNUNET_ERROR_TYPE_DEBUG,
1644        "Going to execute next round maliciously type %" PRIu32 ".\n",
1645       mal_type);
1646   do_round_task = NULL;
1647   GNUNET_assert (mal_type <= 3);
1648   /* Do malicious actions */
1649   if (1 == mal_type)
1650   { /* Try to maximise representation */
1651
1652     /* The maximum of pushes we're going to send this round */
1653     num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit,
1654                                          num_attacked_peers),
1655                              GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE);
1656
1657     LOG (GNUNET_ERROR_TYPE_DEBUG,
1658          "Going to send %" PRIu32 " pushes\n",
1659          num_pushes);
1660
1661     /* Send PUSHes to attacked peers */
1662     for (i = 0 ; i < num_pushes ; i++)
1663     {
1664       if (att_peers_tail == att_peer_index)
1665         att_peer_index = att_peers_head;
1666       else
1667         att_peer_index = att_peer_index->next;
1668
1669       send_push (&att_peer_index->peer_id);
1670     }
1671
1672     /* Send PULLs to some peers to learn about additional peers to attack */
1673     tmp_att_peer = att_peer_index;
1674     for (i = 0 ; i < num_pushes * alpha ; i++)
1675     {
1676       if (att_peers_tail == tmp_att_peer)
1677         tmp_att_peer = att_peers_head;
1678       else
1679         att_peer_index = tmp_att_peer->next;
1680
1681       send_pull_request (&tmp_att_peer->peer_id);
1682     }
1683   }
1684
1685
1686   else if (2 == mal_type)
1687   { /**
1688      * Try to partition the network
1689      * Send as many pushes to the attacked peer as possible
1690      * That is one push per round as it will ignore more.
1691      */
1692     Peers_check_peer_live (&attacked_peer);
1693     if (GNUNET_YES == Peers_check_peer_valid (&attacked_peer))
1694       send_push (&attacked_peer);
1695   }
1696
1697
1698   if (3 == mal_type)
1699   { /* Combined attack */
1700
1701     /* Send PUSH to attacked peers */
1702     if (GNUNET_YES == Peers_check_peer_known (&attacked_peer))
1703     {
1704       Peers_check_peer_live (&attacked_peer);
1705       if (GNUNET_YES == Peers_check_peer_valid (&attacked_peer))
1706       {
1707         LOG (GNUNET_ERROR_TYPE_DEBUG,
1708             "Goding to send push to attacked peer (%s)\n",
1709             GNUNET_i2s (&attacked_peer));
1710         send_push (&attacked_peer);
1711       }
1712       else
1713         Peers_issue_peer_liveliness_check (&attacked_peer);
1714     }
1715     else
1716       Peers_check_peer_live (&attacked_peer);
1717     Peers_issue_peer_liveliness_check (&attacked_peer);
1718
1719     /* The maximum of pushes we're going to send this round */
1720     num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1,
1721                                          num_attacked_peers),
1722                              GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE);
1723
1724     LOG (GNUNET_ERROR_TYPE_DEBUG,
1725          "Going to send %" PRIu32 " pushes\n",
1726          num_pushes);
1727
1728     for (i = 0; i < num_pushes; i++)
1729     {
1730       if (att_peers_tail == att_peer_index)
1731         att_peer_index = att_peers_head;
1732       else
1733         att_peer_index = att_peer_index->next;
1734
1735       send_push (&att_peer_index->peer_id);
1736     }
1737
1738     /* Send PULLs to some peers to learn about additional peers to attack */
1739     tmp_att_peer = att_peer_index;
1740     for (i = 0; i < num_pushes * alpha; i++)
1741     {
1742       if (att_peers_tail == tmp_att_peer)
1743         tmp_att_peer = att_peers_head;
1744       else
1745         att_peer_index = tmp_att_peer->next;
1746
1747       send_pull_request (&tmp_att_peer->peer_id);
1748     }
1749   }
1750
1751   /* Schedule next round */
1752   time_next_round = compute_rand_delay (round_interval, 2);
1753
1754   //do_round_task = GNUNET_SCHEDULER_add_delayed (round_interval, &do_mal_round,
1755   //NULL);
1756   GNUNET_assert (NULL == do_round_task);
1757   do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
1758                                                 &do_mal_round, NULL);
1759   LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
1760 }
1761 #endif /* ENABLE_MALICIOUS */
1762
1763
1764 /**
1765  * Send out PUSHes and PULLs, possibly update #view, samplers.
1766  *
1767  * This is executed regylary.
1768  */
1769 static void
1770 do_round (void *cls)
1771 {
1772   uint32_t i;
1773   const struct GNUNET_PeerIdentity *view_array;
1774   unsigned int *permut;
1775   unsigned int a_peers; /* Number of peers we send pushes to */
1776   unsigned int b_peers; /* Number of peers we send pull requests to */
1777   uint32_t first_border;
1778   uint32_t second_border;
1779   struct GNUNET_PeerIdentity peer;
1780   struct GNUNET_PeerIdentity *update_peer;
1781
1782   LOG (GNUNET_ERROR_TYPE_DEBUG,
1783        "Going to execute next round.\n");
1784   do_round_task = NULL;
1785   LOG (GNUNET_ERROR_TYPE_DEBUG,
1786        "Printing view:\n");
1787   to_file (file_name_view_log,
1788            "___ new round ___");
1789   view_array = View_get_as_array ();
1790   for (i = 0; i < View_size (); i++)
1791   {
1792     LOG (GNUNET_ERROR_TYPE_DEBUG,
1793          "\t%s\n", GNUNET_i2s (&view_array[i]));
1794     to_file (file_name_view_log,
1795              "=%s\t(do round)",
1796              GNUNET_i2s_full (&view_array[i]));
1797   }
1798
1799
1800   /* Send pushes and pull requests */
1801   if (0 < View_size ())
1802   {
1803     permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_STRONG,
1804                                            View_size ());
1805
1806     /* Send PUSHes */
1807     a_peers = ceil (alpha * View_size ());
1808
1809     LOG (GNUNET_ERROR_TYPE_DEBUG,
1810          "Going to send pushes to %u (ceil (%f * %u)) peers.\n",
1811          a_peers, alpha, View_size ());
1812     for (i = 0; i < a_peers; i++)
1813     {
1814       peer = view_array[permut[i]];
1815       if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer)) // TODO
1816       { // FIXME if this fails schedule/loop this for later
1817         send_push (&peer);
1818       }
1819     }
1820
1821     /* Send PULL requests */
1822     b_peers = ceil (beta * View_size ());
1823     first_border = a_peers;
1824     second_border = a_peers + b_peers;
1825     if (second_border > View_size ())
1826     {
1827       first_border = View_size () - b_peers;
1828       second_border = View_size ();
1829     }
1830     LOG (GNUNET_ERROR_TYPE_DEBUG,
1831         "Going to send pulls to %u (ceil (%f * %u)) peers.\n",
1832         b_peers, beta, View_size ());
1833     for (i = first_border; i < second_border; i++)
1834     {
1835       peer = view_array[permut[i]];
1836       if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer) &&
1837           GNUNET_NO == Peers_check_peer_flag (&peer, Peers_PULL_REPLY_PENDING)) // TODO
1838       { // FIXME if this fails schedule/loop this for later
1839         send_pull_request (&peer);
1840       }
1841     }
1842
1843     GNUNET_free (permut);
1844     permut = NULL;
1845   }
1846
1847
1848   /* Update view */
1849   /* TODO see how many peers are in push-/pull- list! */
1850
1851   if ((CustomPeerMap_size (push_map) <= alpha * View_size ()) &&
1852       (0 < CustomPeerMap_size (push_map)) &&
1853       (0 < CustomPeerMap_size (pull_map)))
1854   { /* If conditions for update are fulfilled, update */
1855     LOG (GNUNET_ERROR_TYPE_DEBUG, "Update of the view.\n");
1856
1857     uint32_t final_size;
1858     uint32_t peers_to_clean_size;
1859     struct GNUNET_PeerIdentity *peers_to_clean;
1860
1861     peers_to_clean = NULL;
1862     peers_to_clean_size = 0;
1863     GNUNET_array_grow (peers_to_clean, peers_to_clean_size, View_size ());
1864     memcpy (peers_to_clean,
1865             view_array,
1866             View_size () * sizeof (struct GNUNET_PeerIdentity));
1867
1868     /* Seems like recreating is the easiest way of emptying the peermap */
1869     View_clear ();
1870     to_file (file_name_view_log,
1871              "--- emptied ---");
1872
1873     first_border  = GNUNET_MIN (ceil (alpha * sampler_size_est_need),
1874                                 CustomPeerMap_size (push_map));
1875     second_border = first_border +
1876                     GNUNET_MIN (floor (beta  * sampler_size_est_need),
1877                                 CustomPeerMap_size (pull_map));
1878     final_size    = second_border +
1879       ceil ((1 - (alpha + beta)) * sampler_size_est_need);
1880
1881     /* Update view with peers received through PUSHes */
1882     permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_STRONG,
1883                                            CustomPeerMap_size (push_map));
1884     for (i = 0; i < first_border; i++)
1885     {
1886       View_put (CustomPeerMap_get_peer_by_index (push_map, permut[i]));
1887       to_file (file_name_view_log,
1888                "+%s\t(push list)",
1889                GNUNET_i2s_full (&view_array[i]));
1890       // TODO change the peer_flags accordingly
1891     }
1892     GNUNET_free (permut);
1893     permut = NULL;
1894
1895     /* Update view with peers received through PULLs */
1896     permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_STRONG,
1897                                            CustomPeerMap_size (pull_map));
1898     for (i = first_border; i < second_border; i++)
1899     {
1900       View_put (CustomPeerMap_get_peer_by_index (pull_map,
1901                                                  permut[i - first_border]));
1902       to_file (file_name_view_log,
1903                "+%s\t(pull list)",
1904                GNUNET_i2s_full (&view_array[i]));
1905       // TODO change the peer_flags accordingly
1906     }
1907     GNUNET_free (permut);
1908     permut = NULL;
1909
1910     /* Update view with peers from history */
1911     RPS_sampler_get_n_rand_peers (prot_sampler,
1912                                   hist_update,
1913                                   NULL,
1914                                   final_size - second_border);
1915     // TODO change the peer_flags accordingly
1916
1917     for (i = 0; i < View_size (); i++)
1918       rem_from_list (&peers_to_clean, &peers_to_clean_size, &view_array[i]);
1919
1920     /* Clean peers that were removed from the view */
1921     for (i = 0; i < peers_to_clean_size; i++)
1922     {
1923       to_file (file_name_view_log,
1924                "-%s",
1925                GNUNET_i2s_full (&peers_to_clean[i]));
1926       Peers_clean_peer (&peers_to_clean[i]);
1927       //peer_destroy_channel_send (sender);
1928     }
1929
1930     GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
1931     peers_to_clean = NULL;
1932   }
1933   else
1934   {
1935     LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
1936   }
1937   // TODO independent of that also get some peers from CADET_get_peers()?
1938
1939   LOG (GNUNET_ERROR_TYPE_DEBUG,
1940        "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (%u) = %.2f)\n",
1941        CustomPeerMap_size (push_map),
1942        CustomPeerMap_size (pull_map),
1943        alpha,
1944        View_size (),
1945        alpha * View_size ());
1946
1947   /* Update samplers */
1948   for (i = 0; i < CustomPeerMap_size (push_map); i++)
1949   {
1950     update_peer = CustomPeerMap_get_peer_by_index (push_map, i);
1951     LOG (GNUNET_ERROR_TYPE_DEBUG,
1952          "Updating with peer %s from push list\n",
1953          GNUNET_i2s (update_peer));
1954     insert_in_sampler (NULL, update_peer);
1955     Peers_clean_peer (update_peer); /* This cleans only if it is not in the view */
1956     //peer_destroy_channel_send (sender);
1957   }
1958
1959   for (i = 0; i < CustomPeerMap_size (pull_map); i++)
1960   {
1961     LOG (GNUNET_ERROR_TYPE_DEBUG,
1962          "Updating with peer %s from pull list\n",
1963          GNUNET_i2s (CustomPeerMap_get_peer_by_index (pull_map, i)));
1964     insert_in_sampler (NULL, CustomPeerMap_get_peer_by_index (pull_map, i));
1965     /* This cleans only if it is not in the view */
1966     Peers_clean_peer (CustomPeerMap_get_peer_by_index (pull_map, i));
1967     //peer_destroy_channel_send (sender);
1968   }
1969
1970
1971   /* Empty push/pull lists */
1972   CustomPeerMap_clear (push_map);
1973   CustomPeerMap_clear (pull_map);
1974
1975   struct GNUNET_TIME_Relative time_next_round;
1976
1977   time_next_round = compute_rand_delay (round_interval, 2);
1978
1979   /* Schedule next round */
1980   do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
1981                                                 &do_round, NULL);
1982   LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
1983 }
1984
1985
1986 static void
1987 rps_start (struct GNUNET_SERVER_Handle *server);
1988
1989
1990 /**
1991  * This is called from GNUNET_CADET_get_peers().
1992  *
1993  * It is called on every peer(ID) that cadet somehow has contact with.
1994  * We use those to initialise the sampler.
1995  */
1996 void
1997 init_peer_cb (void *cls,
1998               const struct GNUNET_PeerIdentity *peer,
1999               int tunnel, // "Do we have a tunnel towards this peer?"
2000               unsigned int n_paths, // "Number of known paths towards this peer"
2001               unsigned int best_path) // "How long is the best path?
2002                                       // (0 = unknown, 1 = ourselves, 2 = neighbor)"
2003 {
2004   if (NULL != peer)
2005   {
2006     LOG (GNUNET_ERROR_TYPE_DEBUG,
2007          "Got peer_id %s from cadet\n",
2008          GNUNET_i2s (peer));
2009     got_peer (peer);
2010   }
2011 }
2012
2013 /**
2014  * @brief Iterator function over stored, valid peers.
2015  *
2016  * We initialise the sampler with those.
2017  *
2018  * @param cls the closure
2019  * @param peer the peer id
2020  * @return #GNUNET_YES if we should continue to
2021  *         iterate,
2022  *         #GNUNET_NO if not.
2023  */
2024 static int
2025 valid_peers_iterator (void *cls,
2026                       const struct GNUNET_PeerIdentity *peer)
2027 {
2028   if (NULL != peer)
2029   {
2030     LOG (GNUNET_ERROR_TYPE_DEBUG,
2031          "Got stored, valid peer %s\n",
2032          GNUNET_i2s (peer));
2033     got_peer (peer);
2034   }
2035   return GNUNET_YES;
2036 }
2037
2038
2039 /**
2040  * Iterator over peers from peerinfo.
2041  *
2042  * @param cls closure
2043  * @param peer id of the peer, NULL for last call
2044  * @param hello hello message for the peer (can be NULL)
2045  * @param error message
2046  */
2047 void
2048 process_peerinfo_peers (void *cls,
2049                         const struct GNUNET_PeerIdentity *peer,
2050                         const struct GNUNET_HELLO_Message *hello,
2051                         const char *err_msg)
2052 {
2053   if (NULL != peer)
2054   {
2055     LOG (GNUNET_ERROR_TYPE_DEBUG,
2056          "Got peer_id %s from peerinfo\n",
2057          GNUNET_i2s (peer));
2058     got_peer (peer);
2059   }
2060 }
2061
2062
2063 /**
2064  * Task run during shutdown.
2065  *
2066  * @param cls unused
2067  */
2068 static void
2069 shutdown_task (void *cls)
2070 {
2071   LOG (GNUNET_ERROR_TYPE_DEBUG,
2072        "RPS is going down\n");
2073   GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle);
2074   GNUNET_PEERINFO_disconnect (peerinfo_handle);
2075
2076   if (NULL != do_round_task)
2077   {
2078     GNUNET_SCHEDULER_cancel (do_round_task);
2079     do_round_task = NULL;
2080   }
2081
2082   Peers_terminate ();
2083
2084   GNUNET_NSE_disconnect (nse);
2085   RPS_sampler_destroy (prot_sampler);
2086   RPS_sampler_destroy (client_sampler);
2087   GNUNET_CADET_disconnect (cadet_handle);
2088   View_destroy ();
2089   CustomPeerMap_destroy (push_map);
2090   CustomPeerMap_destroy (pull_map);
2091   #ifdef ENABLE_MALICIOUS
2092   struct AttackedPeer *tmp_att_peer;
2093   GNUNET_free (file_name_view_log);
2094   GNUNET_array_grow (mal_peers, num_mal_peers, 0);
2095   if (NULL != mal_peer_set)
2096     GNUNET_CONTAINER_multipeermap_destroy (mal_peer_set);
2097   if (NULL != att_peer_set)
2098     GNUNET_CONTAINER_multipeermap_destroy (att_peer_set);
2099   while (NULL != att_peers_head)
2100   {
2101     tmp_att_peer = att_peers_head;
2102     GNUNET_CONTAINER_DLL_remove (att_peers_head, att_peers_tail, tmp_att_peer);
2103   }
2104   #endif /* ENABLE_MALICIOUS */
2105 }
2106
2107
2108 /**
2109  * @brief Get informed about a connecting client.
2110  *
2111  * @param cls unused
2112  * @param client the client that connects
2113  */
2114 static void
2115 handle_client_connect (void *cls,
2116                        struct GNUNET_SERVER_Client *client)
2117 {
2118   struct ClientContext *cli_ctx;
2119
2120   LOG (GNUNET_ERROR_TYPE_DEBUG,
2121        "Client connected\n");
2122   if (NULL == client)
2123     return; /* Server was destroyed before a client connected. Shutting down */
2124   cli_ctx = GNUNET_new (struct ClientContext);
2125   cli_ctx->mq = GNUNET_MQ_queue_for_server_client (client);
2126   GNUNET_SERVER_client_set_user_context (client, cli_ctx);
2127   GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
2128                                cli_ctx_tail,
2129                                cli_ctx);
2130 }
2131
2132 /**
2133  * A client disconnected.  Remove all of its data structure entries.
2134  *
2135  * @param cls closure, NULL
2136  * @param client identification of the client
2137  */
2138 static void
2139 handle_client_disconnect (void *cls,
2140                                             struct GNUNET_SERVER_Client *client)
2141 {
2142   struct ClientContext *cli_ctx;
2143
2144   if (NULL == client)
2145   {/* shutdown task */
2146     while (NULL != cli_ctx_head)
2147       destroy_cli_ctx (cli_ctx_head);
2148   }
2149   else
2150   {
2151     cli_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientContext);
2152     destroy_cli_ctx (cli_ctx);
2153   }
2154 }
2155
2156
2157 /**
2158  * Actually start the service.
2159  */
2160   static void
2161 rps_start (struct GNUNET_SERVER_Handle *server)
2162 {
2163   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2164     {&handle_client_request,        NULL, GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST,
2165       sizeof (struct GNUNET_RPS_CS_RequestMessage)},
2166     {&handle_client_request_cancel, NULL, GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST_CANCEL,
2167       sizeof (struct GNUNET_RPS_CS_RequestCancelMessage)},
2168     {&handle_client_seed,           NULL, GNUNET_MESSAGE_TYPE_RPS_CS_SEED, 0},
2169     #ifdef ENABLE_MALICIOUS
2170     {&handle_client_act_malicious,  NULL, GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS , 0},
2171     #endif /* ENABLE_MALICIOUS */
2172     {NULL, NULL, 0, 0}
2173   };
2174
2175   GNUNET_SERVER_add_handlers (server, handlers);
2176   GNUNET_SERVER_connect_notify (server,
2177                                 &handle_client_connect,
2178                                 NULL);
2179   GNUNET_SERVER_disconnect_notify (server,
2180                                    &handle_client_disconnect,
2181                                    NULL);
2182   LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
2183
2184
2185   do_round_task = GNUNET_SCHEDULER_add_now (&do_round, NULL);
2186   LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled first round\n");
2187
2188   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2189                                  NULL);
2190 }
2191
2192
2193 /**
2194  * Process statistics requests.
2195  *
2196  * @param cls closure
2197  * @param server the initialized server
2198  * @param c configuration to use
2199  */
2200   static void
2201 run (void *cls,
2202      struct GNUNET_SERVER_Handle *server,
2203      const struct GNUNET_CONFIGURATION_Handle *c)
2204 {
2205   int size;
2206   int out_size;
2207   char* fn_valid_peers;
2208
2209   GNUNET_log_setup ("rps", GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_DEBUG), NULL);
2210   cfg = c;
2211
2212
2213   /* Get own ID */
2214   GNUNET_CRYPTO_get_peer_identity (cfg, &own_identity); // TODO check return value
2215   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2216               "STARTING SERVICE (rps) for peer [%s]\n",
2217               GNUNET_i2s (&own_identity));
2218   #ifdef ENABLE_MALICIOUS
2219   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2220               "Malicious execution compiled in.\n");
2221   #endif /* ENABLE_MALICIOUS */
2222
2223
2224
2225   /* Get time interval from the configuration */
2226   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "RPS",
2227                                                         "ROUNDINTERVAL",
2228                                                         &round_interval))
2229   {
2230     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2231                                "RPS", "ROUNDINTERVAL");
2232     GNUNET_SCHEDULER_shutdown ();
2233     return;
2234   }
2235
2236   /* Get initial size of sampler/view from the configuration */
2237   if (GNUNET_OK !=
2238       GNUNET_CONFIGURATION_get_value_number (cfg, "RPS", "INITSIZE",
2239         (long long unsigned int *) &sampler_size_est_need))
2240   {
2241     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2242                                "RPS", "INITSIZE");
2243     GNUNET_SCHEDULER_shutdown ();
2244     return;
2245   }
2246   LOG (GNUNET_ERROR_TYPE_DEBUG, "INITSIZE is %u\n", sampler_size_est_need);
2247
2248   if (GNUNET_OK !=
2249       GNUNET_CONFIGURATION_get_value_filename (cfg,
2250                                                "rps",
2251                                                "FILENAME_VALID_PEERS",
2252                                                &fn_valid_peers))
2253   {
2254     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2255                                "rps", "FILENAME_VALID_PEERS");
2256   }
2257
2258
2259   View_create (4);
2260
2261   /* file_name_view_log */
2262   if (GNUNET_OK != GNUNET_DISK_directory_create ("/tmp/rps/"))
2263   {
2264     LOG (GNUNET_ERROR_TYPE_WARNING,
2265          "Failed to create directory /tmp/rps/\n");
2266   }
2267
2268   size = (14 + strlen (GNUNET_i2s_full (&own_identity)) + 1) * sizeof (char);
2269   file_name_view_log = GNUNET_malloc (size);
2270   out_size = GNUNET_snprintf (file_name_view_log,
2271                               size,
2272                               "/tmp/rps/view-%s",
2273                               GNUNET_i2s_full (&own_identity));
2274   if (size < out_size ||
2275       0 > out_size)
2276   {
2277     LOG (GNUNET_ERROR_TYPE_WARNING,
2278          "Failed to write string to buffer (size: %i, out_size: %i)\n",
2279          size,
2280          out_size);
2281   }
2282
2283
2284   /* connect to NSE */
2285   nse = GNUNET_NSE_connect (cfg, nse_callback, NULL);
2286
2287
2288   alpha = 0.45;
2289   beta  = 0.45;
2290
2291
2292   /* Initialise cadet */
2293   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2294     {&handle_peer_push        , GNUNET_MESSAGE_TYPE_RPS_PP_PUSH        ,
2295       sizeof (struct GNUNET_MessageHeader)},
2296     {&handle_peer_pull_request, GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
2297       sizeof (struct GNUNET_MessageHeader)},
2298     {&handle_peer_pull_reply  , GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY  , 0},
2299     {NULL, 0, 0}
2300   };
2301   const uint32_t ports[] = {GNUNET_RPS_CADET_PORT, 0}; // _PORT specified in src/rps/rps.h
2302   cadet_handle = GNUNET_CADET_connect (cfg,
2303                                        cls,
2304                                        &Peers_handle_inbound_channel,
2305                                        &cleanup_destroyed_channel,
2306                                        cadet_handlers,
2307                                        ports);
2308
2309   peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
2310   Peers_initialise (fn_valid_peers, cadet_handle, &own_identity);
2311   GNUNET_free (fn_valid_peers);
2312
2313   /* Initialise sampler */
2314   struct GNUNET_TIME_Relative half_round_interval;
2315   struct GNUNET_TIME_Relative  max_round_interval;
2316
2317   half_round_interval = GNUNET_TIME_relative_multiply (round_interval, .5);
2318   max_round_interval = GNUNET_TIME_relative_add (round_interval, half_round_interval);
2319
2320   prot_sampler =   RPS_sampler_init     (sampler_size_est_need, max_round_interval);
2321   client_sampler = RPS_sampler_mod_init (sampler_size_est_need, max_round_interval);
2322
2323   /* Initialise push and pull maps */
2324   push_map = CustomPeerMap_create (4);
2325   pull_map = CustomPeerMap_create (4);
2326
2327
2328   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
2329   GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, NULL);
2330   // TODO send push/pull to each of those peers?
2331   // TODO read stored valid peers from last run
2332   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting stored valid peers\n");
2333   Peers_get_valid_peers (valid_peers_iterator, NULL);
2334
2335   peerinfo_notify_handle = GNUNET_PEERINFO_notify (cfg,
2336                                                    GNUNET_NO,
2337                                                    process_peerinfo_peers,
2338                                                    NULL);
2339
2340   rps_start (server);
2341 }
2342
2343
2344 /**
2345  * The main function for the rps service.
2346  *
2347  * @param argc number of arguments from the command line
2348  * @param argv command line arguments
2349  * @return 0 ok, 1 on error
2350  */
2351 int
2352 main (int argc, char *const *argv)
2353 {
2354   return (GNUNET_OK ==
2355           GNUNET_SERVICE_run (argc,
2356                               argv,
2357                               "rps",
2358                               GNUNET_SERVICE_OPTION_NONE,
2359                               &run, NULL)) ? 0 : 1;
2360 }
2361
2362 /* end of gnunet-service-rps.c */