aboutsummaryrefslogtreecommitdiff
path: root/src/rps/gnunet-service-rps.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rps/gnunet-service-rps.c')
-rw-r--r--src/rps/gnunet-service-rps.c1798
1 files changed, 1763 insertions, 35 deletions
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index 0a4543b30..ec70075cf 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -33,7 +33,6 @@
33#include "rps-test_util.h" 33#include "rps-test_util.h"
34#include "gnunet-service-rps_sampler.h" 34#include "gnunet-service-rps_sampler.h"
35#include "gnunet-service-rps_custommap.h" 35#include "gnunet-service-rps_custommap.h"
36#include "gnunet-service-rps_peers.h"
37#include "gnunet-service-rps_view.h" 36#include "gnunet-service-rps_view.h"
38 37
39#include <math.h> 38#include <math.h>
@@ -66,6 +65,1728 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
66static struct GNUNET_PeerIdentity own_identity; 65static struct GNUNET_PeerIdentity own_identity;
67 66
68 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 */
113struct 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 */
132struct 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 */
164struct 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 */
244struct 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 */
260static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
261
262/**
263 * @brief Maximum number of valid peers to keep.
264 * TODO read from config
265 */
266static uint32_t num_valid_peers_max = UINT32_MAX;
267
268/**
269 * @brief Filename of the file that stores the valid peers persistently.
270 */
271static char *filename_valid_peers;
272
273/**
274 * Set of all peers to keep track of them.
275 */
276static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
277
278/**
279 * Cadet handle.
280 */
281static 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 */
292static struct PeerContext *
293get_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
305int
306Peers_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 */
315static struct PeerContext *
316create_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 */
341static struct PeerContext *
342create_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
351void
352Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
353
354void
355Peers_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 */
367int
368Peers_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 */
395struct 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 */
426static int
427get_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 */
449static const struct GNUNET_PeerIdentity *
450get_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 */
478static int
479add_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 */
505static void
506set_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
539static void
540cleanup_destroyed_channel (void *cls,
541 const struct GNUNET_CADET_Channel *channel);
542
543/* Declaration of handlers */
544static void
545handle_peer_check (void *cls,
546 const struct GNUNET_MessageHeader *msg);
547
548static void
549handle_peer_push (void *cls,
550 const struct GNUNET_MessageHeader *msg);
551
552static void
553handle_peer_pull_request (void *cls,
554 const struct GNUNET_MessageHeader *msg);
555
556static int
557check_peer_pull_reply (void *cls,
558 const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
559
560static void
561handle_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 */
573struct GNUNET_CADET_Channel *
574get_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 */
633static struct GNUNET_MQ_Handle *
634get_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 */
655static void
656mq_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 */
676static void
677check_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 */
706static struct PendingMessage *
707insert_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 */
732static void
733remove_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 */
763static int
764check_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
777int
778Peers_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 */
789static int
790peermap_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 */
806static void
807mq_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 */
832static int
833store_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 */
862static void
863store_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 */
923static const struct GNUNET_PeerIdentity *
924s2i_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 */
963static void
964restore_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 */
1033void
1034Peers_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 */
1051void
1052Peers_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 */
1079static int
1080valid_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 */
1099int
1100Peers_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 */
1129int
1130Peers_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
1141int
1142Peers_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 */
1154int
1155Peers_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 */
1187int
1188Peers_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
1207uint32_t *
1208Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1209 enum Peers_ChannelRole role);
1210
1211int
1212Peers_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 */
1221int
1222Peers_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 */
1297void
1298Peers_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 */
1313void
1314Peers_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 */
1333int
1334Peers_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 */
1353void
1354Peers_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 */
1366void
1367Peers_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 */
1382int
1383Peers_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 */
1396uint32_t *
1397Peers_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 */
1427int
1428Peers_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 */
1444int
1445Peers_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 */
1458void
1459Peers_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 */
1475int
1476Peers_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 */
1499void *
1500Peers_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 */
1535int
1536Peers_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 */
1565int
1566Peers_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 */
1603int
1604Peers_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 */
1631void
1632Peers_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 */
1709void
1710Peers_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 */
1739int
1740Peers_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 */
1776struct GNUNET_CADET_Channel *
1777Peers_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
69/*********************************************************************** 1790/***********************************************************************
70 * Housekeeping with clients 1791 * Housekeeping with clients
71***********************************************************************/ 1792***********************************************************************/
@@ -847,6 +2568,7 @@ cleanup_destroyed_channel (void *cls,
847{ 2568{
848 struct GNUNET_PeerIdentity *peer = cls; 2569 struct GNUNET_PeerIdentity *peer = cls;
849 uint32_t *channel_flag; 2570 uint32_t *channel_flag;
2571 struct PeerContext *peer_ctx;
850 2572
851 if (GNUNET_NO == Peers_check_peer_known (peer)) 2573 if (GNUNET_NO == Peers_check_peer_known (peer))
852 { /* We don't know a context to that peer */ 2574 { /* We don't know a context to that peer */
@@ -856,6 +2578,15 @@ cleanup_destroyed_channel (void *cls,
856 return; 2578 return;
857 } 2579 }
858 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
859 if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY)) 2590 if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY))
860 { /* We are in the middle of removing that peer from our knowledge. In this 2591 { /* We are in the middle of removing that peer from our knowledge. In this
861 case simply make sure that the channels are cleaned. */ 2592 case simply make sure that the channels are cleaned. */
@@ -1121,7 +2852,6 @@ handle_client_request_cancel (void *cls,
1121 (rep_cls->id != ntohl (msg->id)) ) 2852 (rep_cls->id != ntohl (msg->id)) )
1122 rep_cls = rep_cls->next; 2853 rep_cls = rep_cls->next;
1123 GNUNET_assert (rep_cls->id == ntohl (msg->id)); 2854 GNUNET_assert (rep_cls->id == ntohl (msg->id));
1124 RPS_sampler_request_cancel (rep_cls->req_handle);
1125 destroy_reply_cls (rep_cls); 2855 destroy_reply_cls (rep_cls);
1126 GNUNET_SERVICE_client_continue (cli_ctx->client); 2856 GNUNET_SERVICE_client_continue (cli_ctx->client);
1127} 2857}
@@ -1239,24 +2969,24 @@ handle_peer_push (void *cls,
1239 (3 == mal_type) ) 2969 (3 == mal_type) )
1240 { /* Try to maximise representation */ 2970 { /* Try to maximise representation */
1241 tmp_att_peer = GNUNET_new (struct AttackedPeer); 2971 tmp_att_peer = GNUNET_new (struct AttackedPeer);
1242 GNUNET_memcpy (&tmp_att_peer->peer_id, peer, sizeof (struct GNUNET_PeerIdentity)); 2972 tmp_att_peer->peer_id = *peer;
1243 if (NULL == att_peer_set) 2973 if (NULL == att_peer_set)
1244 att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO); 2974 att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
1245 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set, 2975 if (GNUNET_NO ==
1246 peer)) 2976 GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
2977 peer))
1247 { 2978 {
1248 GNUNET_CONTAINER_DLL_insert (att_peers_head, 2979 GNUNET_CONTAINER_DLL_insert (att_peers_head,
1249 att_peers_tail, 2980 att_peers_tail,
1250 tmp_att_peer); 2981 tmp_att_peer);
1251 add_peer_array_to_set (peer, 1, att_peer_set); 2982 add_peer_array_to_set (peer, 1, att_peer_set);
1252 } 2983 }
1253 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
1254 } 2984 }
1255 2985
1256 2986
1257 else if (2 == mal_type) 2987 else if (2 == mal_type)
1258 { /* We attack one single well-known peer - simply ignore */ 2988 {
1259 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); 2989 /* We attack one single well-known peer - simply ignore */
1260 } 2990 }
1261 #endif /* ENABLE_MALICIOUS */ 2991 #endif /* ENABLE_MALICIOUS */
1262 2992
@@ -1289,7 +3019,6 @@ handle_peer_pull_request (void *cls,
1289 || 3 == mal_type) 3019 || 3 == mal_type)
1290 { /* Try to maximise representation */ 3020 { /* Try to maximise representation */
1291 send_pull_reply (peer, mal_peers, num_mal_peers); 3021 send_pull_reply (peer, mal_peers, num_mal_peers);
1292 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
1293 } 3022 }
1294 3023
1295 else if (2 == mal_type) 3024 else if (2 == mal_type)
@@ -1298,7 +3027,6 @@ handle_peer_pull_request (void *cls,
1298 { 3027 {
1299 send_pull_reply (peer, mal_peers, num_mal_peers); 3028 send_pull_reply (peer, mal_peers, num_mal_peers);
1300 } 3029 }
1301 GNUNET_CADET_receive_done (Peers_get_recv_channel (peer));
1302 } 3030 }
1303 #endif /* ENABLE_MALICIOUS */ 3031 #endif /* ENABLE_MALICIOUS */
1304 3032
@@ -1360,7 +3088,7 @@ static void
1360handle_peer_pull_reply (void *cls, 3088handle_peer_pull_reply (void *cls,
1361 const struct GNUNET_RPS_P2P_PullReplyMessage *msg) 3089 const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
1362{ 3090{
1363 struct GNUNET_PeerIdentity *peers; 3091 const struct GNUNET_PeerIdentity *peers;
1364 struct GNUNET_PeerIdentity *sender = cls; 3092 struct GNUNET_PeerIdentity *sender = cls;
1365 uint32_t i; 3093 uint32_t i;
1366#ifdef ENABLE_MALICIOUS 3094#ifdef ENABLE_MALICIOUS
@@ -1373,12 +3101,11 @@ handle_peer_pull_reply (void *cls,
1373 // We shouldn't even receive pull replies as we're not sending 3101 // We shouldn't even receive pull replies as we're not sending
1374 if (2 == mal_type) 3102 if (2 == mal_type)
1375 { 3103 {
1376 GNUNET_CADET_receive_done (Peers_get_recv_channel (sender));
1377 } 3104 }
1378 #endif /* ENABLE_MALICIOUS */ 3105 #endif /* ENABLE_MALICIOUS */
1379 3106
1380 /* Do actual logic */ 3107 /* Do actual logic */
1381 peers = (struct GNUNET_PeerIdentity *) &msg[1]; 3108 peers = (const struct GNUNET_PeerIdentity *) &msg[1];
1382 3109
1383 LOG (GNUNET_ERROR_TYPE_DEBUG, 3110 LOG (GNUNET_ERROR_TYPE_DEBUG,
1384 "PULL REPLY received, got following %u peers:\n", 3111 "PULL REPLY received, got following %u peers:\n",
@@ -2132,7 +3859,6 @@ shutdown_task (void *cls)
2132 reply_cls); 3859 reply_cls);
2133 GNUNET_free (reply_cls); 3860 GNUNET_free (reply_cls);
2134 } 3861 }
2135 GNUNET_MQ_destroy (client_ctx->mq);
2136 GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx); 3862 GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx);
2137 GNUNET_free (client_ctx); 3863 GNUNET_free (client_ctx);
2138 } 3864 }
@@ -2150,6 +3876,7 @@ shutdown_task (void *cls)
2150 GNUNET_NSE_disconnect (nse); 3876 GNUNET_NSE_disconnect (nse);
2151 RPS_sampler_destroy (prot_sampler); 3877 RPS_sampler_destroy (prot_sampler);
2152 RPS_sampler_destroy (client_sampler); 3878 RPS_sampler_destroy (client_sampler);
3879 GNUNET_CADET_close_port (cadet_port);
2153 GNUNET_CADET_disconnect (cadet_handle); 3880 GNUNET_CADET_disconnect (cadet_handle);
2154 View_destroy (); 3881 View_destroy ();
2155 CustomPeerMap_destroy (push_map); 3882 CustomPeerMap_destroy (push_map);
@@ -2240,26 +3967,6 @@ run (void *cls,
2240 const struct GNUNET_CONFIGURATION_Handle *c, 3967 const struct GNUNET_CONFIGURATION_Handle *c,
2241 struct GNUNET_SERVICE_Handle *service) 3968 struct GNUNET_SERVICE_Handle *service)
2242{ 3969{
2243 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2244 GNUNET_MQ_hd_fixed_size (peer_check,
2245 GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
2246 struct GNUNET_MessageHeader,
2247 NULL),
2248 GNUNET_MQ_hd_fixed_size (peer_push,
2249 GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
2250 struct GNUNET_MessageHeader,
2251 NULL),
2252 GNUNET_MQ_hd_fixed_size (peer_pull_request,
2253 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
2254 struct GNUNET_MessageHeader,
2255 NULL),
2256 GNUNET_MQ_hd_var_size (peer_pull_reply,
2257 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
2258 struct GNUNET_RPS_P2P_PullReplyMessage,
2259 NULL),
2260 GNUNET_MQ_handler_end ()
2261 };
2262
2263 int size; 3970 int size;
2264 int out_size; 3971 int out_size;
2265 char* fn_valid_peers; 3972 char* fn_valid_peers;
@@ -2349,6 +4056,27 @@ run (void *cls,
2349 4056
2350 4057
2351 /* Initialise cadet */ 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
2352 cadet_handle = GNUNET_CADET_connect (cfg); 4080 cadet_handle = GNUNET_CADET_connect (cfg);
2353 GNUNET_assert (NULL != cadet_handle); 4081 GNUNET_assert (NULL != cadet_handle);
2354 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS, 4082 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
@@ -2365,7 +4093,7 @@ run (void *cls,
2365 4093
2366 peerinfo_handle = GNUNET_PEERINFO_connect (cfg); 4094 peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
2367 Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel, 4095 Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel,
2368 cadet_handlers, &own_identity); 4096 &own_identity);
2369 GNUNET_free (fn_valid_peers); 4097 GNUNET_free (fn_valid_peers);
2370 4098
2371 /* Initialise sampler */ 4099 /* Initialise sampler */