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