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