Merge remote-tracking branch 'origin/master' into identity_oidc
[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_applications.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_cadet_service.h"
30 #include "gnunet_peerinfo_service.h"
31 #include "gnunet_nse_service.h"
32 #include "rps.h"
33 #include "rps-test_util.h"
34 #include "gnunet-service-rps_sampler.h"
35 #include "gnunet-service-rps_custommap.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 /***********************************************************************
70  * Old gnunet-service-rps_peers.c
71 ***********************************************************************/
72
73 /**
74  * Set a peer flag of given peer context.
75  */
76 #define set_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
77
78 /**
79  * Get peer flag of given peer context.
80  */
81 #define check_peer_flag_set(peer_ctx, mask)\
82   ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
83
84 /**
85  * Unset flag of given peer context.
86  */
87 #define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
88
89 /**
90  * Set a channel flag of given channel context.
91  */
92 #define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask))
93
94 /**
95  * Get channel flag of given channel context.
96  */
97 #define check_channel_flag_set(channel_flags, mask)\
98   ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
99
100 /**
101  * Unset flag of given channel context.
102  */
103 #define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
104
105
106
107 /**
108  * Pending operation on peer consisting of callback and closure
109  *
110  * When an operation cannot be executed right now this struct is used to store
111  * the callback and closure for later execution.
112  */
113 struct PeerPendingOp
114 {
115   /**
116    * Callback
117    */
118   PeerOp op;
119
120   /**
121    * Closure
122    */
123   void *op_cls;
124 };
125
126 /**
127  * List containing all messages that are yet to be send
128  *
129  * This is used to keep track of all messages that have not been sent yet. When
130  * a peer is to be removed the pending messages can be removed properly.
131  */
132 struct PendingMessage
133 {
134   /**
135    * DLL next, prev
136    */
137   struct PendingMessage *next;
138   struct PendingMessage *prev;
139
140   /**
141    * The envelope to the corresponding message
142    */
143   struct GNUNET_MQ_Envelope *ev;
144
145   /**
146    * The corresponding context
147    */
148   struct PeerContext *peer_ctx;
149
150   /**
151    * The message type
152    */
153   const char *type;
154 };
155
156 /**
157  * Struct used to keep track of other peer's status
158  *
159  * This is stored in a multipeermap.
160  * It contains information such as cadet channels, a message queue for sending,
161  * status about the channels, the pending operations on this peer and some flags
162  * about the status of the peer itself. (live, valid, ...)
163  */
164 struct PeerContext
165 {
166   /**
167    * Message queue open to client
168    */
169   struct GNUNET_MQ_Handle *mq;
170
171   /**
172    * Channel open to client.
173    */
174   struct GNUNET_CADET_Channel *send_channel;
175
176   /**
177    * Flags to the sending channel
178    */
179   uint32_t *send_channel_flags;
180
181   /**
182    * Channel open from client.
183    */
184   struct GNUNET_CADET_Channel *recv_channel; // unneeded?
185
186   /**
187    * Flags to the receiving channel
188    */
189   uint32_t *recv_channel_flags;
190
191   /**
192    * Array of pending operations on this peer.
193    */
194   struct PeerPendingOp *pending_ops;
195
196   /**
197    * Handle to the callback given to cadet_ntfy_tmt_rdy()
198    *
199    * To be canceled on shutdown.
200    */
201   struct PendingMessage *liveliness_check_pending;
202
203   /**
204    * Number of pending operations.
205    */
206   unsigned int num_pending_ops;
207
208   /**
209    * Identity of the peer
210    */
211   struct GNUNET_PeerIdentity peer_id;
212
213   /**
214    * Flags indicating status of peer
215    */
216   uint32_t peer_flags;
217
218   /**
219    * Last time we received something from that peer.
220    */
221   struct GNUNET_TIME_Absolute last_message_recv;
222
223   /**
224    * Last time we received a keepalive message.
225    */
226   struct GNUNET_TIME_Absolute last_keepalive;
227
228   /**
229    * DLL with all messages that are yet to be sent
230    */
231   struct PendingMessage *pending_messages_head;
232   struct PendingMessage *pending_messages_tail;
233
234   /**
235    * This is pobably followed by 'statistical' data (when we first saw
236    * him, how did we get his ID, how many pushes (in a timeinterval),
237    * ...)
238    */
239 };
240
241 /**
242  * @brief Closure to #valid_peer_iterator
243  */
244 struct PeersIteratorCls
245 {
246   /**
247    * Iterator function
248    */
249   PeersIterator iterator;
250
251   /**
252    * Closure to iterator
253    */
254   void *cls;
255 };
256
257 /**
258  * @brief Hashmap of valid peers.
259  */
260 static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
261
262 /**
263  * @brief Maximum number of valid peers to keep.
264  * TODO read from config
265  */
266 static uint32_t num_valid_peers_max = UINT32_MAX;
267
268 /**
269  * @brief Filename of the file that stores the valid peers persistently.
270  */
271 static char *filename_valid_peers;
272
273 /**
274  * Set of all peers to keep track of them.
275  */
276 static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
277
278 /**
279  * Cadet handle.
280  */
281 static struct GNUNET_CADET_Handle *cadet_handle;
282
283
284
285 /**
286  * @brief Get the #PeerContext associated with a peer
287  *
288  * @param peer the peer id
289  *
290  * @return the #PeerContext
291  */
292 static struct PeerContext *
293 get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
294 {
295   struct PeerContext *ctx;
296   int ret;
297
298   ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
299   GNUNET_assert (GNUNET_YES == ret);
300   ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
301   GNUNET_assert (NULL != ctx);
302   return ctx;
303 }
304
305 int
306 Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer);
307
308 /**
309  * @brief Create a new #PeerContext and insert it into the peer map
310  *
311  * @param peer the peer to create the #PeerContext for
312  *
313  * @return the #PeerContext
314  */
315 static struct PeerContext *
316 create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
317 {
318   struct PeerContext *ctx;
319   int ret;
320
321   GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
322
323   ctx = GNUNET_new (struct PeerContext);
324   ctx->peer_id = *peer;
325   ctx->send_channel_flags = GNUNET_new (uint32_t);
326   ctx->recv_channel_flags = GNUNET_new (uint32_t);
327   ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
328       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
329   GNUNET_assert (GNUNET_OK == ret);
330   return ctx;
331 }
332
333
334 /**
335  * @brief Create or get a #PeerContext
336  *
337  * @param peer the peer to get the associated context to
338  *
339  * @return the context
340  */
341 static struct PeerContext *
342 create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
343 {
344   if (GNUNET_NO == Peers_check_peer_known (peer))
345   {
346     return create_peer_ctx (peer);
347   }
348   return get_peer_ctx (peer);
349 }
350
351 void
352 Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
353
354 void
355 Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
356
357 /**
358  * @brief Check whether we have a connection to this @a peer
359  *
360  * Also sets the #Peers_ONLINE flag accordingly
361  *
362  * @param peer the peer in question
363  *
364  * @return #GNUNET_YES if we are connected
365  *         #GNUNET_NO  otherwise
366  */
367 int
368 Peers_check_connected (const struct GNUNET_PeerIdentity *peer)
369 {
370   const struct PeerContext *peer_ctx;
371
372   /* If we don't know about this peer we don't know whether it's online */
373   if (GNUNET_NO == Peers_check_peer_known (peer))
374   {
375     return GNUNET_NO;
376   }
377   /* Get the context */
378   peer_ctx = get_peer_ctx (peer);
379   /* If we have no channel to this peer we don't know whether it's online */
380   if ( (NULL == peer_ctx->send_channel) &&
381        (NULL == peer_ctx->recv_channel) )
382   {
383     Peers_unset_peer_flag (peer, Peers_ONLINE);
384     return GNUNET_NO;
385   }
386   /* Otherwise (if we have a channel, we know that it's online */
387   Peers_set_peer_flag (peer, Peers_ONLINE);
388   return GNUNET_YES;
389 }
390
391
392 /**
393  * @brief The closure to #get_rand_peer_iterator.
394  */
395 struct GetRandPeerIteratorCls
396 {
397   /**
398    * @brief The index of the peer to return.
399    * Will be decreased until 0.
400    * Then current peer is returned.
401    */
402   uint32_t index;
403
404   /**
405    * @brief Pointer to peer to return.
406    */
407   const struct GNUNET_PeerIdentity *peer;
408 };
409
410
411 /**
412  * @brief Iterator function for #get_random_peer_from_peermap.
413  *
414  * Implements #GNUNET_CONTAINER_PeerMapIterator.
415  * Decreases the index until the index is null.
416  * Then returns the current peer.
417  *
418  * @param cls the #GetRandPeerIteratorCls containing index and peer
419  * @param peer current peer
420  * @param value unused
421  *
422  * @return  #GNUNET_YES if we should continue to
423  *          iterate,
424  *          #GNUNET_NO if not.
425  */
426 static int
427 get_rand_peer_iterator (void *cls,
428                         const struct GNUNET_PeerIdentity *peer,
429                         void *value)
430 {
431   struct GetRandPeerIteratorCls *iterator_cls = cls;
432   if (0 >= iterator_cls->index)
433   {
434     iterator_cls->peer = peer;
435     return GNUNET_NO;
436   }
437   iterator_cls->index--;
438   return GNUNET_YES;
439 }
440
441
442 /**
443  * @brief Get a random peer from @a peer_map
444  *
445  * @param peer_map the peer_map to get the peer from
446  *
447  * @return a random peer
448  */
449 static const struct GNUNET_PeerIdentity *
450 get_random_peer_from_peermap (const struct
451                               GNUNET_CONTAINER_MultiPeerMap *peer_map)
452 {
453   struct GetRandPeerIteratorCls *iterator_cls;
454   const struct GNUNET_PeerIdentity *ret;
455
456   iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
457   iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
458       GNUNET_CONTAINER_multipeermap_size (peer_map));
459   (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
460                                                 get_rand_peer_iterator,
461                                                 iterator_cls);
462   ret = iterator_cls->peer;
463   GNUNET_free (iterator_cls);
464   return ret;
465 }
466
467
468 /**
469  * @brief Add a given @a peer to valid peers.
470  *
471  * If valid peers are already #num_valid_peers_max, delete a peer previously.
472  *
473  * @param peer the peer that is added to the valid peers.
474  *
475  * @return #GNUNET_YES if no other peer had to be removed
476  *         #GNUNET_NO  otherwise
477  */
478 static int
479 add_valid_peer (const struct GNUNET_PeerIdentity *peer)
480 {
481   const struct GNUNET_PeerIdentity *rand_peer;
482   int ret;
483
484   ret = GNUNET_YES;
485   while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
486   {
487     rand_peer = get_random_peer_from_peermap (valid_peers);
488     GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
489     ret = GNUNET_NO;
490   }
491   (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
492       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
493   return ret;
494 }
495
496
497 /**
498  * @brief Set the peer flag to living and
499  *        call the pending operations on this peer.
500  *
501  * Also adds peer to #valid_peers.
502  *
503  * @param peer_ctx the #PeerContext of the peer to set live
504  */
505 static void
506 set_peer_live (struct PeerContext *peer_ctx)
507 {
508   struct GNUNET_PeerIdentity *peer;
509   unsigned int i;
510
511   peer = &peer_ctx->peer_id;
512   LOG (GNUNET_ERROR_TYPE_DEBUG,
513       "Peer %s is live and valid, calling %i pending operations on it\n",
514       GNUNET_i2s (peer),
515       peer_ctx->num_pending_ops);
516
517   if (NULL != peer_ctx->liveliness_check_pending)
518   {
519     LOG (GNUNET_ERROR_TYPE_DEBUG,
520          "Removing pending liveliness check for peer %s\n",
521          GNUNET_i2s (&peer_ctx->peer_id));
522     // TODO wait until cadet sets mq->cancel_impl
523     //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
524     GNUNET_free (peer_ctx->liveliness_check_pending);
525     peer_ctx->liveliness_check_pending = NULL;
526   }
527
528   (void) add_valid_peer (peer);
529   set_peer_flag (peer_ctx, Peers_ONLINE);
530
531   /* Call pending operations */
532   for (i = 0; i < peer_ctx->num_pending_ops; i++)
533   {
534     peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
535   }
536   GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
537 }
538
539 static void
540 cleanup_destroyed_channel (void *cls,
541                            const struct GNUNET_CADET_Channel *channel);
542
543 /* Declaration of handlers */
544 static void
545 handle_peer_check (void *cls,
546                    const struct GNUNET_MessageHeader *msg);
547
548 static void
549 handle_peer_push (void *cls,
550                   const struct GNUNET_MessageHeader *msg);
551
552 static void
553 handle_peer_pull_request (void *cls,
554                           const struct GNUNET_MessageHeader *msg);
555
556 static int
557 check_peer_pull_reply (void *cls,
558                        const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
559
560 static void
561 handle_peer_pull_reply (void *cls,
562                         const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
563
564 /* End declaration of handlers */
565
566
567 /**
568  * @brief Get the channel of a peer. If not existing, create.
569  *
570  * @param peer the peer id
571  * @return the #GNUNET_CADET_Channel used to send data to @a peer
572  */
573 struct GNUNET_CADET_Channel *
574 get_channel (const struct GNUNET_PeerIdentity *peer)
575 {
576   struct PeerContext *peer_ctx;
577   struct GNUNET_HashCode port;
578   /* There exists a copy-paste-clone in run() */
579   struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
580     GNUNET_MQ_hd_fixed_size (peer_check,
581                              GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
582                              struct GNUNET_MessageHeader,
583                              NULL),
584     GNUNET_MQ_hd_fixed_size (peer_push,
585                              GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
586                              struct GNUNET_MessageHeader,
587                              NULL),
588     GNUNET_MQ_hd_fixed_size (peer_pull_request,
589                              GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
590                              struct GNUNET_MessageHeader,
591                              NULL),
592     GNUNET_MQ_hd_var_size (peer_pull_reply,
593                            GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
594                            struct GNUNET_RPS_P2P_PullReplyMessage,
595                            NULL),
596     GNUNET_MQ_handler_end ()
597   };
598
599
600   peer_ctx = get_peer_ctx (peer);
601   if (NULL == peer_ctx->send_channel)
602   {
603     LOG (GNUNET_ERROR_TYPE_DEBUG,
604          "Trying to establish channel to peer %s\n",
605          GNUNET_i2s (peer));
606     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
607                         strlen (GNUNET_APPLICATION_PORT_RPS),
608                         &port);
609     peer_ctx->send_channel =
610       GNUNET_CADET_channel_create (cadet_handle,
611                                    (struct GNUNET_PeerIdentity *) peer, /* context */
612                                    peer,
613                                    &port,
614                                    GNUNET_CADET_OPTION_RELIABLE,
615                                    NULL, /* WindowSize handler */
616                                    cleanup_destroyed_channel, /* Disconnect handler */
617                                    cadet_handlers);
618   }
619   GNUNET_assert (NULL != peer_ctx->send_channel);
620   return peer_ctx->send_channel;
621 }
622
623
624 /**
625  * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
626  *
627  * If we already have a message queue open to this client,
628  * simply return it, otherways create one.
629  *
630  * @param peer the peer to get the mq to
631  * @return the #GNUNET_MQ_Handle
632  */
633 static struct GNUNET_MQ_Handle *
634 get_mq (const struct GNUNET_PeerIdentity *peer)
635 {
636   struct PeerContext *peer_ctx;
637
638   peer_ctx = get_peer_ctx (peer);
639
640   if (NULL == peer_ctx->mq)
641   {
642     (void) get_channel (peer);
643     peer_ctx->mq = GNUNET_CADET_get_mq (peer_ctx->send_channel);
644   }
645   return peer_ctx->mq;
646 }
647
648
649 /**
650  * @brief This is called in response to the first message we sent as a
651  * liveliness check.
652  *
653  * @param cls #PeerContext of peer with pending liveliness check
654  */
655 static void
656 mq_liveliness_check_successful (void *cls)
657 {
658   struct PeerContext *peer_ctx = cls;
659
660   if (NULL != peer_ctx->liveliness_check_pending)
661   {
662     LOG (GNUNET_ERROR_TYPE_DEBUG,
663         "Liveliness check for peer %s was successfull\n",
664         GNUNET_i2s (&peer_ctx->peer_id));
665     GNUNET_free (peer_ctx->liveliness_check_pending);
666     peer_ctx->liveliness_check_pending = NULL;
667     set_peer_live (peer_ctx);
668   }
669 }
670
671 /**
672  * Issue a check whether peer is live
673  *
674  * @param peer_ctx the context of the peer
675  */
676 static void
677 check_peer_live (struct PeerContext *peer_ctx)
678 {
679   LOG (GNUNET_ERROR_TYPE_DEBUG,
680        "Get informed about peer %s getting live\n",
681        GNUNET_i2s (&peer_ctx->peer_id));
682
683   struct GNUNET_MQ_Handle *mq;
684   struct GNUNET_MQ_Envelope *ev;
685
686   ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE);
687   peer_ctx->liveliness_check_pending = GNUNET_new (struct PendingMessage);
688   peer_ctx->liveliness_check_pending->ev = ev;
689   peer_ctx->liveliness_check_pending->peer_ctx = peer_ctx;
690   peer_ctx->liveliness_check_pending->type = "Check liveliness";
691   mq = get_mq (&peer_ctx->peer_id);
692   GNUNET_MQ_notify_sent (ev,
693                          mq_liveliness_check_successful,
694                          peer_ctx);
695   GNUNET_MQ_send (mq, ev);
696 }
697
698 /**
699  * @brief Add an envelope to a message passed to mq to list of pending messages
700  *
701  * @param peer peer the message was sent to
702  * @param ev envelope to the message
703  * @param type type of the message to be sent
704  * @return pointer to pending message
705  */
706 static struct PendingMessage *
707 insert_pending_message (const struct GNUNET_PeerIdentity *peer,
708                         struct GNUNET_MQ_Envelope *ev,
709                         const char *type)
710 {
711   struct PendingMessage *pending_msg;
712   struct PeerContext *peer_ctx;
713
714   peer_ctx = get_peer_ctx (peer);
715   pending_msg = GNUNET_new (struct PendingMessage);
716   pending_msg->ev = ev;
717   pending_msg->peer_ctx = peer_ctx;
718   pending_msg->type = type;
719   GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
720                                peer_ctx->pending_messages_tail,
721                                pending_msg);
722   return pending_msg;
723 }
724
725
726 /**
727  * @brief Remove a pending message from the respective DLL
728  *
729  * @param pending_msg the pending message to remove
730  * @param cancel cancel the pending message, too
731  */
732 static void
733 remove_pending_message (struct PendingMessage *pending_msg, int cancel)
734 {
735   struct PeerContext *peer_ctx;
736
737   peer_ctx = pending_msg->peer_ctx;
738   GNUNET_assert (NULL != peer_ctx);
739   GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
740                                peer_ctx->pending_messages_tail,
741                                pending_msg);
742   // TODO wait for the cadet implementation of message cancellation
743   //if (GNUNET_YES == cancel)
744   //{
745   //  GNUNET_MQ_send_cancel (pending_msg->ev);
746   //}
747   GNUNET_free (pending_msg);
748 }
749
750
751 /**
752  * @brief Check whether function of type #PeerOp was already scheduled
753  *
754  * The array with pending operations will probably never grow really big, so
755  * iterating over it should be ok.
756  *
757  * @param peer the peer to check
758  * @param peer_op the operation (#PeerOp) on the peer
759  *
760  * @return #GNUNET_YES if this operation is scheduled on that peer
761  *         #GNUNET_NO  otherwise
762  */
763 static int
764 check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
765                            const PeerOp peer_op)
766 {
767   const struct PeerContext *peer_ctx;
768   unsigned int i;
769
770   peer_ctx = get_peer_ctx (peer);
771   for (i = 0; i < peer_ctx->num_pending_ops; i++)
772     if (peer_op == peer_ctx->pending_ops[i].op)
773       return GNUNET_YES;
774   return GNUNET_NO;
775 }
776
777 int
778 Peers_remove_peer (const struct GNUNET_PeerIdentity *peer);
779
780 /**
781  * Iterator over hash map entries. Deletes all contexts of peers.
782  *
783  * @param cls closure
784  * @param key current public key
785  * @param value value in the hash map
786  * @return #GNUNET_YES if we should continue to iterate,
787  *         #GNUNET_NO if not.
788  */
789 static int
790 peermap_clear_iterator (void *cls,
791                         const struct GNUNET_PeerIdentity *key,
792                         void *value)
793 {
794   Peers_remove_peer (key);
795   return GNUNET_YES;
796 }
797
798
799 /**
800  * @brief This is called once a message is sent.
801  *
802  * Removes the pending message
803  *
804  * @param cls type of the message that was sent
805  */
806 static void
807 mq_notify_sent_cb (void *cls)
808 {
809   struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
810   LOG (GNUNET_ERROR_TYPE_DEBUG,
811       "%s was sent.\n",
812       pending_msg->type);
813   /* Do not cancle message */
814   remove_pending_message (pending_msg, GNUNET_NO);
815 }
816
817
818 /**
819  * @brief Iterator function for #store_valid_peers.
820  *
821  * Implements #GNUNET_CONTAINER_PeerMapIterator.
822  * Writes single peer to disk.
823  *
824  * @param cls the file handle to write to.
825  * @param peer current peer
826  * @param value unused
827  *
828  * @return  #GNUNET_YES if we should continue to
829  *          iterate,
830  *          #GNUNET_NO if not.
831  */
832 static int
833 store_peer_presistently_iterator (void *cls,
834                                   const struct GNUNET_PeerIdentity *peer,
835                                   void *value)
836 {
837   const struct GNUNET_DISK_FileHandle *fh = cls;
838   char peer_string[128];
839   int size;
840   ssize_t ret;
841
842   if (NULL == peer)
843   {
844     return GNUNET_YES;
845   }
846   size = GNUNET_snprintf (peer_string,
847                           sizeof (peer_string),
848                           "%s\n",
849                           GNUNET_i2s_full (peer));
850   GNUNET_assert (53 == size);
851   ret = GNUNET_DISK_file_write (fh,
852                                 peer_string,
853                                 size);
854   GNUNET_assert (size == ret);
855   return GNUNET_YES;
856 }
857
858
859 /**
860  * @brief Store the peers currently in #valid_peers to disk.
861  */
862 static void
863 store_valid_peers ()
864 {
865   struct GNUNET_DISK_FileHandle *fh;
866   uint32_t number_written_peers;
867   int ret;
868
869   if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
870   {
871     return;
872   }
873
874   ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers);
875   if (GNUNET_SYSERR == ret)
876   {
877     LOG (GNUNET_ERROR_TYPE_WARNING,
878         "Not able to create directory for file `%s'\n",
879         filename_valid_peers);
880     GNUNET_break (0);
881   }
882   else if (GNUNET_NO == ret)
883   {
884     LOG (GNUNET_ERROR_TYPE_WARNING,
885         "Directory for file `%s' exists but is not writable for us\n",
886         filename_valid_peers);
887     GNUNET_break (0);
888   }
889   fh = GNUNET_DISK_file_open (filename_valid_peers,
890                               GNUNET_DISK_OPEN_WRITE |
891                                   GNUNET_DISK_OPEN_CREATE,
892                               GNUNET_DISK_PERM_USER_READ |
893                                   GNUNET_DISK_PERM_USER_WRITE);
894   if (NULL == fh)
895   {
896     LOG (GNUNET_ERROR_TYPE_WARNING,
897         "Not able to write valid peers to file `%s'\n",
898         filename_valid_peers);
899     return;
900   }
901   LOG (GNUNET_ERROR_TYPE_DEBUG,
902       "Writing %u valid peers to disk\n",
903       GNUNET_CONTAINER_multipeermap_size (valid_peers));
904   number_written_peers =
905     GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
906                                            store_peer_presistently_iterator,
907                                            fh);
908   GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
909   GNUNET_assert (number_written_peers ==
910       GNUNET_CONTAINER_multipeermap_size (valid_peers));
911 }
912
913
914 /**
915  * @brief Convert string representation of peer id to peer id.
916  *
917  * Counterpart to #GNUNET_i2s_full.
918  *
919  * @param string_repr The string representation of the peer id
920  *
921  * @return The peer id
922  */
923 static const struct GNUNET_PeerIdentity *
924 s2i_full (const char *string_repr)
925 {
926   struct GNUNET_PeerIdentity *peer;
927   size_t len;
928   int ret;
929
930   peer = GNUNET_new (struct GNUNET_PeerIdentity);
931   len = strlen (string_repr);
932   if (52 > len)
933   {
934     LOG (GNUNET_ERROR_TYPE_WARNING,
935         "Not able to convert string representation of PeerID to PeerID\n"
936         "Sting representation: %s (len %lu) - too short\n",
937         string_repr,
938         len);
939     GNUNET_break (0);
940   }
941   else if (52 < len)
942   {
943     len = 52;
944   }
945   ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
946                                                     len,
947                                                     &peer->public_key);
948   if (GNUNET_OK != ret)
949   {
950     LOG (GNUNET_ERROR_TYPE_WARNING,
951         "Not able to convert string representation of PeerID to PeerID\n"
952         "Sting representation: %s\n",
953         string_repr);
954     GNUNET_break (0);
955   }
956   return peer;
957 }
958
959
960 /**
961  * @brief Restore the peers on disk to #valid_peers.
962  */
963 static void
964 restore_valid_peers ()
965 {
966   off_t file_size;
967   uint32_t num_peers;
968   struct GNUNET_DISK_FileHandle *fh;
969   char *buf;
970   ssize_t size_read;
971   char *iter_buf;
972   char *str_repr;
973   const struct GNUNET_PeerIdentity *peer;
974
975   if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
976   {
977     return;
978   }
979
980   if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers))
981   {
982     return;
983   }
984   fh = GNUNET_DISK_file_open (filename_valid_peers,
985                               GNUNET_DISK_OPEN_READ,
986                               GNUNET_DISK_PERM_NONE);
987   GNUNET_assert (NULL != fh);
988   GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size));
989   num_peers = file_size / 53;
990   buf = GNUNET_malloc (file_size);
991   size_read = GNUNET_DISK_file_read (fh, buf, file_size);
992   GNUNET_assert (size_read == file_size);
993   LOG (GNUNET_ERROR_TYPE_DEBUG,
994       "Restoring %" PRIu32 " peers from file `%s'\n",
995       num_peers,
996       filename_valid_peers);
997   for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
998   {
999     str_repr = GNUNET_strndup (iter_buf, 53);
1000     peer = s2i_full (str_repr);
1001     GNUNET_free (str_repr);
1002     add_valid_peer (peer);
1003     LOG (GNUNET_ERROR_TYPE_DEBUG,
1004         "Restored valid peer %s from disk\n",
1005         GNUNET_i2s_full (peer));
1006   }
1007   iter_buf = NULL;
1008   GNUNET_free (buf);
1009   LOG (GNUNET_ERROR_TYPE_DEBUG,
1010       "num_peers: %" PRIu32 ", _size (valid_peers): %u\n",
1011       num_peers,
1012       GNUNET_CONTAINER_multipeermap_size (valid_peers));
1013   if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers))
1014   {
1015     LOG (GNUNET_ERROR_TYPE_WARNING,
1016         "Number of restored peers does not match file size. Have probably duplicates.\n");
1017   }
1018   GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
1019   LOG (GNUNET_ERROR_TYPE_DEBUG,
1020       "Restored %u valid peers from disk\n",
1021       GNUNET_CONTAINER_multipeermap_size (valid_peers));
1022 }
1023
1024
1025 /**
1026  * @brief Initialise storage of peers
1027  *
1028  * @param fn_valid_peers filename of the file used to store valid peer ids
1029  * @param cadet_h cadet handle
1030  * @param disconnect_handler Disconnect handler
1031  * @param own_id own peer identity
1032  */
1033 void
1034 Peers_initialise (char* fn_valid_peers,
1035                   struct GNUNET_CADET_Handle *cadet_h,
1036                   GNUNET_CADET_DisconnectEventHandler disconnect_handler,
1037                   const struct GNUNET_PeerIdentity *own_id)
1038 {
1039   filename_valid_peers = GNUNET_strdup (fn_valid_peers);
1040   cadet_handle = cadet_h;
1041   own_identity = *own_id;
1042   peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
1043   valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
1044   restore_valid_peers ();
1045 }
1046
1047
1048 /**
1049  * @brief Delete storage of peers that was created with #Peers_initialise ()
1050  */
1051 void
1052 Peers_terminate ()
1053 {
1054   if (GNUNET_SYSERR ==
1055       GNUNET_CONTAINER_multipeermap_iterate (peer_map,
1056                                              peermap_clear_iterator,
1057                                              NULL))
1058   {
1059     LOG (GNUNET_ERROR_TYPE_WARNING,
1060         "Iteration destroying peers was aborted.\n");
1061   }
1062   GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1063   store_valid_peers ();
1064   GNUNET_free (filename_valid_peers);
1065   GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
1066 }
1067
1068
1069 /**
1070  * Iterator over #valid_peers hash map entries.
1071  *
1072  * @param cls closure - unused
1073  * @param peer current peer id
1074  * @param value value in the hash map - unused
1075  * @return #GNUNET_YES if we should continue to
1076  *         iterate,
1077  *         #GNUNET_NO if not.
1078  */
1079 static int
1080 valid_peer_iterator (void *cls,
1081                      const struct GNUNET_PeerIdentity *peer,
1082                      void *value)
1083 {
1084   struct PeersIteratorCls *it_cls = cls;
1085
1086   return it_cls->iterator (it_cls->cls,
1087                            peer);
1088 }
1089
1090
1091 /**
1092  * @brief Get all currently known, valid peer ids.
1093  *
1094  * @param it function to call on each peer id
1095  * @param it_cls extra argument to @a it
1096  * @return the number of key value pairs processed,
1097  *         #GNUNET_SYSERR if it aborted iteration
1098  */
1099 int
1100 Peers_get_valid_peers (PeersIterator iterator,
1101                        void *it_cls)
1102 {
1103   struct PeersIteratorCls *cls;
1104   int ret;
1105
1106   cls = GNUNET_new (struct PeersIteratorCls);
1107   cls->iterator = iterator;
1108   cls->cls = it_cls;
1109   ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1110                                                valid_peer_iterator,
1111                                                cls);
1112   GNUNET_free (cls);
1113   return ret;
1114 }
1115
1116
1117 /**
1118  * @brief Add peer to known peers.
1119  *
1120  * This function is called on new peer_ids from 'external' sources
1121  * (client seed, cadet get_peers(), ...)
1122  *
1123  * @param peer the new #GNUNET_PeerIdentity
1124  *
1125  * @return #GNUNET_YES if peer was inserted
1126  *         #GNUNET_NO  otherwise (if peer was already known or
1127  *                     peer was #own_identity)
1128  */
1129 int
1130 Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
1131 {
1132   if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
1133        (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity)) )
1134   {
1135     return GNUNET_NO; /* We already know this peer - nothing to do */
1136   }
1137   (void) create_peer_ctx (peer);
1138   return GNUNET_YES;
1139 }
1140
1141 int
1142 Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
1143
1144 /**
1145  * @brief Try connecting to a peer to see whether it is online
1146  *
1147  * If not known yet, insert into known peers
1148  *
1149  * @param peer the peer whose liveliness is to be checked
1150  * @return #GNUNET_YES if peer had to be inserted
1151  *         #GNUNET_NO  otherwise (if peer was already known or
1152  *                     peer was #own_identity)
1153  */
1154 int
1155 Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1156 {
1157   struct PeerContext *peer_ctx;
1158   int ret;
1159
1160   if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
1161   {
1162     return GNUNET_NO;
1163   }
1164   ret = Peers_insert_peer (peer);
1165   peer_ctx = get_peer_ctx (peer);
1166   if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE))
1167   {
1168     check_peer_live (peer_ctx);
1169   }
1170   return ret;
1171 }
1172
1173
1174 /**
1175  * @brief Check if peer is removable.
1176  *
1177  * Check if
1178  *  - a recv channel exists
1179  *  - there are pending messages
1180  *  - there is no pending pull reply
1181  *
1182  * @param peer the peer in question
1183  * @return #GNUNET_YES    if peer is removable
1184  *         #GNUNET_NO     if peer is NOT removable
1185  *         #GNUNET_SYSERR if peer is not known
1186  */
1187 int
1188 Peers_check_removable (const struct GNUNET_PeerIdentity *peer)
1189 {
1190   struct PeerContext *peer_ctx;
1191
1192   if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1193   {
1194     return GNUNET_SYSERR;
1195   }
1196
1197   peer_ctx = get_peer_ctx (peer);
1198   if ( (NULL != peer_ctx->recv_channel) ||
1199        (NULL != peer_ctx->pending_messages_head) ||
1200        (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
1201   {
1202     return GNUNET_NO;
1203   }
1204   return GNUNET_YES;
1205 }
1206
1207 uint32_t *
1208 Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1209                         enum Peers_ChannelRole role);
1210
1211 int
1212 Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
1213
1214 /**
1215  * @brief Remove peer
1216  *
1217  * @param peer the peer to clean
1218  * @return #GNUNET_YES if peer was removed
1219  *         #GNUNET_NO  otherwise
1220  */
1221 int
1222 Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
1223 {
1224   struct PeerContext *peer_ctx;
1225   uint32_t *channel_flag;
1226
1227   if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1228   {
1229     return GNUNET_NO;
1230   }
1231
1232   peer_ctx = get_peer_ctx (peer);
1233   set_peer_flag (peer_ctx, Peers_TO_DESTROY);
1234   LOG (GNUNET_ERROR_TYPE_DEBUG,
1235        "Going to remove peer %s\n",
1236        GNUNET_i2s (&peer_ctx->peer_id));
1237   Peers_unset_peer_flag (peer, Peers_ONLINE);
1238
1239   GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
1240   while (NULL != peer_ctx->pending_messages_head)
1241   {
1242     LOG (GNUNET_ERROR_TYPE_DEBUG,
1243         "Removing unsent %s\n",
1244         peer_ctx->pending_messages_head->type);
1245     /* Cancle pending message, too */
1246     remove_pending_message (peer_ctx->pending_messages_head, GNUNET_YES);
1247   }
1248   /* If we are still waiting for notification whether this peer is live
1249    * cancel the according task */
1250   if (NULL != peer_ctx->liveliness_check_pending)
1251   {
1252     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1253          "Removing pending liveliness check for peer %s\n",
1254          GNUNET_i2s (&peer_ctx->peer_id));
1255     // TODO wait until cadet sets mq->cancel_impl
1256     //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
1257     GNUNET_free (peer_ctx->liveliness_check_pending);
1258     peer_ctx->liveliness_check_pending = NULL;
1259   }
1260   channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING);
1261   if (NULL != peer_ctx->send_channel &&
1262       GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING))
1263   {
1264     LOG (GNUNET_ERROR_TYPE_DEBUG,
1265         "Destroying send channel\n");
1266     GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1267     peer_ctx->send_channel = NULL;
1268   }
1269   channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING);
1270   if (NULL != peer_ctx->recv_channel &&
1271       GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING))
1272   {
1273     LOG (GNUNET_ERROR_TYPE_DEBUG,
1274         "Destroying recv channel\n");
1275     GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1276     peer_ctx->recv_channel = NULL;
1277   }
1278
1279   GNUNET_free (peer_ctx->send_channel_flags);
1280   GNUNET_free (peer_ctx->recv_channel_flags);
1281
1282   if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
1283   {
1284     LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
1285   }
1286   GNUNET_free (peer_ctx);
1287   return GNUNET_YES;
1288 }
1289
1290
1291 /**
1292  * @brief set flags on a given peer.
1293  *
1294  * @param peer the peer to set flags on
1295  * @param flags the flags
1296  */
1297 void
1298 Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1299 {
1300   struct PeerContext *peer_ctx;
1301
1302   peer_ctx = get_peer_ctx (peer);
1303   set_peer_flag (peer_ctx, flags);
1304 }
1305
1306
1307 /**
1308  * @brief unset flags on a given peer.
1309  *
1310  * @param peer the peer to unset flags on
1311  * @param flags the flags
1312  */
1313 void
1314 Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1315 {
1316   struct PeerContext *peer_ctx;
1317
1318   peer_ctx = get_peer_ctx (peer);
1319   unset_peer_flag (peer_ctx, flags);
1320 }
1321
1322
1323 /**
1324  * @brief Check whether flags on a peer are set.
1325  *
1326  * @param peer the peer to check the flag of
1327  * @param flags the flags to check
1328  *
1329  * @return #GNUNET_SYSERR if peer is not known
1330  *         #GNUNET_YES    if all given flags are set
1331  *         #GNUNET_NO     otherwise
1332  */
1333 int
1334 Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1335 {
1336   struct PeerContext *peer_ctx;
1337
1338   if (GNUNET_NO == Peers_check_peer_known (peer))
1339   {
1340     return GNUNET_SYSERR;
1341   }
1342   peer_ctx = get_peer_ctx (peer);
1343   return check_peer_flag_set (peer_ctx, flags);
1344 }
1345
1346
1347 /**
1348  * @brief set flags on a given channel.
1349  *
1350  * @param channel the channel to set flags on
1351  * @param flags the flags
1352  */
1353 void
1354 Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1355 {
1356   set_channel_flag (channel_flags, flags);
1357 }
1358
1359
1360 /**
1361  * @brief unset flags on a given channel.
1362  *
1363  * @param channel the channel to unset flags on
1364  * @param flags the flags
1365  */
1366 void
1367 Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1368 {
1369   unset_channel_flag (channel_flags, flags);
1370 }
1371
1372
1373 /**
1374  * @brief Check whether flags on a channel are set.
1375  *
1376  * @param channel the channel to check the flag of
1377  * @param flags the flags to check
1378  *
1379  * @return #GNUNET_YES if all given flags are set
1380  *         #GNUNET_NO  otherwise
1381  */
1382 int
1383 Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1384 {
1385   return check_channel_flag_set (channel_flags, flags);
1386 }
1387
1388 /**
1389  * @brief Get the flags for the channel in @a role for @a peer.
1390  *
1391  * @param peer Peer to get the channel flags for.
1392  * @param role Role of channel to get flags for
1393  *
1394  * @return The flags.
1395  */
1396 uint32_t *
1397 Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1398                         enum Peers_ChannelRole role)
1399 {
1400   const struct PeerContext *peer_ctx;
1401
1402   peer_ctx = get_peer_ctx (peer);
1403   if (Peers_CHANNEL_ROLE_SENDING == role)
1404   {
1405     return peer_ctx->send_channel_flags;
1406   }
1407   else if (Peers_CHANNEL_ROLE_RECEIVING == role)
1408   {
1409     return peer_ctx->recv_channel_flags;
1410   }
1411   else
1412   {
1413     GNUNET_assert (0);
1414   }
1415 }
1416
1417 /**
1418  * @brief Check whether we have information about the given peer.
1419  *
1420  * FIXME probably deprecated. Make this the new _online.
1421  *
1422  * @param peer peer in question
1423  *
1424  * @return #GNUNET_YES if peer is known
1425  *         #GNUNET_NO  if peer is not knwon
1426  */
1427 int
1428 Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
1429 {
1430   return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
1431 }
1432
1433
1434 /**
1435  * @brief Check whether @a peer is actually a peer.
1436  *
1437  * A valid peer is a peer that we know exists eg. we were connected to once.
1438  *
1439  * @param peer peer in question
1440  *
1441  * @return #GNUNET_YES if peer is valid
1442  *         #GNUNET_NO  if peer is not valid
1443  */
1444 int
1445 Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer)
1446 {
1447   return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1448 }
1449
1450
1451 /**
1452  * @brief Indicate that we want to send to the other peer
1453  *
1454  * This establishes a sending channel
1455  *
1456  * @param peer the peer to establish channel to
1457  */
1458 void
1459 Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
1460 {
1461   GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1462   (void) get_channel (peer);
1463 }
1464
1465
1466 /**
1467  * @brief Check whether other peer has the intention to send/opened channel
1468  *        towars us
1469  *
1470  * @param peer the peer in question
1471  *
1472  * @return #GNUNET_YES if peer has the intention to send
1473  *         #GNUNET_NO  otherwise
1474  */
1475 int
1476 Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
1477 {
1478   const struct PeerContext *peer_ctx;
1479
1480   peer_ctx = get_peer_ctx (peer);
1481   if (NULL != peer_ctx->recv_channel)
1482   {
1483     return GNUNET_YES;
1484   }
1485   return GNUNET_NO;
1486 }
1487
1488
1489 /**
1490  * Handle the channel a peer opens to us.
1491  *
1492  * @param cls The closure
1493  * @param channel The channel the peer wants to establish
1494  * @param initiator The peer's peer ID
1495  *
1496  * @return initial channel context for the channel
1497  *         (can be NULL -- that's not an error)
1498  */
1499 void *
1500 Peers_handle_inbound_channel (void *cls,
1501                               struct GNUNET_CADET_Channel *channel,
1502                               const struct GNUNET_PeerIdentity *initiator)
1503 {
1504   struct PeerContext *peer_ctx;
1505
1506   LOG (GNUNET_ERROR_TYPE_DEBUG,
1507       "New channel was established to us (Peer %s).\n",
1508       GNUNET_i2s (initiator));
1509   GNUNET_assert (NULL != channel); /* according to cadet API */
1510   /* Make sure we 'know' about this peer */
1511   peer_ctx = create_or_get_peer_ctx (initiator);
1512   set_peer_live (peer_ctx);
1513   /* We only accept one incoming channel per peer */
1514   if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
1515   {
1516     set_channel_flag (peer_ctx->recv_channel_flags,
1517                       Peers_CHANNEL_ESTABLISHED_TWICE);
1518     GNUNET_CADET_channel_destroy (channel);
1519     /* return the channel context */
1520     return &peer_ctx->peer_id;
1521   }
1522   peer_ctx->recv_channel = channel;
1523   return &peer_ctx->peer_id;
1524 }
1525
1526
1527 /**
1528  * @brief Check whether a sending channel towards the given peer exists
1529  *
1530  * @param peer the peer to check for
1531  *
1532  * @return #GNUNET_YES if a sending channel towards that peer exists
1533  *         #GNUNET_NO  otherwise
1534  */
1535 int
1536 Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
1537 {
1538   struct PeerContext *peer_ctx;
1539
1540   if (GNUNET_NO == Peers_check_peer_known (peer))
1541   { /* If no such peer exists, there is no channel */
1542     return GNUNET_NO;
1543   }
1544   peer_ctx = get_peer_ctx (peer);
1545   if (NULL == peer_ctx->send_channel)
1546   {
1547     return GNUNET_NO;
1548   }
1549   return GNUNET_YES;
1550 }
1551
1552
1553 /**
1554  * @brief check whether the given channel is the sending channel of the given
1555  *        peer
1556  *
1557  * @param peer the peer in question
1558  * @param channel the channel to check for
1559  * @param role either #Peers_CHANNEL_ROLE_SENDING, or
1560  *                    #Peers_CHANNEL_ROLE_RECEIVING
1561  *
1562  * @return #GNUNET_YES if the given chennel is the sending channel of the peer
1563  *         #GNUNET_NO  otherwise
1564  */
1565 int
1566 Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
1567                           const struct GNUNET_CADET_Channel *channel,
1568                           enum Peers_ChannelRole role)
1569 {
1570   const struct PeerContext *peer_ctx;
1571
1572   if (GNUNET_NO == Peers_check_peer_known (peer))
1573   {
1574     return GNUNET_NO;
1575   }
1576   peer_ctx = get_peer_ctx (peer);
1577   if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
1578        (channel == peer_ctx->send_channel) )
1579   {
1580     return GNUNET_YES;
1581   }
1582   if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
1583        (channel == peer_ctx->recv_channel) )
1584   {
1585     return GNUNET_YES;
1586   }
1587   return GNUNET_NO;
1588 }
1589
1590
1591 /**
1592  * @brief Destroy the send channel of a peer e.g. stop indicating a sending
1593  *        intention to another peer
1594  *
1595  * If there is also no channel to receive messages from that peer, remove it
1596  * from the peermap.
1597  * TODO really?
1598  *
1599  * @peer the peer identity of the peer whose sending channel to destroy
1600  * @return #GNUNET_YES if channel was destroyed
1601  *         #GNUNET_NO  otherwise
1602  */
1603 int
1604 Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1605 {
1606   struct PeerContext *peer_ctx;
1607
1608   if (GNUNET_NO == Peers_check_peer_known (peer))
1609   {
1610     return GNUNET_NO;
1611   }
1612   peer_ctx = get_peer_ctx (peer);
1613   if (NULL != peer_ctx->send_channel)
1614   {
1615     set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1616     GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1617     peer_ctx->send_channel = NULL;
1618     (void) Peers_check_connected (peer);
1619     return GNUNET_YES;
1620   }
1621   return GNUNET_NO;
1622 }
1623
1624 /**
1625  * This is called when a channel is destroyed.
1626  *
1627  * @param cls The closure
1628  * @param channel The channel being closed
1629  * @param channel_ctx The context associated with this channel
1630  */
1631 void
1632 Peers_cleanup_destroyed_channel (void *cls,
1633                                  const struct GNUNET_CADET_Channel *channel)
1634 {
1635   struct GNUNET_PeerIdentity *peer = cls;
1636   struct PeerContext *peer_ctx;
1637
1638   if (GNUNET_NO == Peers_check_peer_known (peer))
1639   {/* We don't want to implicitly create a context that we're about to kill */
1640   LOG (GNUNET_ERROR_TYPE_DEBUG,
1641        "channel (%s) without associated context was destroyed\n",
1642        GNUNET_i2s (peer));
1643     return;
1644   }
1645   peer_ctx = get_peer_ctx (peer);
1646
1647   /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1648    * flag will be set. In this case simply make sure that the channels are
1649    * cleaned. */
1650   /* FIXME This distinction seems to be redundant */
1651   if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1652   {/* We initiatad the destruction of this particular peer */
1653     if (channel == peer_ctx->send_channel)
1654       peer_ctx->send_channel = NULL;
1655     else if (channel == peer_ctx->recv_channel)
1656       peer_ctx->recv_channel = NULL;
1657
1658     if (NULL != peer_ctx->send_channel)
1659     {
1660       GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1661       peer_ctx->send_channel = NULL;
1662     }
1663     if (NULL != peer_ctx->recv_channel)
1664     {
1665       GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1666       peer_ctx->recv_channel = NULL;
1667     }
1668     /* Set the #Peers_ONLINE flag accordingly */
1669     (void) Peers_check_connected (peer);
1670     return;
1671   }
1672
1673   else
1674   { /* We did not initiate the destruction of this peer */
1675     if (channel == peer_ctx->send_channel)
1676     { /* Something (but us) killd the channel - clean up peer */
1677       LOG (GNUNET_ERROR_TYPE_DEBUG,
1678           "send channel (%s) was destroyed - cleaning up\n",
1679           GNUNET_i2s (peer));
1680       peer_ctx->send_channel = NULL;
1681     }
1682     else if (channel == peer_ctx->recv_channel)
1683     { /* Other peer doesn't want to send us messages anymore */
1684       LOG (GNUNET_ERROR_TYPE_DEBUG,
1685            "Peer %s destroyed recv channel - cleaning up channel\n",
1686            GNUNET_i2s (peer));
1687       peer_ctx->recv_channel = NULL;
1688     }
1689     else
1690     {
1691       LOG (GNUNET_ERROR_TYPE_WARNING,
1692            "unknown channel (%s) was destroyed\n",
1693            GNUNET_i2s (peer));
1694     }
1695   }
1696   (void) Peers_check_connected (peer);
1697 }
1698
1699 /**
1700  * @brief Send a message to another peer.
1701  *
1702  * Keeps track about pending messages so they can be properly removed when the
1703  * peer is destroyed.
1704  *
1705  * @param peer receeiver of the message
1706  * @param ev envelope of the message
1707  * @param type type of the message
1708  */
1709 void
1710 Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1711                     struct GNUNET_MQ_Envelope *ev,
1712                     const char *type)
1713 {
1714   struct PendingMessage *pending_msg;
1715   struct GNUNET_MQ_Handle *mq;
1716
1717   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1718               "Sending message to %s of type %s\n",
1719               GNUNET_i2s (peer),
1720               type);
1721   pending_msg = insert_pending_message (peer, ev, type);
1722   mq = get_mq (peer);
1723   GNUNET_MQ_notify_sent (ev,
1724                          mq_notify_sent_cb,
1725                          pending_msg);
1726   GNUNET_MQ_send (mq, ev);
1727 }
1728
1729 /**
1730  * @brief Schedule a operation on given peer
1731  *
1732  * Avoids scheduling an operation twice.
1733  *
1734  * @param peer the peer we want to schedule the operation for once it gets live
1735  *
1736  * @return #GNUNET_YES if the operation was scheduled
1737  *         #GNUNET_NO  otherwise
1738  */
1739 int
1740 Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1741                           const PeerOp peer_op)
1742 {
1743   struct PeerPendingOp pending_op;
1744   struct PeerContext *peer_ctx;
1745
1746   if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
1747   {
1748     return GNUNET_NO;
1749   }
1750   GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1751
1752   //TODO if LIVE/ONLINE execute immediately
1753
1754   if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1755   {
1756     peer_ctx = get_peer_ctx (peer);
1757     pending_op.op = peer_op;
1758     pending_op.op_cls = NULL;
1759     GNUNET_array_append (peer_ctx->pending_ops,
1760                          peer_ctx->num_pending_ops,
1761                          pending_op);
1762     return GNUNET_YES;
1763   }
1764   return GNUNET_NO;
1765 }
1766
1767 /**
1768  * @brief Get the recv_channel of @a peer.
1769  * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
1770  * messages.
1771  *
1772  * @param peer The peer to get the recv_channel from.
1773  *
1774  * @return The recv_channel.
1775  */
1776 struct GNUNET_CADET_Channel *
1777 Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer)
1778 {
1779   struct PeerContext *peer_ctx;
1780
1781   GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1782   peer_ctx = get_peer_ctx (peer);
1783   return peer_ctx->recv_channel;
1784 }
1785 /***********************************************************************
1786  * /Old gnunet-service-rps_peers.c
1787 ***********************************************************************/
1788
1789
1790 /***********************************************************************
1791  * Housekeeping with clients
1792 ***********************************************************************/
1793
1794 /**
1795  * Closure used to pass the client and the id to the callback
1796  * that replies to a client's request
1797  */
1798 struct ReplyCls
1799 {
1800   /**
1801    * DLL
1802    */
1803   struct ReplyCls *next;
1804   struct ReplyCls *prev;
1805
1806   /**
1807    * The identifier of the request
1808    */
1809   uint32_t id;
1810
1811   /**
1812    * The handle to the request
1813    */
1814   struct RPS_SamplerRequestHandle *req_handle;
1815
1816   /**
1817    * The client handle to send the reply to
1818    */
1819   struct ClientContext *cli_ctx;
1820 };
1821
1822
1823 /**
1824  * Struct used to store the context of a connected client.
1825  */
1826 struct ClientContext
1827 {
1828   /**
1829    * DLL
1830    */
1831   struct ClientContext *next;
1832   struct ClientContext *prev;
1833
1834   /**
1835    * The message queue to communicate with the client.
1836    */
1837   struct GNUNET_MQ_Handle *mq;
1838
1839   /**
1840    * DLL with handles to single requests from the client
1841    */
1842   struct ReplyCls *rep_cls_head;
1843   struct ReplyCls *rep_cls_tail;
1844
1845   /**
1846    * The client handle to send the reply to
1847    */
1848   struct GNUNET_SERVICE_Client *client;
1849 };
1850
1851 /**
1852  * DLL with all clients currently connected to us
1853  */
1854 struct ClientContext *cli_ctx_head;
1855 struct ClientContext *cli_ctx_tail;
1856
1857 /***********************************************************************
1858  * /Housekeeping with clients
1859 ***********************************************************************/
1860
1861
1862
1863
1864
1865 /***********************************************************************
1866  * Globals
1867 ***********************************************************************/
1868
1869 /**
1870  * Sampler used for the Brahms protocol itself.
1871  */
1872 static struct RPS_Sampler *prot_sampler;
1873
1874 /**
1875  * Sampler used for the clients.
1876  */
1877 static struct RPS_Sampler *client_sampler;
1878
1879 /**
1880  * Name to log view to
1881  */
1882 static char *file_name_view_log;
1883
1884 /**
1885  * The size of sampler we need to be able to satisfy the client's need
1886  * of random peers.
1887  */
1888 static unsigned int sampler_size_client_need;
1889
1890 /**
1891  * The size of sampler we need to be able to satisfy the Brahms protocol's
1892  * need of random peers.
1893  *
1894  * This is one minimum size the sampler grows to.
1895  */
1896 static unsigned int sampler_size_est_need;
1897
1898 /**
1899  * Percentage of total peer number in the view
1900  * to send random PUSHes to
1901  */
1902 static float alpha;
1903
1904 /**
1905  * Percentage of total peer number in the view
1906  * to send random PULLs to
1907  */
1908 static float beta;
1909
1910 /**
1911  * Identifier for the main task that runs periodically.
1912  */
1913 static struct GNUNET_SCHEDULER_Task *do_round_task;
1914
1915 /**
1916  * Time inverval the do_round task runs in.
1917  */
1918 static struct GNUNET_TIME_Relative round_interval;
1919
1920 /**
1921  * List to store peers received through pushes temporary.
1922  */
1923 static struct CustomPeerMap *push_map;
1924
1925 /**
1926  * List to store peers received through pulls temporary.
1927  */
1928 static struct CustomPeerMap *pull_map;
1929
1930 /**
1931  * Handler to NSE.
1932  */
1933 static struct GNUNET_NSE_Handle *nse;
1934
1935 /**
1936  * Handler to CADET.
1937  */
1938 static struct GNUNET_CADET_Handle *cadet_handle;
1939
1940 /**
1941  * @brief Port to communicate to other peers.
1942  */
1943 static struct GNUNET_CADET_Port *cadet_port;
1944
1945 /**
1946  * Handler to PEERINFO.
1947  */
1948 static struct GNUNET_PEERINFO_Handle *peerinfo_handle;
1949
1950 /**
1951  * Handle for cancellation of iteration over peers.
1952  */
1953 static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify_handle;
1954
1955 /**
1956  * Request counter.
1957  *
1958  * Counts how many requets clients already issued.
1959  * Only needed in the beginning to check how many of the 64 deltas
1960  * we already have
1961  */
1962 static unsigned int req_counter;
1963
1964 /**
1965  * Time of the last request we received.
1966  *
1967  * Used to compute the expected request rate.
1968  */
1969 static struct GNUNET_TIME_Absolute last_request;
1970
1971 /**
1972  * Size of #request_deltas.
1973  */
1974 #define REQUEST_DELTAS_SIZE 64
1975 static unsigned int request_deltas_size = REQUEST_DELTAS_SIZE;
1976
1977 /**
1978  * Last 64 deltas between requests
1979  */
1980 static struct GNUNET_TIME_Relative request_deltas[REQUEST_DELTAS_SIZE];
1981
1982 /**
1983  * The prediction of the rate of requests
1984  */
1985 static struct GNUNET_TIME_Relative request_rate;
1986
1987
1988 #ifdef ENABLE_MALICIOUS
1989 /**
1990  * Type of malicious peer
1991  *
1992  * 0 Don't act malicious at all - Default
1993  * 1 Try to maximise representation
1994  * 2 Try to partition the network
1995  * 3 Combined attack
1996  */
1997 static uint32_t mal_type;
1998
1999 /**
2000  * Other malicious peers
2001  */
2002 static struct GNUNET_PeerIdentity *mal_peers;
2003
2004 /**
2005  * Hashmap of malicious peers used as set.
2006  * Used to more efficiently check whether we know that peer.
2007  */
2008 static struct GNUNET_CONTAINER_MultiPeerMap *mal_peer_set;
2009
2010 /**
2011  * Number of other malicious peers
2012  */
2013 static uint32_t num_mal_peers;
2014
2015
2016 /**
2017  * If type is 2 This struct is used to store the attacked peers in a DLL
2018  */
2019 struct AttackedPeer
2020 {
2021   /**
2022    * DLL
2023    */
2024   struct AttackedPeer *next;
2025   struct AttackedPeer *prev;
2026
2027   /**
2028    * PeerID
2029    */
2030   struct GNUNET_PeerIdentity peer_id;
2031 };
2032
2033 /**
2034  * If type is 2 this is the DLL of attacked peers
2035  */
2036 static struct AttackedPeer *att_peers_head;
2037 static struct AttackedPeer *att_peers_tail;
2038
2039 /**
2040  * This index is used to point to an attacked peer to
2041  * implement the round-robin-ish way to select attacked peers.
2042  */
2043 static struct AttackedPeer *att_peer_index;
2044
2045 /**
2046  * Hashmap of attacked peers used as set.
2047  * Used to more efficiently check whether we know that peer.
2048  */
2049 static struct GNUNET_CONTAINER_MultiPeerMap *att_peer_set;
2050
2051 /**
2052  * Number of attacked peers
2053  */
2054 static uint32_t num_attacked_peers;
2055
2056 /**
2057  * If type is 1 this is the attacked peer
2058  */
2059 static struct GNUNET_PeerIdentity attacked_peer;
2060
2061 /**
2062  * The limit of PUSHes we can send in one round.
2063  * This is an assumption of the Brahms protocol and either implemented
2064  * via proof of work
2065  * or
2066  * assumend to be the bandwidth limitation.
2067  */
2068 static uint32_t push_limit = 10000;
2069 #endif /* ENABLE_MALICIOUS */
2070
2071
2072 /***********************************************************************
2073  * /Globals
2074 ***********************************************************************/
2075
2076
2077 /***********************************************************************
2078  * Util functions
2079 ***********************************************************************/
2080
2081
2082 /**
2083  * Print peerlist to log.
2084  */
2085 static void
2086 print_peer_list (struct GNUNET_PeerIdentity *list,
2087                  unsigned int len)
2088 {
2089   unsigned int i;
2090
2091   LOG (GNUNET_ERROR_TYPE_DEBUG,
2092        "Printing peer list of length %u at %p:\n",
2093        len,
2094        list);
2095   for (i = 0 ; i < len ; i++)
2096   {
2097     LOG (GNUNET_ERROR_TYPE_DEBUG,
2098          "%u. peer: %s\n",
2099          i, GNUNET_i2s (&list[i]));
2100   }
2101 }
2102
2103
2104 /**
2105  * Remove peer from list.
2106  */
2107 static void
2108 rem_from_list (struct GNUNET_PeerIdentity **peer_list,
2109                unsigned int *list_size,
2110                const struct GNUNET_PeerIdentity *peer)
2111 {
2112   unsigned int i;
2113   struct GNUNET_PeerIdentity *tmp;
2114
2115   tmp = *peer_list;
2116
2117   LOG (GNUNET_ERROR_TYPE_DEBUG,
2118        "Removing peer %s from list at %p\n",
2119        GNUNET_i2s (peer),
2120        tmp);
2121
2122   for ( i = 0 ; i < *list_size ; i++ )
2123   {
2124     if (0 == GNUNET_CRYPTO_cmp_peer_identity (&tmp[i], peer))
2125     {
2126       if (i < *list_size -1)
2127       { /* Not at the last entry -- shift peers left */
2128         memmove (&tmp[i], &tmp[i +1],
2129                 ((*list_size) - i -1) * sizeof (struct GNUNET_PeerIdentity));
2130       }
2131       /* Remove last entry (should be now useless PeerID) */
2132       GNUNET_array_grow (tmp, *list_size, (*list_size) -1);
2133     }
2134   }
2135   *peer_list = tmp;
2136 }
2137
2138
2139 /**
2140  * Sum all time relatives of an array.
2141  */
2142 static struct GNUNET_TIME_Relative
2143 T_relative_sum (const struct GNUNET_TIME_Relative *rel_array,
2144                 uint32_t arr_size)
2145 {
2146   struct GNUNET_TIME_Relative sum;
2147   uint32_t i;
2148
2149   sum = GNUNET_TIME_UNIT_ZERO;
2150   for ( i = 0 ; i < arr_size ; i++ )
2151   {
2152     sum = GNUNET_TIME_relative_add (sum, rel_array[i]);
2153   }
2154   return sum;
2155 }
2156
2157
2158 /**
2159  * Compute the average of given time relatives.
2160  */
2161 static struct GNUNET_TIME_Relative
2162 T_relative_avg (const struct GNUNET_TIME_Relative *rel_array,
2163                 uint32_t arr_size)
2164 {
2165   return GNUNET_TIME_relative_divide (T_relative_sum (rel_array,
2166                                                       arr_size),
2167                                       arr_size);
2168 }
2169
2170
2171 /**
2172  * Insert PeerID in #view
2173  *
2174  * Called once we know a peer is live.
2175  * Implements #PeerOp
2176  *
2177  * @return GNUNET_OK if peer was actually inserted
2178  *         GNUNET_NO if peer was not inserted
2179  */
2180 static void
2181 insert_in_view_op (void *cls,
2182                 const struct GNUNET_PeerIdentity *peer);
2183
2184 /**
2185  * Insert PeerID in #view
2186  *
2187  * Called once we know a peer is live.
2188  *
2189  * @return GNUNET_OK if peer was actually inserted
2190  *         GNUNET_NO if peer was not inserted
2191  */
2192 static int
2193 insert_in_view (const struct GNUNET_PeerIdentity *peer)
2194 {
2195   int online;
2196
2197   online = Peers_check_peer_flag (peer, Peers_ONLINE);
2198   if ( (GNUNET_NO == online) ||
2199        (GNUNET_SYSERR == online) ) /* peer is not even known */
2200   {
2201     (void) Peers_issue_peer_liveliness_check (peer);
2202     (void) Peers_schedule_operation (peer, insert_in_view_op);
2203     return GNUNET_NO;
2204   }
2205   /* Open channel towards peer to keep connection open */
2206   Peers_indicate_sending_intention (peer);
2207   return View_put (peer);
2208 }
2209
2210 /**
2211  * Put random peer from sampler into the view as history update.
2212  */
2213 static void
2214 hist_update (void *cls,
2215              struct GNUNET_PeerIdentity *ids,
2216              uint32_t num_peers)
2217 {
2218   unsigned int i;
2219
2220   for (i = 0; i < num_peers; i++)
2221   {
2222     (void) insert_in_view (&ids[i]);
2223     to_file (file_name_view_log,
2224              "+%s\t(hist)",
2225              GNUNET_i2s_full (ids));
2226   }
2227 }
2228
2229
2230 /**
2231  * Wrapper around #RPS_sampler_resize()
2232  *
2233  * If we do not have enough sampler elements, double current sampler size
2234  * If we have more than enough sampler elements, halv current sampler size
2235  */
2236 static void
2237 resize_wrapper (struct RPS_Sampler *sampler, uint32_t new_size)
2238 {
2239   unsigned int sampler_size;
2240
2241   // TODO statistics
2242   // TODO respect the min, max
2243   sampler_size = RPS_sampler_get_size (sampler);
2244   if (sampler_size > new_size * 4)
2245   { /* Shrinking */
2246     RPS_sampler_resize (sampler, sampler_size / 2);
2247   }
2248   else if (sampler_size < new_size)
2249   { /* Growing */
2250     RPS_sampler_resize (sampler, sampler_size * 2);
2251   }
2252   LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler_size is now %u\n", sampler_size);
2253 }
2254
2255
2256 /**
2257  * Wrapper around #RPS_sampler_resize() resizing the client sampler
2258  */
2259 static void
2260 client_resize_wrapper ()
2261 {
2262   uint32_t bigger_size;
2263
2264   // TODO statistics
2265
2266   bigger_size = GNUNET_MAX (sampler_size_est_need, sampler_size_client_need);
2267
2268   // TODO respect the min, max
2269   resize_wrapper (client_sampler, bigger_size);
2270   LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler_size_client is now %" PRIu32 "\n",
2271       bigger_size);
2272 }
2273
2274
2275 /**
2276  * Estimate request rate
2277  *
2278  * Called every time we receive a request from the client.
2279  */
2280 static void
2281 est_request_rate()
2282 {
2283   struct GNUNET_TIME_Relative max_round_duration;
2284
2285   if (request_deltas_size > req_counter)
2286     req_counter++;
2287   if ( 1 < req_counter)
2288   {
2289     /* Shift last request deltas to the right */
2290     memmove (&request_deltas[1],
2291         request_deltas,
2292         (req_counter - 1) * sizeof (struct GNUNET_TIME_Relative));
2293
2294     /* Add current delta to beginning */
2295     request_deltas[0] =
2296         GNUNET_TIME_absolute_get_difference (last_request,
2297                                              GNUNET_TIME_absolute_get ());
2298     request_rate = T_relative_avg (request_deltas, req_counter);
2299     request_rate = (request_rate.rel_value_us < 1) ?
2300       GNUNET_TIME_relative_get_unit_ () : request_rate;
2301
2302     /* Compute the duration a round will maximally take */
2303     max_round_duration =
2304         GNUNET_TIME_relative_add (round_interval,
2305                                   GNUNET_TIME_relative_divide (round_interval, 2));
2306
2307     /* Set the estimated size the sampler has to have to
2308      * satisfy the current client request rate */
2309     sampler_size_client_need =
2310         max_round_duration.rel_value_us / request_rate.rel_value_us;
2311
2312     /* Resize the sampler */
2313     client_resize_wrapper ();
2314   }
2315   last_request = GNUNET_TIME_absolute_get ();
2316 }
2317
2318
2319 /**
2320  * Add all peers in @a peer_array to @a peer_map used as set.
2321  *
2322  * @param peer_array array containing the peers
2323  * @param num_peers number of peers in @peer_array
2324  * @param peer_map the peermap to use as set
2325  */
2326 static void
2327 add_peer_array_to_set (const struct GNUNET_PeerIdentity *peer_array,
2328                        unsigned int num_peers,
2329                        struct GNUNET_CONTAINER_MultiPeerMap *peer_map)
2330 {
2331   unsigned int i;
2332   if (NULL == peer_map)
2333   {
2334     LOG (GNUNET_ERROR_TYPE_WARNING,
2335          "Trying to add peers to non-existing peermap.\n");
2336     return;
2337   }
2338
2339   for (i = 0; i < num_peers; i++)
2340   {
2341     GNUNET_CONTAINER_multipeermap_put (peer_map,
2342                                        &peer_array[i],
2343                                        NULL,
2344                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
2345   }
2346 }
2347
2348
2349 /**
2350  * Send a PULL REPLY to @a peer_id
2351  *
2352  * @param peer_id the peer to send the reply to.
2353  * @param peer_ids the peers to send to @a peer_id
2354  * @param num_peer_ids the number of peers to send to @a peer_id
2355  */
2356 static void
2357 send_pull_reply (const struct GNUNET_PeerIdentity *peer_id,
2358                  const struct GNUNET_PeerIdentity *peer_ids,
2359                  unsigned int num_peer_ids)
2360 {
2361   uint32_t send_size;
2362   struct GNUNET_MQ_Envelope *ev;
2363   struct GNUNET_RPS_P2P_PullReplyMessage *out_msg;
2364
2365   /* Compute actual size */
2366   send_size = sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) +
2367               num_peer_ids * sizeof (struct GNUNET_PeerIdentity);
2368
2369   if (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < send_size)
2370     /* Compute number of peers to send
2371      * If too long, simply truncate */
2372     // TODO select random ones via permutation
2373     //      or even better: do good protocol design
2374     send_size =
2375       (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE -
2376        sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
2377        sizeof (struct GNUNET_PeerIdentity);
2378   else
2379     send_size = num_peer_ids;
2380
2381   LOG (GNUNET_ERROR_TYPE_DEBUG,
2382       "Going to send PULL REPLY with %u peers to %s\n",
2383       send_size, GNUNET_i2s (peer_id));
2384
2385   ev = GNUNET_MQ_msg_extra (out_msg,
2386                             send_size * sizeof (struct GNUNET_PeerIdentity),
2387                             GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY);
2388   out_msg->num_peers = htonl (send_size);
2389   GNUNET_memcpy (&out_msg[1], peer_ids,
2390          send_size * sizeof (struct GNUNET_PeerIdentity));
2391
2392   Peers_send_message (peer_id, ev, "PULL REPLY");
2393 }
2394
2395
2396 /**
2397  * Insert PeerID in #pull_map
2398  *
2399  * Called once we know a peer is live.
2400  */
2401 static void
2402 insert_in_pull_map (void *cls,
2403                     const struct GNUNET_PeerIdentity *peer)
2404 {
2405   CustomPeerMap_put (pull_map, peer);
2406 }
2407
2408
2409 /**
2410  * Insert PeerID in #view
2411  *
2412  * Called once we know a peer is live.
2413  * Implements #PeerOp
2414  */
2415 static void
2416 insert_in_view_op (void *cls,
2417                 const struct GNUNET_PeerIdentity *peer)
2418 {
2419   (void) insert_in_view (peer);
2420 }
2421
2422
2423 /**
2424  * Update sampler with given PeerID.
2425  * Implements #PeerOp
2426  */
2427 static void
2428 insert_in_sampler (void *cls,
2429                    const struct GNUNET_PeerIdentity *peer)
2430 {
2431   LOG (GNUNET_ERROR_TYPE_DEBUG,
2432        "Updating samplers with peer %s from insert_in_sampler()\n",
2433        GNUNET_i2s (peer));
2434   RPS_sampler_update (prot_sampler,   peer);
2435   RPS_sampler_update (client_sampler, peer);
2436   if (0 < RPS_sampler_count_id (prot_sampler, peer))
2437   {
2438     /* Make sure we 'know' about this peer */
2439     (void) Peers_issue_peer_liveliness_check (peer);
2440     /* Establish a channel towards that peer to indicate we are going to send
2441      * messages to it */
2442     //Peers_indicate_sending_intention (peer);
2443   }
2444 }
2445
2446 /**
2447  * @brief This is called on peers from external sources (cadet, peerinfo, ...)
2448  *        If the peer is not known, liveliness check is issued and it is
2449  *        scheduled to be inserted in sampler and view.
2450  *
2451  * "External sources" refer to every source except the gossip.
2452  *
2453  * @param peer peer to insert
2454  */
2455 static void
2456 got_peer (const struct GNUNET_PeerIdentity *peer)
2457 {
2458   /* If we did not know this peer already, insert it into sampler and view */
2459   if (GNUNET_YES == Peers_issue_peer_liveliness_check (peer))
2460   {
2461     Peers_schedule_operation (peer, insert_in_sampler);
2462     Peers_schedule_operation (peer, insert_in_view_op);
2463   }
2464 }
2465
2466 /**
2467  * @brief Checks if there is a sending channel and if it is needed
2468  *
2469  * @param peer the peer whose sending channel is checked
2470  * @return GNUNET_YES if sending channel exists and is still needed
2471  *         GNUNET_NO  otherwise
2472  */
2473 static int
2474 check_sending_channel_needed (const struct GNUNET_PeerIdentity *peer)
2475 {
2476   /* struct GNUNET_CADET_Channel *channel; */
2477   if (GNUNET_NO == Peers_check_peer_known (peer))
2478   {
2479     return GNUNET_NO;
2480   }
2481   if (GNUNET_YES == Peers_check_sending_channel_exists (peer))
2482   {
2483     if ( (0 < RPS_sampler_count_id (prot_sampler, peer)) ||
2484          (GNUNET_YES == View_contains_peer (peer)) ||
2485          (GNUNET_YES == CustomPeerMap_contains_peer (push_map, peer)) ||
2486          (GNUNET_YES == CustomPeerMap_contains_peer (pull_map, peer)) ||
2487          (GNUNET_YES == Peers_check_peer_flag (peer, Peers_PULL_REPLY_PENDING)))
2488     { /* If we want to keep the connection to peer open */
2489       return GNUNET_YES;
2490     }
2491     return GNUNET_NO;
2492   }
2493   return GNUNET_NO;
2494 }
2495
2496 /**
2497  * @brief remove peer from our knowledge, the view, push and pull maps and
2498  * samplers.
2499  *
2500  * @param peer the peer to remove
2501  */
2502 static void
2503 remove_peer (const struct GNUNET_PeerIdentity *peer)
2504 {
2505   (void) View_remove_peer (peer);
2506   CustomPeerMap_remove_peer (pull_map, peer);
2507   CustomPeerMap_remove_peer (push_map, peer);
2508   RPS_sampler_reinitialise_by_value (prot_sampler, peer);
2509   RPS_sampler_reinitialise_by_value (client_sampler, peer);
2510   Peers_remove_peer (peer);
2511 }
2512
2513
2514 /**
2515  * @brief Remove data that is not needed anymore.
2516  *
2517  * If the sending channel is no longer needed it is destroyed.
2518  *
2519  * @param peer the peer whose data is about to be cleaned
2520  */
2521 static void
2522 clean_peer (const struct GNUNET_PeerIdentity *peer)
2523 {
2524   if (GNUNET_NO == check_sending_channel_needed (peer))
2525   {
2526     LOG (GNUNET_ERROR_TYPE_DEBUG,
2527         "Going to remove send channel to peer %s\n",
2528         GNUNET_i2s (peer));
2529     #ifdef ENABLE_MALICIOUS
2530     if (0 != GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
2531       (void) Peers_destroy_sending_channel (peer);
2532     #else /* ENABLE_MALICIOUS */
2533     (void) Peers_destroy_sending_channel (peer);
2534     #endif /* ENABLE_MALICIOUS */
2535   }
2536
2537   if ( (GNUNET_NO == Peers_check_peer_send_intention (peer)) &&
2538        (GNUNET_NO == View_contains_peer (peer)) &&
2539        (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
2540        (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
2541        (0 == RPS_sampler_count_id (prot_sampler,   peer)) &&
2542        (0 == RPS_sampler_count_id (client_sampler, peer)) &&
2543        (GNUNET_NO != Peers_check_removable (peer)) )
2544   { /* We can safely remove this peer */
2545     LOG (GNUNET_ERROR_TYPE_DEBUG,
2546         "Going to remove peer %s\n",
2547         GNUNET_i2s (peer));
2548     remove_peer (peer);
2549     return;
2550   }
2551 }
2552
2553 /**
2554  * @brief This is called when a channel is destroyed.
2555  *
2556  * Removes peer completely from our knowledge if the send_channel was destroyed
2557  * Otherwise simply delete the recv_channel
2558  * Also check if the knowledge about this peer is still needed.
2559  * If not, remove this peer from our knowledge.
2560  *
2561  * @param cls The closure
2562  * @param channel The channel being closed
2563  * @param channel_ctx The context associated with this channel
2564  */
2565 static void
2566 cleanup_destroyed_channel (void *cls,
2567                            const struct GNUNET_CADET_Channel *channel)
2568 {
2569   struct GNUNET_PeerIdentity *peer = cls;
2570   uint32_t *channel_flag;
2571   struct PeerContext *peer_ctx;
2572
2573   if (GNUNET_NO == Peers_check_peer_known (peer))
2574   { /* We don't know a context to that peer */
2575     LOG (GNUNET_ERROR_TYPE_WARNING,
2576          "channel (%s) without associated context was destroyed\n",
2577          GNUNET_i2s (peer));
2578     return;
2579   }
2580
2581   peer_ctx = get_peer_ctx (peer);
2582   if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING))
2583   {
2584     set_channel_flag (peer_ctx->recv_channel_flags, Peers_CHANNEL_DESTROING);
2585   } else if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING))
2586   {
2587     set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_DESTROING);
2588   }
2589
2590   if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY))
2591   { /* We are in the middle of removing that peer from our knowledge. In this
2592        case simply make sure that the channels are cleaned. */
2593     Peers_cleanup_destroyed_channel (cls, channel);
2594     to_file (file_name_view_log,
2595              "-%s\t(cleanup channel, ourself)",
2596              GNUNET_i2s_full (peer));
2597     return;
2598   }
2599
2600   if (GNUNET_YES ==
2601       Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING))
2602   { /* Channel used for sending was destroyed */
2603     /* Possible causes of channel destruction:
2604      *  - ourselves  -> cleaning send channel -> clean context
2605      *  - other peer -> peer probably went down -> remove
2606      */
2607     channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING);
2608     if (GNUNET_YES == Peers_check_channel_flag (channel_flag, Peers_CHANNEL_CLEAN))
2609     { /* We are about to clean the sending channel. Clean the respective
2610        * context */
2611       Peers_cleanup_destroyed_channel (cls, channel);
2612       return;
2613     }
2614     else
2615     { /* Other peer destroyed our sending channel that he is supposed to keep
2616        * open. It probably went down. Remove it from our knowledge. */
2617       Peers_cleanup_destroyed_channel (cls, channel);
2618       remove_peer (peer);
2619       return;
2620     }
2621   }
2622   else if (GNUNET_YES ==
2623       Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING))
2624   { /* Channel used for receiving was destroyed */
2625     /* Possible causes of channel destruction:
2626      *  - ourselves  -> peer tried to establish channel twice -> clean context
2627      *  - other peer -> peer doesn't want to send us data -> clean
2628      */
2629     channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING);
2630     if (GNUNET_YES ==
2631         Peers_check_channel_flag (channel_flag, Peers_CHANNEL_ESTABLISHED_TWICE))
2632     { /* Other peer tried to establish a channel to us twice. We do not accept
2633        * that. Clean the context. */
2634       Peers_cleanup_destroyed_channel (cls, channel);
2635       return;
2636     }
2637     else
2638     { /* Other peer doesn't want to send us data anymore. We are free to clean
2639        * it. */
2640       Peers_cleanup_destroyed_channel (cls, channel);
2641       clean_peer (peer);
2642       return;
2643     }
2644   }
2645   else
2646   {
2647     LOG (GNUNET_ERROR_TYPE_WARNING,
2648         "Destroyed channel is neither sending nor receiving channel\n");
2649   }
2650 }
2651
2652 /***********************************************************************
2653  * /Util functions
2654 ***********************************************************************/
2655
2656 static void
2657 destroy_reply_cls (struct ReplyCls *rep_cls)
2658 {
2659   struct ClientContext *cli_ctx;
2660
2661   cli_ctx = rep_cls->cli_ctx;
2662   GNUNET_assert (NULL != cli_ctx);
2663   if (NULL != rep_cls->req_handle)
2664   {
2665     RPS_sampler_request_cancel (rep_cls->req_handle);
2666   }
2667   GNUNET_CONTAINER_DLL_remove (cli_ctx->rep_cls_head,
2668                                cli_ctx->rep_cls_tail,
2669                                rep_cls);
2670   GNUNET_free (rep_cls);
2671 }
2672
2673
2674 static void
2675 destroy_cli_ctx (struct ClientContext *cli_ctx)
2676 {
2677   GNUNET_assert (NULL != cli_ctx);
2678   if (NULL != cli_ctx->rep_cls_head)
2679   {
2680     LOG (GNUNET_ERROR_TYPE_WARNING,
2681          "Trying to destroy the context of a client that still has pending requests. Going to clean those\n");
2682     while (NULL != cli_ctx->rep_cls_head)
2683       destroy_reply_cls (cli_ctx->rep_cls_head);
2684   }
2685   GNUNET_CONTAINER_DLL_remove (cli_ctx_head,
2686                                cli_ctx_tail,
2687                                cli_ctx);
2688   GNUNET_free (cli_ctx);
2689 }
2690
2691
2692 /**
2693  * Function called by NSE.
2694  *
2695  * Updates sizes of sampler list and view and adapt those lists
2696  * accordingly.
2697  */
2698 static void
2699 nse_callback (void *cls,
2700               struct GNUNET_TIME_Absolute timestamp,
2701               double logestimate, double std_dev)
2702 {
2703   double estimate;
2704   //double scale; // TODO this might go gloabal/config
2705
2706   LOG (GNUNET_ERROR_TYPE_DEBUG,
2707        "Received a ns estimate - logest: %f, std_dev: %f (old_size: %u)\n",
2708        logestimate, std_dev, RPS_sampler_get_size (prot_sampler));
2709   //scale = .01;
2710   estimate = GNUNET_NSE_log_estimate_to_n (logestimate);
2711   // GNUNET_NSE_log_estimate_to_n (logestimate);
2712   estimate = pow (estimate, 1.0 / 3);
2713   // TODO add if std_dev is a number
2714   // estimate += (std_dev * scale);
2715   if (2 < ceil (estimate))
2716   {
2717     LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing estimate to %f\n", estimate);
2718     sampler_size_est_need = estimate;
2719   } else
2720     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not using estimate %f\n", estimate);
2721
2722   /* If the NSE has changed adapt the lists accordingly */
2723   resize_wrapper (prot_sampler, sampler_size_est_need);
2724   client_resize_wrapper ();
2725 }
2726
2727
2728 /**
2729  * Callback called once the requested PeerIDs are ready.
2730  *
2731  * Sends those to the requesting client.
2732  */
2733 static void
2734 client_respond (void *cls,
2735                 struct GNUNET_PeerIdentity *peer_ids,
2736                 uint32_t num_peers)
2737 {
2738   struct ReplyCls *reply_cls = cls;
2739   uint32_t i;
2740   struct GNUNET_MQ_Envelope *ev;
2741   struct GNUNET_RPS_CS_ReplyMessage *out_msg;
2742   uint32_t size_needed;
2743   struct ClientContext *cli_ctx;
2744
2745   GNUNET_assert (NULL != reply_cls);
2746   LOG (GNUNET_ERROR_TYPE_DEBUG,
2747        "sampler returned %" PRIu32 " peers:\n",
2748        num_peers);
2749   for (i = 0; i < num_peers; i++)
2750   {
2751     LOG (GNUNET_ERROR_TYPE_DEBUG,
2752          "  %" PRIu32 ": %s\n",
2753          i,
2754          GNUNET_i2s (&peer_ids[i]));
2755   }
2756
2757   size_needed = sizeof (struct GNUNET_RPS_CS_ReplyMessage) +
2758                 num_peers * sizeof (struct GNUNET_PeerIdentity);
2759
2760   GNUNET_assert (GNUNET_MAX_MESSAGE_SIZE >= size_needed);
2761
2762   ev = GNUNET_MQ_msg_extra (out_msg,
2763                             num_peers * sizeof (struct GNUNET_PeerIdentity),
2764                             GNUNET_MESSAGE_TYPE_RPS_CS_REPLY);
2765   out_msg->num_peers = htonl (num_peers);
2766   out_msg->id = htonl (reply_cls->id);
2767
2768   GNUNET_memcpy (&out_msg[1],
2769           peer_ids,
2770           num_peers * sizeof (struct GNUNET_PeerIdentity));
2771   GNUNET_free (peer_ids);
2772
2773   cli_ctx = reply_cls->cli_ctx;
2774   GNUNET_assert (NULL != cli_ctx);
2775   reply_cls->req_handle = NULL;
2776   destroy_reply_cls (reply_cls);
2777   GNUNET_MQ_send (cli_ctx->mq, ev);
2778 }
2779
2780
2781 /**
2782  * Handle RPS request from the client.
2783  *
2784  * @param cls closure
2785  * @param message the actual message
2786  */
2787 static void
2788 handle_client_request (void *cls,
2789                        const struct GNUNET_RPS_CS_RequestMessage *msg)
2790 {
2791   struct ClientContext *cli_ctx = cls;
2792   uint32_t num_peers;
2793   uint32_t size_needed;
2794   struct ReplyCls *reply_cls;
2795   uint32_t i;
2796
2797   num_peers = ntohl (msg->num_peers);
2798   size_needed = sizeof (struct GNUNET_RPS_CS_RequestMessage) +
2799                 num_peers * sizeof (struct GNUNET_PeerIdentity);
2800
2801   if (GNUNET_MAX_MESSAGE_SIZE < size_needed)
2802   {
2803     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2804                 "Message received from client has size larger than expected\n");
2805     GNUNET_SERVICE_client_drop (cli_ctx->client);
2806     return;
2807   }
2808
2809   for (i = 0 ; i < num_peers ; i++)
2810     est_request_rate();
2811
2812   LOG (GNUNET_ERROR_TYPE_DEBUG,
2813        "Client requested %" PRIu32 " random peer(s).\n",
2814        num_peers);
2815
2816   reply_cls = GNUNET_new (struct ReplyCls);
2817   reply_cls->id = ntohl (msg->id);
2818   reply_cls->cli_ctx = cli_ctx;
2819   reply_cls->req_handle = RPS_sampler_get_n_rand_peers (client_sampler,
2820                                                         client_respond,
2821                                                         reply_cls,
2822                                                         num_peers);
2823
2824   GNUNET_assert (NULL != cli_ctx);
2825   GNUNET_CONTAINER_DLL_insert (cli_ctx->rep_cls_head,
2826                                cli_ctx->rep_cls_tail,
2827                                reply_cls);
2828   GNUNET_SERVICE_client_continue (cli_ctx->client);
2829 }
2830
2831
2832 /**
2833  * @brief Handle a message that requests the cancellation of a request
2834  *
2835  * @param cls unused
2836  * @param message the message containing the id of the request
2837  */
2838 static void
2839 handle_client_request_cancel (void *cls,
2840                               const struct GNUNET_RPS_CS_RequestCancelMessage *msg)
2841 {
2842   struct ClientContext *cli_ctx = cls;
2843   struct ReplyCls *rep_cls;
2844
2845   GNUNET_assert (NULL != cli_ctx);
2846   GNUNET_assert (NULL != cli_ctx->rep_cls_head);
2847   rep_cls = cli_ctx->rep_cls_head;
2848   LOG (GNUNET_ERROR_TYPE_DEBUG,
2849       "Client cancels request with id %" PRIu32 "\n",
2850       ntohl (msg->id));
2851   while ( (NULL != rep_cls->next) &&
2852           (rep_cls->id != ntohl (msg->id)) )
2853     rep_cls = rep_cls->next;
2854   GNUNET_assert (rep_cls->id == ntohl (msg->id));
2855   destroy_reply_cls (rep_cls);
2856   GNUNET_SERVICE_client_continue (cli_ctx->client);
2857 }
2858
2859
2860 /**
2861  * @brief This function is called, when the client seeds peers.
2862  * It verifies that @a msg is well-formed.
2863  *
2864  * @param cls the closure (#ClientContext)
2865  * @param msg the message
2866  * @return #GNUNET_OK if @a msg is well-formed
2867  */
2868 static int
2869 check_client_seed (void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
2870 {
2871   struct ClientContext *cli_ctx = cls;
2872   uint16_t msize = ntohs (msg->header.size);
2873   uint32_t num_peers = ntohl (msg->num_peers);
2874
2875   msize -= sizeof (struct GNUNET_RPS_CS_SeedMessage);
2876   if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
2877        (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
2878   {
2879     GNUNET_break (0);
2880     GNUNET_SERVICE_client_drop (cli_ctx->client);
2881     return GNUNET_SYSERR;
2882   }
2883   return GNUNET_OK;
2884 }
2885
2886
2887 /**
2888  * Handle seed from the client.
2889  *
2890  * @param cls closure
2891  * @param message the actual message
2892  */
2893 static void
2894 handle_client_seed (void *cls,
2895                     const struct GNUNET_RPS_CS_SeedMessage *msg)
2896 {
2897   struct ClientContext *cli_ctx = cls;
2898   struct GNUNET_PeerIdentity *peers;
2899   uint32_t num_peers;
2900   uint32_t i;
2901
2902   num_peers = ntohl (msg->num_peers);
2903   peers = (struct GNUNET_PeerIdentity *) &msg[1];
2904   //peers = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
2905   //GNUNET_memcpy (peers, &msg[1], num_peers * sizeof (struct GNUNET_PeerIdentity));
2906
2907   LOG (GNUNET_ERROR_TYPE_DEBUG,
2908        "Client seeded peers:\n");
2909   print_peer_list (peers, num_peers);
2910
2911   for (i = 0; i < num_peers; i++)
2912   {
2913     LOG (GNUNET_ERROR_TYPE_DEBUG,
2914          "Updating samplers with seed %" PRIu32 ": %s\n",
2915          i,
2916          GNUNET_i2s (&peers[i]));
2917
2918     got_peer (&peers[i]);
2919   }
2920
2921   ////GNUNET_free (peers);
2922
2923   GNUNET_SERVICE_client_continue (cli_ctx->client);
2924 }
2925
2926 /**
2927  * Handle a CHECK_LIVE message from another peer.
2928  *
2929  * This does nothing. But without calling #GNUNET_CADET_receive_done()
2930  * the channel is blocked for all other communication.
2931  *
2932  * @param cls Closure
2933  * @param msg The message header
2934  */
2935 static void
2936 handle_peer_check (void *cls,
2937                    const struct GNUNET_MessageHeader *msg)
2938 {
2939   const struct GNUNET_PeerIdentity *peer = cls;
2940
2941   GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
2942 }
2943
2944 /**
2945  * Handle a PUSH message from another peer.
2946  *
2947  * Check the proof of work and store the PeerID
2948  * in the temporary list for pushed PeerIDs.
2949  *
2950  * @param cls Closure
2951  * @param msg The message header
2952  */
2953 static void
2954 handle_peer_push (void *cls,
2955                   const struct GNUNET_MessageHeader *msg)
2956 {
2957   const struct GNUNET_PeerIdentity *peer = cls;
2958
2959   // (check the proof of work (?))
2960
2961   LOG (GNUNET_ERROR_TYPE_DEBUG,
2962        "Received PUSH (%s)\n",
2963        GNUNET_i2s (peer));
2964
2965   #ifdef ENABLE_MALICIOUS
2966   struct AttackedPeer *tmp_att_peer;
2967
2968   if ( (1 == mal_type) ||
2969        (3 == mal_type) )
2970   { /* Try to maximise representation */
2971     tmp_att_peer = GNUNET_new (struct AttackedPeer);
2972     tmp_att_peer->peer_id = *peer;
2973     if (NULL == att_peer_set)
2974       att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
2975     if (GNUNET_NO ==
2976         GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
2977                                                 peer))
2978     {
2979       GNUNET_CONTAINER_DLL_insert (att_peers_head,
2980                                    att_peers_tail,
2981                                    tmp_att_peer);
2982       add_peer_array_to_set (peer, 1, att_peer_set);
2983     }
2984   }
2985
2986
2987   else if (2 == mal_type)
2988   {
2989     /* We attack one single well-known peer - simply ignore */
2990   }
2991   #endif /* ENABLE_MALICIOUS */
2992
2993   /* Add the sending peer to the push_map */
2994   CustomPeerMap_put (push_map, peer);
2995
2996   GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
2997 }
2998
2999
3000 /**
3001  * Handle PULL REQUEST request message from another peer.
3002  *
3003  * Reply with the view of PeerIDs.
3004  *
3005  * @param cls Closure
3006  * @param msg The message header
3007  */
3008 static void
3009 handle_peer_pull_request (void *cls,
3010                           const struct GNUNET_MessageHeader *msg)
3011 {
3012   struct GNUNET_PeerIdentity *peer = cls;
3013   const struct GNUNET_PeerIdentity *view_array;
3014
3015   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer));
3016
3017   #ifdef ENABLE_MALICIOUS
3018   if (1 == mal_type
3019       || 3 == mal_type)
3020   { /* Try to maximise representation */
3021     send_pull_reply (peer, mal_peers, num_mal_peers);
3022   }
3023
3024   else if (2 == mal_type)
3025   { /* Try to partition network */
3026     if (0 == GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
3027     {
3028       send_pull_reply (peer, mal_peers, num_mal_peers);
3029     }
3030   }
3031   #endif /* ENABLE_MALICIOUS */
3032
3033   view_array = View_get_as_array ();
3034   send_pull_reply (peer, view_array, View_size ());
3035
3036   GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
3037 }
3038
3039
3040 /**
3041  * Check whether we sent a corresponding request and
3042  * whether this reply is the first one.
3043  *
3044  * @param cls Closure
3045  * @param msg The message header
3046  */
3047 static int
3048 check_peer_pull_reply (void *cls,
3049                        const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3050 {
3051   struct GNUNET_PeerIdentity *sender = cls;
3052
3053   if (sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) > ntohs (msg->header.size))
3054   {
3055     GNUNET_break_op (0);
3056     return GNUNET_SYSERR;
3057   }
3058
3059   if ((ntohs (msg->header.size) - sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
3060       sizeof (struct GNUNET_PeerIdentity) != ntohl (msg->num_peers))
3061   {
3062     LOG (GNUNET_ERROR_TYPE_ERROR,
3063         "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3064         ntohl (msg->num_peers),
3065         (ntohs (msg->header.size) - sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
3066             sizeof (struct GNUNET_PeerIdentity));
3067     GNUNET_break_op (0);
3068     return GNUNET_SYSERR;
3069   }
3070
3071   if (GNUNET_YES != Peers_check_peer_flag (sender, Peers_PULL_REPLY_PENDING))
3072   {
3073     LOG (GNUNET_ERROR_TYPE_WARNING,
3074         "Received a pull reply from a peer we didn't request one from!\n");
3075     GNUNET_break_op (0);
3076     return GNUNET_SYSERR;
3077   }
3078   return GNUNET_OK;
3079 }
3080
3081 /**
3082  * Handle PULL REPLY message from another peer.
3083  *
3084  * @param cls Closure
3085  * @param msg The message header
3086  */
3087 static void
3088 handle_peer_pull_reply (void *cls,
3089                         const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3090 {
3091   const struct GNUNET_PeerIdentity *peers;
3092   struct GNUNET_PeerIdentity *sender = cls;
3093   uint32_t i;
3094 #ifdef ENABLE_MALICIOUS
3095   struct AttackedPeer *tmp_att_peer;
3096 #endif /* ENABLE_MALICIOUS */
3097
3098   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (sender));
3099
3100   #ifdef ENABLE_MALICIOUS
3101   // We shouldn't even receive pull replies as we're not sending
3102   if (2 == mal_type)
3103   {
3104   }
3105   #endif /* ENABLE_MALICIOUS */
3106
3107   /* Do actual logic */
3108   peers = (const struct GNUNET_PeerIdentity *) &msg[1];
3109
3110   LOG (GNUNET_ERROR_TYPE_DEBUG,
3111        "PULL REPLY received, got following %u peers:\n",
3112        ntohl (msg->num_peers));
3113
3114   for (i = 0; i < ntohl (msg->num_peers); i++)
3115   {
3116     LOG (GNUNET_ERROR_TYPE_DEBUG,
3117          "%u. %s\n",
3118          i,
3119          GNUNET_i2s (&peers[i]));
3120
3121     #ifdef ENABLE_MALICIOUS
3122     if ((NULL != att_peer_set) &&
3123         (1 == mal_type || 3 == mal_type))
3124     { /* Add attacked peer to local list */
3125       // TODO check if we sent a request and this was the first reply
3126       if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
3127                                                                &peers[i])
3128           && GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (mal_peer_set,
3129                                                                   &peers[i])
3130           && 0 != GNUNET_CRYPTO_cmp_peer_identity (&peers[i],
3131                                                    &own_identity))
3132       {
3133         tmp_att_peer = GNUNET_new (struct AttackedPeer);
3134         tmp_att_peer->peer_id = peers[i];
3135         GNUNET_CONTAINER_DLL_insert (att_peers_head,
3136                                      att_peers_tail,
3137                                      tmp_att_peer);
3138         add_peer_array_to_set (&peers[i], 1, att_peer_set);
3139       }
3140       continue;
3141     }
3142     #endif /* ENABLE_MALICIOUS */
3143     if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity,
3144                                               &peers[i]))
3145     {
3146       /* Make sure we 'know' about this peer */
3147       (void) Peers_insert_peer (&peers[i]);
3148
3149       if (GNUNET_YES == Peers_check_peer_valid (&peers[i]))
3150       {
3151         CustomPeerMap_put (pull_map, &peers[i]);
3152       }
3153       else
3154       {
3155         Peers_schedule_operation (&peers[i], insert_in_pull_map);
3156         (void) Peers_issue_peer_liveliness_check (&peers[i]);
3157       }
3158     }
3159   }
3160
3161   Peers_unset_peer_flag (sender, Peers_PULL_REPLY_PENDING);
3162   clean_peer (sender);
3163
3164   GNUNET_CADET_receive_done (Peers_get_recv_channel (sender));
3165 }
3166
3167
3168 /**
3169  * Compute a random delay.
3170  * A uniformly distributed value between mean + spread and mean - spread.
3171  *
3172  * For example for mean 4 min and spread 2 the minimum is (4 min - (1/2 * 4 min))
3173  * It would return a random value between 2 and 6 min.
3174  *
3175  * @param mean the mean
3176  * @param spread the inverse amount of deviation from the mean
3177  */
3178 static struct GNUNET_TIME_Relative
3179 compute_rand_delay (struct GNUNET_TIME_Relative mean,
3180                     unsigned int spread)
3181 {
3182   struct GNUNET_TIME_Relative half_interval;
3183   struct GNUNET_TIME_Relative ret;
3184   unsigned int rand_delay;
3185   unsigned int max_rand_delay;
3186
3187   if (0 == spread)
3188   {
3189     LOG (GNUNET_ERROR_TYPE_WARNING,
3190          "Not accepting spread of 0\n");
3191     GNUNET_break (0);
3192     GNUNET_assert (0);
3193   }
3194   GNUNET_assert (0 != mean.rel_value_us);
3195
3196   /* Compute random time value between spread * mean and spread * mean */
3197   half_interval = GNUNET_TIME_relative_divide (mean, spread);
3198
3199   max_rand_delay = GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us / mean.rel_value_us * (2/spread);
3200   /**
3201    * Compute random value between (0 and 1) * round_interval
3202    * via multiplying round_interval with a 'fraction' (0 to value)/value
3203    */
3204   rand_delay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_rand_delay);
3205   ret = GNUNET_TIME_relative_saturating_multiply (mean,  rand_delay);
3206   ret = GNUNET_TIME_relative_divide   (ret, max_rand_delay);
3207   ret = GNUNET_TIME_relative_add      (ret, half_interval);
3208
3209   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == ret.rel_value_us)
3210     LOG (GNUNET_ERROR_TYPE_WARNING,
3211          "Returning FOREVER_REL\n");
3212
3213   return ret;
3214 }
3215
3216
3217 /**
3218  * Send single pull request
3219  *
3220  * @param peer_id the peer to send the pull request to.
3221  */
3222 static void
3223 send_pull_request (const struct GNUNET_PeerIdentity *peer)
3224 {
3225   struct GNUNET_MQ_Envelope *ev;
3226
3227   GNUNET_assert (GNUNET_NO == Peers_check_peer_flag (peer,
3228                                                      Peers_PULL_REPLY_PENDING));
3229   Peers_set_peer_flag (peer, Peers_PULL_REPLY_PENDING);
3230
3231   LOG (GNUNET_ERROR_TYPE_DEBUG,
3232        "Going to send PULL REQUEST to peer %s.\n",
3233        GNUNET_i2s (peer));
3234
3235   ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST);
3236   Peers_send_message (peer, ev, "PULL REQUEST");
3237 }
3238
3239
3240 /**
3241  * Send single push
3242  *
3243  * @param peer_id the peer to send the push to.
3244  */
3245 static void
3246 send_push (const struct GNUNET_PeerIdentity *peer_id)
3247 {
3248   struct GNUNET_MQ_Envelope *ev;
3249
3250   LOG (GNUNET_ERROR_TYPE_DEBUG,
3251        "Going to send PUSH to peer %s.\n",
3252        GNUNET_i2s (peer_id));
3253
3254   ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PUSH);
3255   Peers_send_message (peer_id, ev, "PUSH");
3256 }
3257
3258
3259 static void
3260 do_round (void *cls);
3261
3262 static void
3263 do_mal_round (void *cls);
3264
3265 #ifdef ENABLE_MALICIOUS
3266
3267
3268 /**
3269  * @brief This function is called, when the client tells us to act malicious.
3270  * It verifies that @a msg is well-formed.
3271  *
3272  * @param cls the closure (#ClientContext)
3273  * @param msg the message
3274  * @return #GNUNET_OK if @a msg is well-formed
3275  */
3276 static int
3277 check_client_act_malicious (void *cls,
3278                             const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
3279 {
3280   struct ClientContext *cli_ctx = cls;
3281   uint16_t msize = ntohs (msg->header.size);
3282   uint32_t num_peers = ntohl (msg->num_peers);
3283
3284   msize -= sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage);
3285   if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
3286        (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
3287   {
3288     LOG (GNUNET_ERROR_TYPE_ERROR,
3289         "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3290         ntohl (msg->num_peers),
3291         (msize / sizeof (struct GNUNET_PeerIdentity)));
3292     GNUNET_break (0);
3293     GNUNET_SERVICE_client_drop (cli_ctx->client);
3294     return GNUNET_SYSERR;
3295   }
3296   return GNUNET_OK;
3297 }
3298
3299 /**
3300  * Turn RPS service to act malicious.
3301  *
3302  * @param cls Closure
3303  * @param client The client that sent the message
3304  * @param msg The message header
3305  */
3306 static void
3307 handle_client_act_malicious (void *cls,
3308                              const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
3309 {
3310   struct ClientContext *cli_ctx = cls;
3311   struct GNUNET_PeerIdentity *peers;
3312   uint32_t num_mal_peers_sent;
3313   uint32_t num_mal_peers_old;
3314
3315   /* Do actual logic */
3316   peers = (struct GNUNET_PeerIdentity *) &msg[1];
3317   mal_type = ntohl (msg->type);
3318   if (NULL == mal_peer_set)
3319     mal_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
3320
3321   LOG (GNUNET_ERROR_TYPE_DEBUG,
3322        "Now acting malicious type %" PRIu32 ", got %" PRIu32 " peers.\n",
3323        mal_type,
3324        ntohl (msg->num_peers));
3325
3326   if (1 == mal_type)
3327   { /* Try to maximise representation */
3328     /* Add other malicious peers to those we already know */
3329
3330     num_mal_peers_sent = ntohl (msg->num_peers);
3331     num_mal_peers_old = num_mal_peers;
3332     GNUNET_array_grow (mal_peers,
3333                        num_mal_peers,
3334                        num_mal_peers + num_mal_peers_sent);
3335     GNUNET_memcpy (&mal_peers[num_mal_peers_old],
3336             peers,
3337             num_mal_peers_sent * sizeof (struct GNUNET_PeerIdentity));
3338
3339     /* Add all mal peers to mal_peer_set */
3340     add_peer_array_to_set (&mal_peers[num_mal_peers_old],
3341                            num_mal_peers_sent,
3342                            mal_peer_set);
3343
3344     /* Substitute do_round () with do_mal_round () */
3345     GNUNET_SCHEDULER_cancel (do_round_task);
3346     do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, NULL);
3347   }
3348
3349   else if ( (2 == mal_type) ||
3350             (3 == mal_type) )
3351   { /* Try to partition the network */
3352     /* Add other malicious peers to those we already know */
3353
3354     num_mal_peers_sent = ntohl (msg->num_peers) - 1;
3355     num_mal_peers_old = num_mal_peers;
3356     GNUNET_array_grow (mal_peers,
3357                        num_mal_peers,
3358                        num_mal_peers + num_mal_peers_sent);
3359     if (NULL != mal_peers &&
3360         0 != num_mal_peers)
3361     {
3362       GNUNET_memcpy (&mal_peers[num_mal_peers_old],
3363               peers,
3364               num_mal_peers_sent * sizeof (struct GNUNET_PeerIdentity));
3365
3366       /* Add all mal peers to mal_peer_set */
3367       add_peer_array_to_set (&mal_peers[num_mal_peers_old],
3368                              num_mal_peers_sent,
3369                              mal_peer_set);
3370     }
3371
3372     /* Store the one attacked peer */
3373     GNUNET_memcpy (&attacked_peer,
3374             &msg->attacked_peer,
3375             sizeof (struct GNUNET_PeerIdentity));
3376     /* Set the flag of the attacked peer to valid to avoid problems */
3377     if (GNUNET_NO == Peers_check_peer_known (&attacked_peer))
3378     {
3379       (void) Peers_issue_peer_liveliness_check (&attacked_peer);
3380     }
3381
3382     LOG (GNUNET_ERROR_TYPE_DEBUG,
3383          "Attacked peer is %s\n",
3384          GNUNET_i2s (&attacked_peer));
3385
3386     /* Substitute do_round () with do_mal_round () */
3387     GNUNET_SCHEDULER_cancel (do_round_task);
3388     do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, NULL);
3389   }
3390   else if (0 == mal_type)
3391   { /* Stop acting malicious */
3392     GNUNET_array_grow (mal_peers, num_mal_peers, 0);
3393
3394     /* Substitute do_mal_round () with do_round () */
3395     GNUNET_SCHEDULER_cancel (do_round_task);
3396     do_round_task = GNUNET_SCHEDULER_add_now (&do_round, NULL);
3397   }
3398   else
3399   {
3400     GNUNET_break (0);
3401     GNUNET_SERVICE_client_continue (cli_ctx->client);
3402   }
3403   GNUNET_SERVICE_client_continue (cli_ctx->client);
3404 }
3405
3406
3407 /**
3408  * Send out PUSHes and PULLs maliciously.
3409  *
3410  * This is executed regylary.
3411  */
3412 static void
3413 do_mal_round (void *cls)
3414 {
3415   uint32_t num_pushes;
3416   uint32_t i;
3417   struct GNUNET_TIME_Relative time_next_round;
3418   struct AttackedPeer *tmp_att_peer;
3419
3420   LOG (GNUNET_ERROR_TYPE_DEBUG,
3421        "Going to execute next round maliciously type %" PRIu32 ".\n",
3422       mal_type);
3423   do_round_task = NULL;
3424   GNUNET_assert (mal_type <= 3);
3425   /* Do malicious actions */
3426   if (1 == mal_type)
3427   { /* Try to maximise representation */
3428
3429     /* The maximum of pushes we're going to send this round */
3430     num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit,
3431                                          num_attacked_peers),
3432                              GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE);
3433
3434     LOG (GNUNET_ERROR_TYPE_DEBUG,
3435          "Going to send %" PRIu32 " pushes\n",
3436          num_pushes);
3437
3438     /* Send PUSHes to attacked peers */
3439     for (i = 0 ; i < num_pushes ; i++)
3440     {
3441       if (att_peers_tail == att_peer_index)
3442         att_peer_index = att_peers_head;
3443       else
3444         att_peer_index = att_peer_index->next;
3445
3446       send_push (&att_peer_index->peer_id);
3447     }
3448
3449     /* Send PULLs to some peers to learn about additional peers to attack */
3450     tmp_att_peer = att_peer_index;
3451     for (i = 0 ; i < num_pushes * alpha ; i++)
3452     {
3453       if (att_peers_tail == tmp_att_peer)
3454         tmp_att_peer = att_peers_head;
3455       else
3456         att_peer_index = tmp_att_peer->next;
3457
3458       send_pull_request (&tmp_att_peer->peer_id);
3459     }
3460   }
3461
3462
3463   else if (2 == mal_type)
3464   { /**
3465      * Try to partition the network
3466      * Send as many pushes to the attacked peer as possible
3467      * That is one push per round as it will ignore more.
3468      */
3469     (void) Peers_issue_peer_liveliness_check (&attacked_peer);
3470     if (GNUNET_YES == Peers_check_peer_flag (&attacked_peer, Peers_ONLINE))
3471       send_push (&attacked_peer);
3472   }
3473
3474
3475   if (3 == mal_type)
3476   { /* Combined attack */
3477
3478     /* Send PUSH to attacked peers */
3479     if (GNUNET_YES == Peers_check_peer_known (&attacked_peer))
3480     {
3481       (void) Peers_issue_peer_liveliness_check (&attacked_peer);
3482       if (GNUNET_YES == Peers_check_peer_flag (&attacked_peer, Peers_ONLINE))
3483       {
3484         LOG (GNUNET_ERROR_TYPE_DEBUG,
3485             "Goding to send push to attacked peer (%s)\n",
3486             GNUNET_i2s (&attacked_peer));
3487         send_push (&attacked_peer);
3488       }
3489     }
3490     (void) Peers_issue_peer_liveliness_check (&attacked_peer);
3491
3492     /* The maximum of pushes we're going to send this round */
3493     num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1,
3494                                          num_attacked_peers),
3495                              GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE);
3496
3497     LOG (GNUNET_ERROR_TYPE_DEBUG,
3498          "Going to send %" PRIu32 " pushes\n",
3499          num_pushes);
3500
3501     for (i = 0; i < num_pushes; i++)
3502     {
3503       if (att_peers_tail == att_peer_index)
3504         att_peer_index = att_peers_head;
3505       else
3506         att_peer_index = att_peer_index->next;
3507
3508       send_push (&att_peer_index->peer_id);
3509     }
3510
3511     /* Send PULLs to some peers to learn about additional peers to attack */
3512     tmp_att_peer = att_peer_index;
3513     for (i = 0; i < num_pushes * alpha; i++)
3514     {
3515       if (att_peers_tail == tmp_att_peer)
3516         tmp_att_peer = att_peers_head;
3517       else
3518         att_peer_index = tmp_att_peer->next;
3519
3520       send_pull_request (&tmp_att_peer->peer_id);
3521     }
3522   }
3523
3524   /* Schedule next round */
3525   time_next_round = compute_rand_delay (round_interval, 2);
3526
3527   //do_round_task = GNUNET_SCHEDULER_add_delayed (round_interval, &do_mal_round,
3528   //NULL);
3529   GNUNET_assert (NULL == do_round_task);
3530   do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
3531                                                 &do_mal_round, NULL);
3532   LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
3533 }
3534 #endif /* ENABLE_MALICIOUS */
3535
3536
3537 /**
3538  * Send out PUSHes and PULLs, possibly update #view, samplers.
3539  *
3540  * This is executed regylary.
3541  */
3542 static void
3543 do_round (void *cls)
3544 {
3545   uint32_t i;
3546   const struct GNUNET_PeerIdentity *view_array;
3547   unsigned int *permut;
3548   unsigned int a_peers; /* Number of peers we send pushes to */
3549   unsigned int b_peers; /* Number of peers we send pull requests to */
3550   uint32_t first_border;
3551   uint32_t second_border;
3552   struct GNUNET_PeerIdentity peer;
3553   struct GNUNET_PeerIdentity *update_peer;
3554
3555   LOG (GNUNET_ERROR_TYPE_DEBUG,
3556        "Going to execute next round.\n");
3557   do_round_task = NULL;
3558   LOG (GNUNET_ERROR_TYPE_DEBUG,
3559        "Printing view:\n");
3560   to_file (file_name_view_log,
3561            "___ new round ___");
3562   view_array = View_get_as_array ();
3563   for (i = 0; i < View_size (); i++)
3564   {
3565     LOG (GNUNET_ERROR_TYPE_DEBUG,
3566          "\t%s\n", GNUNET_i2s (&view_array[i]));
3567     to_file (file_name_view_log,
3568              "=%s\t(do round)",
3569              GNUNET_i2s_full (&view_array[i]));
3570   }
3571
3572
3573   /* Send pushes and pull requests */
3574   if (0 < View_size ())
3575   {
3576     permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_STRONG,
3577                                            View_size ());
3578
3579     /* Send PUSHes */
3580     a_peers = ceil (alpha * View_size ());
3581
3582     LOG (GNUNET_ERROR_TYPE_DEBUG,
3583          "Going to send pushes to %u (ceil (%f * %u)) peers.\n",
3584          a_peers, alpha, View_size ());
3585     for (i = 0; i < a_peers; i++)
3586     {
3587       peer = view_array[permut[i]];
3588       if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer)) // TODO
3589       { // FIXME if this fails schedule/loop this for later
3590         send_push (&peer);
3591       }
3592     }
3593
3594     /* Send PULL requests */
3595     b_peers = ceil (beta * View_size ());
3596     first_border = a_peers;
3597     second_border = a_peers + b_peers;
3598     if (second_border > View_size ())
3599     {
3600       first_border = View_size () - b_peers;
3601       second_border = View_size ();
3602     }
3603     LOG (GNUNET_ERROR_TYPE_DEBUG,
3604         "Going to send pulls to %u (ceil (%f * %u)) peers.\n",
3605         b_peers, beta, View_size ());
3606     for (i = first_border; i < second_border; i++)
3607     {
3608       peer = view_array[permut[i]];
3609       if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer) &&
3610           GNUNET_NO == Peers_check_peer_flag (&peer, Peers_PULL_REPLY_PENDING)) // TODO
3611       { // FIXME if this fails schedule/loop this for later
3612         send_pull_request (&peer);
3613       }
3614     }
3615
3616     GNUNET_free (permut);
3617     permut = NULL;
3618   }
3619
3620
3621   /* Update view */
3622   /* TODO see how many peers are in push-/pull- list! */
3623
3624   if ((CustomPeerMap_size (push_map) <= alpha * View_size ()) &&
3625       (0 < CustomPeerMap_size (push_map)) &&
3626       (0 < CustomPeerMap_size (pull_map)))
3627   { /* If conditions for update are fulfilled, update */
3628     LOG (GNUNET_ERROR_TYPE_DEBUG, "Update of the view.\n");
3629
3630     uint32_t final_size;
3631     uint32_t peers_to_clean_size;
3632     struct GNUNET_PeerIdentity *peers_to_clean;
3633
3634     peers_to_clean = NULL;
3635     peers_to_clean_size = 0;
3636     GNUNET_array_grow (peers_to_clean, peers_to_clean_size, View_size ());
3637     GNUNET_memcpy (peers_to_clean,
3638             view_array,
3639             View_size () * sizeof (struct GNUNET_PeerIdentity));
3640
3641     /* Seems like recreating is the easiest way of emptying the peermap */
3642     View_clear ();
3643     to_file (file_name_view_log,
3644              "--- emptied ---");
3645
3646     first_border  = GNUNET_MIN (ceil (alpha * sampler_size_est_need),
3647                                 CustomPeerMap_size (push_map));
3648     second_border = first_border +
3649                     GNUNET_MIN (floor (beta  * sampler_size_est_need),
3650                                 CustomPeerMap_size (pull_map));
3651     final_size    = second_border +
3652       ceil ((1 - (alpha + beta)) * sampler_size_est_need);
3653
3654     /* Update view with peers received through PUSHes */
3655     permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_STRONG,
3656                                            CustomPeerMap_size (push_map));
3657     for (i = 0; i < first_border; i++)
3658     {
3659       (void) insert_in_view (CustomPeerMap_get_peer_by_index (push_map,
3660                                                               permut[i]));
3661       to_file (file_name_view_log,
3662                "+%s\t(push list)",
3663                GNUNET_i2s_full (&view_array[i]));
3664       // TODO change the peer_flags accordingly
3665     }
3666     GNUNET_free (permut);
3667     permut = NULL;
3668
3669     /* Update view with peers received through PULLs */
3670     permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_STRONG,
3671                                            CustomPeerMap_size (pull_map));
3672     for (i = first_border; i < second_border; i++)
3673     {
3674       (void) insert_in_view (CustomPeerMap_get_peer_by_index (pull_map,
3675             permut[i - first_border]));
3676       to_file (file_name_view_log,
3677                "+%s\t(pull list)",
3678                GNUNET_i2s_full (&view_array[i]));
3679       // TODO change the peer_flags accordingly
3680     }
3681     GNUNET_free (permut);
3682     permut = NULL;
3683
3684     /* Update view with peers from history */
3685     RPS_sampler_get_n_rand_peers (prot_sampler,
3686                                   hist_update,
3687                                   NULL,
3688                                   final_size - second_border);
3689     // TODO change the peer_flags accordingly
3690
3691     for (i = 0; i < View_size (); i++)
3692       rem_from_list (&peers_to_clean, &peers_to_clean_size, &view_array[i]);
3693
3694     /* Clean peers that were removed from the view */
3695     for (i = 0; i < peers_to_clean_size; i++)
3696     {
3697       to_file (file_name_view_log,
3698                "-%s",
3699                GNUNET_i2s_full (&peers_to_clean[i]));
3700       clean_peer (&peers_to_clean[i]);
3701       //peer_destroy_channel_send (sender);
3702     }
3703
3704     GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
3705   }
3706   else
3707   {
3708     LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
3709   }
3710   // TODO independent of that also get some peers from CADET_get_peers()?
3711
3712   LOG (GNUNET_ERROR_TYPE_DEBUG,
3713        "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (%u) = %.2f)\n",
3714        CustomPeerMap_size (push_map),
3715        CustomPeerMap_size (pull_map),
3716        alpha,
3717        View_size (),
3718        alpha * View_size ());
3719
3720   /* Update samplers */
3721   for (i = 0; i < CustomPeerMap_size (push_map); i++)
3722   {
3723     update_peer = CustomPeerMap_get_peer_by_index (push_map, i);
3724     LOG (GNUNET_ERROR_TYPE_DEBUG,
3725          "Updating with peer %s from push list\n",
3726          GNUNET_i2s (update_peer));
3727     insert_in_sampler (NULL, update_peer);
3728     clean_peer (update_peer); /* This cleans only if it is not in the view */
3729     //peer_destroy_channel_send (sender);
3730   }
3731
3732   for (i = 0; i < CustomPeerMap_size (pull_map); i++)
3733   {
3734     LOG (GNUNET_ERROR_TYPE_DEBUG,
3735          "Updating with peer %s from pull list\n",
3736          GNUNET_i2s (CustomPeerMap_get_peer_by_index (pull_map, i)));
3737     insert_in_sampler (NULL, CustomPeerMap_get_peer_by_index (pull_map, i));
3738     /* This cleans only if it is not in the view */
3739     clean_peer (CustomPeerMap_get_peer_by_index (pull_map, i));
3740     //peer_destroy_channel_send (sender);
3741   }
3742
3743
3744   /* Empty push/pull lists */
3745   CustomPeerMap_clear (push_map);
3746   CustomPeerMap_clear (pull_map);
3747
3748   struct GNUNET_TIME_Relative time_next_round;
3749
3750   time_next_round = compute_rand_delay (round_interval, 2);
3751
3752   /* Schedule next round */
3753   do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
3754                                                 &do_round, NULL);
3755   LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
3756 }
3757
3758
3759 /**
3760  * This is called from GNUNET_CADET_get_peers().
3761  *
3762  * It is called on every peer(ID) that cadet somehow has contact with.
3763  * We use those to initialise the sampler.
3764  */
3765 void
3766 init_peer_cb (void *cls,
3767               const struct GNUNET_PeerIdentity *peer,
3768               int tunnel, // "Do we have a tunnel towards this peer?"
3769               unsigned int n_paths, // "Number of known paths towards this peer"
3770               unsigned int best_path) // "How long is the best path?
3771                                       // (0 = unknown, 1 = ourselves, 2 = neighbor)"
3772 {
3773   if (NULL != peer)
3774   {
3775     LOG (GNUNET_ERROR_TYPE_DEBUG,
3776          "Got peer_id %s from cadet\n",
3777          GNUNET_i2s (peer));
3778     got_peer (peer);
3779   }
3780 }
3781
3782 /**
3783  * @brief Iterator function over stored, valid peers.
3784  *
3785  * We initialise the sampler with those.
3786  *
3787  * @param cls the closure
3788  * @param peer the peer id
3789  * @return #GNUNET_YES if we should continue to
3790  *         iterate,
3791  *         #GNUNET_NO if not.
3792  */
3793 static int
3794 valid_peers_iterator (void *cls,
3795                       const struct GNUNET_PeerIdentity *peer)
3796 {
3797   if (NULL != peer)
3798   {
3799     LOG (GNUNET_ERROR_TYPE_DEBUG,
3800          "Got stored, valid peer %s\n",
3801          GNUNET_i2s (peer));
3802     got_peer (peer);
3803   }
3804   return GNUNET_YES;
3805 }
3806
3807
3808 /**
3809  * Iterator over peers from peerinfo.
3810  *
3811  * @param cls closure
3812  * @param peer id of the peer, NULL for last call
3813  * @param hello hello message for the peer (can be NULL)
3814  * @param error message
3815  */
3816 void
3817 process_peerinfo_peers (void *cls,
3818                         const struct GNUNET_PeerIdentity *peer,
3819                         const struct GNUNET_HELLO_Message *hello,
3820                         const char *err_msg)
3821 {
3822   if (NULL != peer)
3823   {
3824     LOG (GNUNET_ERROR_TYPE_DEBUG,
3825          "Got peer_id %s from peerinfo\n",
3826          GNUNET_i2s (peer));
3827     got_peer (peer);
3828   }
3829 }
3830
3831
3832 /**
3833  * Task run during shutdown.
3834  *
3835  * @param cls unused
3836  */
3837 static void
3838 shutdown_task (void *cls)
3839 {
3840   struct ClientContext *client_ctx;
3841   struct ReplyCls *reply_cls;
3842
3843   LOG (GNUNET_ERROR_TYPE_DEBUG,
3844        "RPS is going down\n");
3845
3846   /* Clean all clients */
3847   for (client_ctx = cli_ctx_head;
3848        NULL != cli_ctx_head;
3849        client_ctx = cli_ctx_head)
3850   {
3851     /* Clean pending requests to the sampler */
3852     for (reply_cls = client_ctx->rep_cls_head;
3853          NULL != client_ctx->rep_cls_head;
3854          reply_cls = client_ctx->rep_cls_head)
3855     {
3856       RPS_sampler_request_cancel (reply_cls->req_handle);
3857       GNUNET_CONTAINER_DLL_remove (client_ctx->rep_cls_head,
3858                                    client_ctx->rep_cls_tail,
3859                                    reply_cls);
3860       GNUNET_free (reply_cls);
3861     }
3862     GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx);
3863     GNUNET_free (client_ctx);
3864   }
3865   GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle);
3866   GNUNET_PEERINFO_disconnect (peerinfo_handle);
3867
3868   if (NULL != do_round_task)
3869   {
3870     GNUNET_SCHEDULER_cancel (do_round_task);
3871     do_round_task = NULL;
3872   }
3873
3874   Peers_terminate ();
3875
3876   GNUNET_NSE_disconnect (nse);
3877   RPS_sampler_destroy (prot_sampler);
3878   RPS_sampler_destroy (client_sampler);
3879   GNUNET_CADET_close_port (cadet_port);
3880   GNUNET_CADET_disconnect (cadet_handle);
3881   View_destroy ();
3882   CustomPeerMap_destroy (push_map);
3883   CustomPeerMap_destroy (pull_map);
3884   #ifdef ENABLE_MALICIOUS
3885   struct AttackedPeer *tmp_att_peer;
3886   GNUNET_free (file_name_view_log);
3887   GNUNET_array_grow (mal_peers, num_mal_peers, 0);
3888   if (NULL != mal_peer_set)
3889     GNUNET_CONTAINER_multipeermap_destroy (mal_peer_set);
3890   if (NULL != att_peer_set)
3891     GNUNET_CONTAINER_multipeermap_destroy (att_peer_set);
3892   while (NULL != att_peers_head)
3893   {
3894     tmp_att_peer = att_peers_head;
3895     GNUNET_CONTAINER_DLL_remove (att_peers_head, att_peers_tail, tmp_att_peer);
3896   }
3897   #endif /* ENABLE_MALICIOUS */
3898 }
3899
3900
3901 /**
3902  * Handle client connecting to the service.
3903  *
3904  * @param cls NULL
3905  * @param client the new client
3906  * @param mq the message queue of @a client
3907  * @return @a client
3908  */
3909 static void *
3910 client_connect_cb (void *cls,
3911                    struct GNUNET_SERVICE_Client *client,
3912                    struct GNUNET_MQ_Handle *mq)
3913 {
3914   struct ClientContext *cli_ctx;
3915
3916   LOG (GNUNET_ERROR_TYPE_DEBUG,
3917        "Client connected\n");
3918   if (NULL == client)
3919     return client; /* Server was destroyed before a client connected. Shutting down */
3920   cli_ctx = GNUNET_new (struct ClientContext);
3921   cli_ctx->mq = GNUNET_SERVICE_client_get_mq (client);
3922   cli_ctx->client = client;
3923   GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
3924                                cli_ctx_tail,
3925                                cli_ctx);
3926   return cli_ctx;
3927 }
3928
3929 /**
3930  * Callback called when a client disconnected from the service
3931  *
3932  * @param cls closure for the service
3933  * @param c the client that disconnected
3934  * @param internal_cls should be equal to @a c
3935  */
3936 static void
3937 client_disconnect_cb (void *cls,
3938                       struct GNUNET_SERVICE_Client *client,
3939                       void *internal_cls)
3940 {
3941   struct ClientContext *cli_ctx = internal_cls;
3942
3943   GNUNET_assert (client == cli_ctx->client);
3944   if (NULL == client)
3945   {/* shutdown task - destroy all clients */
3946     while (NULL != cli_ctx_head)
3947       destroy_cli_ctx (cli_ctx_head);
3948   }
3949   else
3950   { /* destroy this client */
3951     LOG (GNUNET_ERROR_TYPE_DEBUG,
3952         "Client disconnected. Destroy its context.\n");
3953     destroy_cli_ctx (cli_ctx);
3954   }
3955 }
3956
3957
3958 /**
3959  * Handle random peer sampling clients.
3960  *
3961  * @param cls closure
3962  * @param c configuration to use
3963  * @param service the initialized service
3964  */
3965 static void
3966 run (void *cls,
3967      const struct GNUNET_CONFIGURATION_Handle *c,
3968      struct GNUNET_SERVICE_Handle *service)
3969 {
3970   int size;
3971   int out_size;
3972   char* fn_valid_peers;
3973   struct GNUNET_HashCode port;
3974
3975   GNUNET_log_setup ("rps", GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_DEBUG), NULL);
3976   cfg = c;
3977
3978
3979   /* Get own ID */
3980   GNUNET_CRYPTO_get_peer_identity (cfg, &own_identity); // TODO check return value
3981   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3982               "STARTING SERVICE (rps) for peer [%s]\n",
3983               GNUNET_i2s (&own_identity));
3984   #ifdef ENABLE_MALICIOUS
3985   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3986               "Malicious execution compiled in.\n");
3987   #endif /* ENABLE_MALICIOUS */
3988
3989
3990
3991   /* Get time interval from the configuration */
3992   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "RPS",
3993                                                         "ROUNDINTERVAL",
3994                                                         &round_interval))
3995   {
3996     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3997                                "RPS", "ROUNDINTERVAL");
3998     GNUNET_SCHEDULER_shutdown ();
3999     return;
4000   }
4001
4002   /* Get initial size of sampler/view from the configuration */
4003   if (GNUNET_OK !=
4004       GNUNET_CONFIGURATION_get_value_number (cfg, "RPS", "INITSIZE",
4005         (long long unsigned int *) &sampler_size_est_need))
4006   {
4007     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
4008                                "RPS", "INITSIZE");
4009     GNUNET_SCHEDULER_shutdown ();
4010     return;
4011   }
4012   LOG (GNUNET_ERROR_TYPE_DEBUG, "INITSIZE is %u\n", sampler_size_est_need);
4013
4014   if (GNUNET_OK !=
4015       GNUNET_CONFIGURATION_get_value_filename (cfg,
4016                                                "rps",
4017                                                "FILENAME_VALID_PEERS",
4018                                                &fn_valid_peers))
4019   {
4020     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
4021                                "rps", "FILENAME_VALID_PEERS");
4022   }
4023
4024
4025   View_create (4);
4026
4027   /* file_name_view_log */
4028   if (GNUNET_OK != GNUNET_DISK_directory_create ("/tmp/rps/"))
4029   {
4030     LOG (GNUNET_ERROR_TYPE_WARNING,
4031          "Failed to create directory /tmp/rps/\n");
4032   }
4033
4034   size = (14 + strlen (GNUNET_i2s_full (&own_identity)) + 1) * sizeof (char);
4035   file_name_view_log = GNUNET_malloc (size);
4036   out_size = GNUNET_snprintf (file_name_view_log,
4037                               size,
4038                               "/tmp/rps/view-%s",
4039                               GNUNET_i2s_full (&own_identity));
4040   if (size < out_size ||
4041       0 > out_size)
4042   {
4043     LOG (GNUNET_ERROR_TYPE_WARNING,
4044          "Failed to write string to buffer (size: %i, out_size: %i)\n",
4045          size,
4046          out_size);
4047   }
4048
4049
4050   /* connect to NSE */
4051   nse = GNUNET_NSE_connect (cfg, nse_callback, NULL);
4052
4053
4054   alpha = 0.45;
4055   beta  = 0.45;
4056
4057
4058   /* Initialise cadet */
4059   /* There exists a copy-paste-clone in get_channel() */
4060   struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
4061     GNUNET_MQ_hd_fixed_size (peer_check,
4062                              GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
4063                              struct GNUNET_MessageHeader,
4064                              NULL),
4065     GNUNET_MQ_hd_fixed_size (peer_push,
4066                              GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
4067                              struct GNUNET_MessageHeader,
4068                              NULL),
4069     GNUNET_MQ_hd_fixed_size (peer_pull_request,
4070                              GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
4071                              struct GNUNET_MessageHeader,
4072                              NULL),
4073     GNUNET_MQ_hd_var_size (peer_pull_reply,
4074                            GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
4075                            struct GNUNET_RPS_P2P_PullReplyMessage,
4076                            NULL),
4077     GNUNET_MQ_handler_end ()
4078   };
4079
4080   cadet_handle = GNUNET_CADET_connect (cfg);
4081   GNUNET_assert (NULL != cadet_handle);
4082   GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
4083                       strlen (GNUNET_APPLICATION_PORT_RPS),
4084                       &port);
4085   cadet_port = GNUNET_CADET_open_port (cadet_handle,
4086                                        &port,
4087                                        &Peers_handle_inbound_channel, /* Connect handler */
4088                                        NULL, /* cls */
4089                                        NULL, /* WindowSize handler */
4090                                        cleanup_destroyed_channel, /* Disconnect handler */
4091                                        cadet_handlers);
4092
4093
4094   peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
4095   Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel,
4096                     &own_identity);
4097   GNUNET_free (fn_valid_peers);
4098
4099   /* Initialise sampler */
4100   struct GNUNET_TIME_Relative half_round_interval;
4101   struct GNUNET_TIME_Relative  max_round_interval;
4102
4103   half_round_interval = GNUNET_TIME_relative_divide (round_interval, 2);
4104   max_round_interval = GNUNET_TIME_relative_add (round_interval, half_round_interval);
4105
4106   prot_sampler =   RPS_sampler_init     (sampler_size_est_need, max_round_interval);
4107   client_sampler = RPS_sampler_mod_init (sampler_size_est_need, max_round_interval);
4108
4109   /* Initialise push and pull maps */
4110   push_map = CustomPeerMap_create (4);
4111   pull_map = CustomPeerMap_create (4);
4112
4113
4114   //LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
4115   //GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, NULL);
4116   // TODO send push/pull to each of those peers?
4117   // TODO read stored valid peers from last run
4118   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting stored valid peers\n");
4119   Peers_get_valid_peers (valid_peers_iterator, NULL);
4120
4121   peerinfo_notify_handle = GNUNET_PEERINFO_notify (cfg,
4122                                                    GNUNET_NO,
4123                                                    process_peerinfo_peers,
4124                                                    NULL);
4125
4126   LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
4127
4128   do_round_task = GNUNET_SCHEDULER_add_now (&do_round, NULL);
4129   LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled first round\n");
4130
4131   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
4132 }
4133
4134
4135 /**
4136  * Define "main" method using service macro.
4137  */
4138 GNUNET_SERVICE_MAIN
4139 ("rps",
4140  GNUNET_SERVICE_OPTION_NONE,
4141  &run,
4142  &client_connect_cb,
4143  &client_disconnect_cb,
4144  NULL,
4145  GNUNET_MQ_hd_fixed_size (client_request,
4146    GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST,
4147    struct GNUNET_RPS_CS_RequestMessage,
4148    NULL),
4149  GNUNET_MQ_hd_fixed_size (client_request_cancel,
4150    GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST_CANCEL,
4151    struct GNUNET_RPS_CS_RequestCancelMessage,
4152    NULL),
4153  GNUNET_MQ_hd_var_size (client_seed,
4154    GNUNET_MESSAGE_TYPE_RPS_CS_SEED,
4155    struct GNUNET_RPS_CS_SeedMessage,
4156    NULL),
4157 #ifdef ENABLE_MALICIOUS
4158  GNUNET_MQ_hd_var_size (client_act_malicious,
4159    GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS,
4160    struct GNUNET_RPS_CS_ActMaliciousMessage,
4161    NULL),
4162 #endif /* ENABLE_MALICIOUS */
4163  GNUNET_MQ_handler_end());
4164
4165 /* end of gnunet-service-rps.c */