aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJulius Bünger <buenger@mytum.de>2016-01-21 16:38:41 +0000
committerJulius Bünger <buenger@mytum.de>2016-01-21 16:38:41 +0000
commit099bde38ac80ca84ac7c4a08cc5ac91ea7abab70 (patch)
tree1fbfa35040da9b68b2fc8bf97952cf3c5f1ca128 /src
parentf7d137478c27910c1f3d7bda32456d8a7b0c6af2 (diff)
downloadgnunet-099bde38ac80ca84ac7c4a08cc5ac91ea7abab70.tar.gz
gnunet-099bde38ac80ca84ac7c4a08cc5ac91ea7abab70.zip
rps: restructured service. moved peer-related code to gnunet-service-rps_peers
Signed-off-by: Julius Bünger <buenger@mytum.de>
Diffstat (limited to 'src')
-rw-r--r--src/rps/Makefile.am1
-rw-r--r--src/rps/gnunet-service-rps.c1164
-rw-r--r--src/rps/gnunet-service-rps_peers.c1158
-rw-r--r--src/rps/gnunet-service-rps_peers.h371
4 files changed, 1793 insertions, 901 deletions
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am
index 48d346aef..f08ded57a 100644
--- a/src/rps/Makefile.am
+++ b/src/rps/Makefile.am
@@ -49,6 +49,7 @@ endif
49gnunet_service_rps_SOURCES = \ 49gnunet_service_rps_SOURCES = \
50 gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \ 50 gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \
51 gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \ 51 gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \
52 gnunet-service-rps_peers.h gnunet-service-rps_peers.c \
52 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ 53 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \
53 gnunet-service-rps_view.h gnunet-service-rps_view.c \ 54 gnunet-service-rps_view.h gnunet-service-rps_view.c \
54 rps-test_util.h rps-test_util.c \ 55 rps-test_util.h rps-test_util.c \
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index fbf42a808..4d227c8d7 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -29,11 +29,11 @@
29#include "gnunet_peerinfo_service.h" 29#include "gnunet_peerinfo_service.h"
30#include "gnunet_nse_service.h" 30#include "gnunet_nse_service.h"
31#include "rps.h" 31#include "rps.h"
32#include "gnunet-service-rps_custommap.h"
33#include "gnunet-service-rps_view.h"
34#include "rps-test_util.h" 32#include "rps-test_util.h"
35
36#include "gnunet-service-rps_sampler.h" 33#include "gnunet-service-rps_sampler.h"
34#include "gnunet-service-rps_custommap.h"
35#include "gnunet-service-rps_peers.h"
36#include "gnunet-service-rps_view.h"
37 37
38#include <math.h> 38#include <math.h>
39#include <inttypes.h> 39#include <inttypes.h>
@@ -52,8 +52,6 @@
52 52
53// TODO blacklist? (-> mal peer detection on top of brahms) 53// TODO blacklist? (-> mal peer detection on top of brahms)
54 54
55// TODO API request_cancel
56
57// hist_size_init, hist_size_max 55// hist_size_init, hist_size_max
58 56
59/** 57/**
@@ -129,146 +127,6 @@ struct ClientContext
129struct ClientContext *cli_ctx_head; 127struct ClientContext *cli_ctx_head;
130struct ClientContext *cli_ctx_tail; 128struct ClientContext *cli_ctx_tail;
131 129
132/**
133 * Used to keep track in what lists single peerIDs are.
134 */
135enum PeerFlags
136{
137 /**
138 * If we are waiting for a reply from that peer (sent a pull request).
139 */
140 PULL_REPLY_PENDING = 0x01,
141
142 IN_OTHER_GOSSIP_LIST = 0x02, // unneeded?
143 IN_OWN_SAMPLER_LIST = 0x04, // unneeded?
144 IN_OWN_GOSSIP_LIST = 0x08, // unneeded?
145
146 /**
147 * We set this bit when we can be sure the other peer is/was live.
148 */
149 VALID = 0x10,
150
151 /**
152 * We set this bit when we are going to destroy the channel to this peer.
153 * When cleanup_channel is called, we know that we wanted to destroy it.
154 * Otherwise the channel to the other peer was destroyed.
155 */
156 TO_DESTROY = 0x20,
157};
158
159
160/**
161 * Functions of this type can be used to be stored at a peer for later execution.
162 */
163typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer);
164
165/**
166 * Outstanding operation on peer consisting of callback and closure
167 */
168struct PeerOutstandingOp
169{
170 /**
171 * Callback
172 */
173 PeerOp op;
174
175 /**
176 * Closure
177 */
178 void *op_cls;
179};
180
181
182/**
183 * List containing all messages that are yet to be send
184 */
185struct PendingMessage
186{
187 /**
188 * DLL next, prev
189 */
190 struct PendingMessage *next;
191 struct PendingMessage *prev;
192
193 /**
194 * The envelope to the corresponding message
195 */
196 struct GNUNET_MQ_Envelope *ev;
197
198 /**
199 * The corresponding context
200 */
201 struct PeerContext *peer_ctx;
202
203 /**
204 * The message type
205 */
206 const char *type;
207};
208
209
210/**
211 * Struct used to keep track of other peer's status
212 *
213 * This is stored in a multipeermap.
214 */
215struct PeerContext
216{
217 /**
218 * Message queue open to client
219 */
220 struct GNUNET_MQ_Handle *mq;
221
222 /**
223 * Channel open to client.
224 */
225 struct GNUNET_CADET_Channel *send_channel;
226
227 /**
228 * Channel open from client.
229 */
230 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
231
232 /**
233 * Array of outstanding operations on this peer.
234 */
235 struct PeerOutstandingOp *outstanding_ops;
236
237 /**
238 * Handle to the callback given to cadet_ntfy_tmt_rdy()
239 *
240 * To be canceled on shutdown.
241 */
242 struct GNUNET_CADET_TransmitHandle *transmit_handle;
243
244 /**
245 * Number of outstanding operations.
246 */
247 unsigned int num_outstanding_ops;
248
249 /**
250 * Identity of the peer
251 */
252 struct GNUNET_PeerIdentity peer_id;
253
254 /**
255 * Flags indicating status of peer
256 */
257 uint32_t peer_flags;
258
259 /**
260 * DLL with all messages that are yet to be sent
261 */
262 struct PendingMessage *pending_messages_head;
263 struct PendingMessage *pending_messages_tail;
264
265 /**
266 * This is pobably followed by 'statistical' data (when we first saw
267 * him, how did we get his ID, how many pushes (in a timeinterval),
268 * ...)
269 */
270};
271
272/*********************************************************************** 130/***********************************************************************
273 * /Housekeeping with peers 131 * /Housekeeping with peers
274***********************************************************************/ 132***********************************************************************/
@@ -291,11 +149,6 @@ static struct RPS_Sampler *prot_sampler;
291 */ 149 */
292static struct RPS_Sampler *client_sampler; 150static struct RPS_Sampler *client_sampler;
293 151
294/**
295 * Set of all peers to keep track of them.
296 */
297static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
298
299 152
300/** 153/**
301 * Name to log view to 154 * Name to log view to
@@ -516,27 +369,6 @@ static uint32_t push_limit = 10000;
516 * Util functions 369 * Util functions
517***********************************************************************/ 370***********************************************************************/
518 371
519/**
520 * Set a peer flag of given peer context.
521 */
522#define set_peer_flag(peer_ctx, mask) (peer_ctx->peer_flags |= mask)
523
524/**
525 * Get peer flag of given peer context.
526 */
527#define get_peer_flag(peer_ctx, mask) (peer_ctx->peer_flags & mask ? GNUNET_YES : GNUNET_NO)
528
529/**
530 * Unset flag of given peer context.
531 */
532#define unset_peer_flag(peer_ctx, mask) (peer_ctx->peer_flags &= (~mask))
533
534/**
535 * Clean the send channel of a peer
536 */
537void
538peer_clean (const struct GNUNET_PeerIdentity *peer);
539
540 372
541/** 373/**
542 * Print peerlist to log. 374 * Print peerlist to log.
@@ -595,201 +427,6 @@ rem_from_list (struct GNUNET_PeerIdentity **peer_list,
595 427
596 428
597/** 429/**
598 * Get the context of a peer. If not existing, create.
599 */
600 struct PeerContext *
601get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
602{
603 struct PeerContext *ctx;
604 int ret;
605
606 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
607 GNUNET_assert (GNUNET_YES == ret);
608 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
609 GNUNET_assert (NULL != ctx);
610 return ctx;
611}
612
613/**
614 * Create a new peer context and insert it into the peer map
615 */
616struct PeerContext *
617create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
618{
619 struct PeerContext *ctx;
620 int ret;
621
622 ctx = GNUNET_new (struct PeerContext);
623 ctx->peer_id = *peer;
624 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
625 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
626 GNUNET_assert (GNUNET_OK == ret);
627 return ctx;
628}
629
630
631/**
632 * Set the peer flag to living and call the outstanding operations on this peer.
633 */
634static size_t
635peer_is_live (struct PeerContext *peer_ctx)
636{
637 struct GNUNET_PeerIdentity *peer;
638
639 /* Cancle transmit_handle if still scheduled */
640 if (NULL != peer_ctx->transmit_handle)
641 {
642 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
643 peer_ctx->transmit_handle = NULL;
644 }
645
646 peer = &peer_ctx->peer_id;
647 set_peer_flag (peer_ctx, VALID);
648
649 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %s is live\n", GNUNET_i2s (peer));
650
651 if (0 < peer_ctx->num_outstanding_ops)
652 { /* Call outstanding operations */
653 unsigned int i;
654
655 for (i = 0 ; i < peer_ctx->num_outstanding_ops ; i++)
656 peer_ctx->outstanding_ops[i].op (peer_ctx->outstanding_ops[i].op_cls, peer);
657 GNUNET_array_grow (peer_ctx->outstanding_ops, peer_ctx->num_outstanding_ops, 0);
658 }
659
660 return 0;
661}
662
663
664/**
665 * Callback that is called when a channel was effectively established.
666 * This is given to ntfy_tmt_rdy and called when the channel was
667 * successfully established.
668 */
669static size_t
670cadet_ntfy_tmt_rdy_cb (void *cls, size_t size, void *buf)
671{
672 struct PeerContext *peer_ctx = (struct PeerContext *) cls;
673
674 peer_ctx->transmit_handle = NULL;
675 LOG (GNUNET_ERROR_TYPE_DEBUG,
676 "Set ->transmit_handle = NULL for peer %s\n",
677 GNUNET_i2s (&peer_ctx->peer_id));
678
679 if (NULL != buf
680 && 0 != size)
681 {
682 peer_is_live (peer_ctx);
683 }
684 else
685 {
686 LOG (GNUNET_ERROR_TYPE_WARNING,
687 "Problems establishing a connection to peer %s in order to check liveliness\n",
688 GNUNET_i2s (&peer_ctx->peer_id));
689 // TODO reschedule? cleanup?
690 }
691
692 //if (NULL != peer_ctx->transmit_handle)
693 //{
694 // LOG (GNUNET_ERROR_TYPE_DEBUG,
695 // "Trying to cancle transmit_handle for peer %s\n",
696 // GNUNET_i2s (&peer_ctx->peer_id));
697 // GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
698 // peer_ctx->transmit_handle = NULL;
699 //}
700
701 return 0;
702}
703
704
705/**
706 * Get the channel of a peer. If not existing, create.
707 */
708 struct GNUNET_CADET_Channel *
709get_channel (const struct GNUNET_PeerIdentity *peer)
710{
711 struct PeerContext *peer_ctx;
712
713 peer_ctx = get_peer_ctx (peer);
714 if (NULL == peer_ctx->send_channel)
715 {
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Trying to establish channel to peer %s\n",
718 GNUNET_i2s (peer));
719
720 peer_ctx->send_channel =
721 GNUNET_CADET_channel_create (cadet_handle,
722 NULL,
723 peer,
724 GNUNET_RPS_CADET_PORT,
725 GNUNET_CADET_OPTION_RELIABLE);
726
727 }
728 return peer_ctx->send_channel;
729}
730
731
732/**
733 * Get the message queue of a specific peer.
734 *
735 * If we already have a message queue open to this client,
736 * simply return it, otherways create one.
737 */
738 struct GNUNET_MQ_Handle *
739get_mq (const struct GNUNET_PeerIdentity *peer_id)
740{
741 struct PeerContext *peer_ctx;
742
743 peer_ctx = get_peer_ctx (peer_id);
744
745 GNUNET_assert (NULL == peer_ctx->transmit_handle);
746
747 if (NULL == peer_ctx->mq)
748 {
749 (void) get_channel (peer_id);
750 peer_ctx->mq = GNUNET_CADET_mq_create (peer_ctx->send_channel);
751 //do I have to explicitly put it in the peer_map?
752 (void) GNUNET_CONTAINER_multipeermap_put (peer_map, peer_id, peer_ctx,
753 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
754 }
755 return peer_ctx->mq;
756}
757
758
759/**
760 * Issue check whether peer is live
761 *
762 * @param peer_ctx the context of the peer
763 */
764void
765check_peer_live (struct PeerContext *peer_ctx)
766{
767 LOG (GNUNET_ERROR_TYPE_DEBUG,
768 "Get informed about peer %s getting live\n",
769 GNUNET_i2s (&peer_ctx->peer_id));
770
771 if (NULL == peer_ctx->transmit_handle &&
772 NULL == peer_ctx->send_channel)
773 {
774 (void) get_channel (&peer_ctx->peer_id);
775 peer_ctx->transmit_handle =
776 GNUNET_CADET_notify_transmit_ready (peer_ctx->send_channel,
777 GNUNET_NO,
778 GNUNET_TIME_UNIT_FOREVER_REL,
779 sizeof (struct GNUNET_MessageHeader),
780 cadet_ntfy_tmt_rdy_cb,
781 peer_ctx);
782 }
783 else if (NULL != peer_ctx->transmit_handle)
784 LOG (GNUNET_ERROR_TYPE_DEBUG,
785 "Already waiting for notification\n");
786 else if (NULL != peer_ctx->send_channel)
787 LOG (GNUNET_ERROR_TYPE_DEBUG,
788 "Already have established channel to peer\n");
789}
790
791
792/**
793 * Sum all time relatives of an array. 430 * Sum all time relatives of an array.
794 */ 431 */
795 struct GNUNET_TIME_Relative 432 struct GNUNET_TIME_Relative
@@ -818,92 +455,6 @@ T_relative_avg (const struct GNUNET_TIME_Relative *rel_array, uint32_t arr_size)
818 455
819 456
820/** 457/**
821 * Insert PeerID in #pull_map
822 *
823 * Called once we know a peer is live.
824 */
825 void
826insert_in_pull_map (void *cls, const struct GNUNET_PeerIdentity *peer)
827{
828 CustomPeerMap_put (pull_map, peer);
829}
830
831/**
832 * Check whether #insert_in_pull_map was already scheduled
833 */
834 int
835insert_in_pull_map_scheduled (const struct PeerContext *peer_ctx)
836{
837 unsigned int i;
838
839 for ( i = 0 ; i < peer_ctx->num_outstanding_ops ; i++ )
840 if (insert_in_pull_map == peer_ctx->outstanding_ops[i].op)
841 return GNUNET_YES;
842 return GNUNET_NO;
843}
844
845
846/**
847 * Insert PeerID in #view
848 *
849 * Called once we know a peer is live.
850 */
851 void
852insert_in_view (void *cls, const struct GNUNET_PeerIdentity *peer)
853{
854 View_put (peer);
855}
856
857/**
858 * Check whether #insert_in_view was already scheduled
859 */
860 int
861insert_in_view_scheduled (const struct PeerContext *peer_ctx)
862{
863 unsigned int i;
864
865 for ( i = 0 ; i < peer_ctx->num_outstanding_ops ; i++ )
866 if (insert_in_view == peer_ctx->outstanding_ops[i].op)
867 return GNUNET_YES;
868 return GNUNET_NO;
869}
870
871
872/**
873 * Update sampler with given PeerID.
874 */
875 void
876insert_in_sampler (void *cls, const struct GNUNET_PeerIdentity *peer)
877{
878 LOG (GNUNET_ERROR_TYPE_DEBUG,
879 "Updating samplers with peer %s from insert_in_sampler()\n",
880 GNUNET_i2s (peer));
881 RPS_sampler_update (prot_sampler, peer);
882 RPS_sampler_update (client_sampler, peer);
883 if (0 < RPS_sampler_count_id (prot_sampler, peer))
884 {
885 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
886 (void) create_peer_ctx (peer);
887 (void) get_channel (peer);
888 }
889}
890
891
892/**
893 * Check whether #insert_in_sampler was already scheduled
894 */
895static int
896insert_in_sampler_scheduled (const struct PeerContext *peer_ctx)
897{
898 unsigned int i;
899
900 for (i = 0 ; i < peer_ctx->num_outstanding_ops ; i++)
901 if (insert_in_sampler== peer_ctx->outstanding_ops[i].op)
902 return GNUNET_YES;
903 return GNUNET_NO;
904}
905
906/**
907 * Put random peer from sampler into the view as history update. 458 * Put random peer from sampler into the view as history update.
908 */ 459 */
909 void 460 void
@@ -1044,61 +595,6 @@ add_peer_array_to_set (const struct GNUNET_PeerIdentity *peer_array,
1044 595
1045 596
1046/** 597/**
1047 * @brief Add an envelope to a message passed to mq to list of pending messages
1048 *
1049 * @param peer peer the message was sent to
1050 * @param ev envelope to the message
1051 * @param type type of the message to be sent
1052 */
1053static struct PendingMessage *
1054insert_pending_message (const struct GNUNET_PeerIdentity *peer,
1055 struct GNUNET_MQ_Envelope *ev,
1056 const char *type)
1057{
1058 struct PendingMessage *pending_msg;
1059 struct PeerContext *peer_ctx;
1060
1061 peer_ctx = get_peer_ctx (peer);
1062 pending_msg = GNUNET_new (struct PendingMessage);
1063 pending_msg->ev = ev;
1064 pending_msg->peer_ctx = peer_ctx;
1065 pending_msg->type = type;
1066 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
1067 peer_ctx->pending_messages_tail,
1068 pending_msg);
1069 return pending_msg;
1070}
1071
1072static void
1073remove_pending_message (struct PendingMessage *pending_msg)
1074{
1075 struct PeerContext *peer_ctx;
1076
1077 peer_ctx = pending_msg->peer_ctx;
1078 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
1079 peer_ctx->pending_messages_tail,
1080 pending_msg);
1081 GNUNET_free (pending_msg);
1082}
1083
1084
1085/**
1086 * @brief This is called once a message is sent.
1087 *
1088 * @param cls type of the message that was sent
1089 */
1090static void
1091mq_notify_sent_cb (void *cls)
1092{
1093 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
1094 LOG (GNUNET_ERROR_TYPE_DEBUG,
1095 "%s was sent.\n",
1096 pending_msg->type);
1097 remove_pending_message (pending_msg);
1098}
1099
1100
1101/**
1102 * Send a PULL REPLY to @a peer_id 598 * Send a PULL REPLY to @a peer_id
1103 * 599 *
1104 * @param peer_id the peer to send the reply to. 600 * @param peer_id the peer to send the reply to.
@@ -1111,10 +607,8 @@ send_pull_reply (const struct GNUNET_PeerIdentity *peer_id,
1111 unsigned int num_peer_ids) 607 unsigned int num_peer_ids)
1112{ 608{
1113 uint32_t send_size; 609 uint32_t send_size;
1114 struct GNUNET_MQ_Handle *mq;
1115 struct GNUNET_MQ_Envelope *ev; 610 struct GNUNET_MQ_Envelope *ev;
1116 struct GNUNET_RPS_P2P_PullReplyMessage *out_msg; 611 struct GNUNET_RPS_P2P_PullReplyMessage *out_msg;
1117 struct PendingMessage *pending_msg;
1118 612
1119 /* Compute actual size */ 613 /* Compute actual size */
1120 send_size = sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) + 614 send_size = sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) +
@@ -1136,8 +630,6 @@ send_pull_reply (const struct GNUNET_PeerIdentity *peer_id,
1136 "Going to send PULL REPLY with %u peers to %s\n", 630 "Going to send PULL REPLY with %u peers to %s\n",
1137 send_size, GNUNET_i2s (peer_id)); 631 send_size, GNUNET_i2s (peer_id));
1138 632
1139 mq = get_mq (peer_id);
1140
1141 ev = GNUNET_MQ_msg_extra (out_msg, 633 ev = GNUNET_MQ_msg_extra (out_msg,
1142 send_size * sizeof (struct GNUNET_PeerIdentity), 634 send_size * sizeof (struct GNUNET_PeerIdentity),
1143 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY); 635 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY);
@@ -1145,69 +637,224 @@ send_pull_reply (const struct GNUNET_PeerIdentity *peer_id,
1145 memcpy (&out_msg[1], peer_ids, 637 memcpy (&out_msg[1], peer_ids,
1146 send_size * sizeof (struct GNUNET_PeerIdentity)); 638 send_size * sizeof (struct GNUNET_PeerIdentity));
1147 639
1148 pending_msg = insert_pending_message (peer_id, ev, "PULL REPLY"); 640 Peers_send_message (peer_id, ev, "PULL REPLY");
1149 GNUNET_MQ_notify_sent (ev,
1150 mq_notify_sent_cb,
1151 pending_msg);
1152 GNUNET_MQ_send (mq, ev);
1153} 641}
1154 642
1155 643
1156/** 644/**
1157 * This function is called on new peer_ids from 'external' sources 645 * Insert PeerID in #pull_map
1158 * (client seed, cadet get_peers(), ...)
1159 * 646 *
1160 * @param peer_id the new peer_id 647 * Called once we know a peer is live.
1161 */ 648 */
1162static void 649 void
1163new_peer_id (const struct GNUNET_PeerIdentity *peer_id) 650insert_in_pull_map (void *cls, const struct GNUNET_PeerIdentity *peer)
1164{ 651{
1165 struct PeerOutstandingOp out_op; 652 CustomPeerMap_put (pull_map, peer);
1166 struct PeerContext *peer_ctx; 653}
1167 654
1168 if ((NULL == peer_id) || 655/**
1169 (0 == GNUNET_CRYPTO_cmp_peer_identity (&own_identity, peer_id))) 656 * Insert PeerID in #view
1170 return; 657 *
658 * Called once we know a peer is live.
659 */
660 void
661insert_in_view (void *cls, const struct GNUNET_PeerIdentity *peer)
662{
663 View_put (peer);
664}
665
666/**
667 * Update sampler with given PeerID.
668 */
669 void
670insert_in_sampler (void *cls, const struct GNUNET_PeerIdentity *peer)
671{
1171 LOG (GNUNET_ERROR_TYPE_DEBUG, 672 LOG (GNUNET_ERROR_TYPE_DEBUG,
1172 "Got peer_id %s (at %p, view size: %u)\n", 673 "Updating samplers with peer %s from insert_in_sampler()\n",
1173 GNUNET_i2s (peer_id), 674 GNUNET_i2s (peer));
1174 peer_id, 675 RPS_sampler_update (prot_sampler, peer);
1175 View_size ()); 676 RPS_sampler_update (client_sampler, peer);
1176 677 if (0 < RPS_sampler_count_id (prot_sampler, peer))
1177 /* if the seed peer is already know, skip context creation */ 678 {
1178 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer_id)) 679 /* Make sure we 'know' about this peer */
1179 peer_ctx = create_peer_ctx (peer_id); 680 (void) Peers_insert_peer (peer);
1180 else 681 /* Establish a channel towards that peer to indicate we are going to send
1181 peer_ctx = get_peer_ctx (peer_id); 682 * messages to it */
683 Peers_indicate_sending_intention (peer);
684 //Peers_issue_peer_liveliness_check (peer);
685 }
686}
1182 687
1183 if (GNUNET_NO == get_peer_flag (peer_ctx, VALID)) 688
689/**
690 * @brief Checks if there is a sending channel and if it is needed
691 *
692 * @param peer the peer whose sending channel is checked
693 * @return GNUNET_YES if sending channel exists and is still needed
694 * GNUNET_NO otherwise
695 */
696static int
697check_sending_channel_needed (const struct GNUNET_PeerIdentity *peer)
698{
699 /* struct GNUNET_CADET_Channel *channel; */
700 if (GNUNET_NO == Peers_check_peer_known (peer))
1184 { 701 {
1185 if (GNUNET_NO == insert_in_sampler_scheduled (peer_ctx)) 702 return GNUNET_NO;
1186 { 703 }
1187 out_op.op = insert_in_sampler; 704 if (GNUNET_YES == Peers_check_sending_channel_exists (peer))
1188 out_op.op_cls = NULL; 705 {
1189 GNUNET_array_append (peer_ctx->outstanding_ops, 706 if ( (0 < RPS_sampler_count_id (prot_sampler, peer)) ||
1190 peer_ctx->num_outstanding_ops, 707 (GNUNET_YES == View_contains_peer (peer)) ||
1191 out_op); 708 (GNUNET_YES == CustomPeerMap_contains_peer (push_map, peer)) ||
709 (GNUNET_YES == CustomPeerMap_contains_peer (pull_map, peer)) ||
710 (GNUNET_YES == Peers_check_peer_flag (peer, Peers_PULL_REPLY_PENDING)))
711 { /* If we want to keep the connection to peer open */
712 return GNUNET_YES;
1192 } 713 }
714 return GNUNET_NO;
715 }
716 return GNUNET_NO;
717}
718
719/**
720 * @brief remove peer from our knowledge, the view, push and pull maps and
721 * samplers.
722 *
723 * @param peer the peer to remove
724 */
725static void
726remove_peer (const struct GNUNET_PeerIdentity *peer)
727{
728 View_remove_peer (peer);
729 CustomPeerMap_remove_peer (pull_map, peer);
730 CustomPeerMap_remove_peer (push_map, peer);
731 RPS_sampler_reinitialise_by_value (prot_sampler, peer);
732 RPS_sampler_reinitialise_by_value (client_sampler, peer);
733 Peers_remove_peer (peer);
734}
1193 735
1194 if (GNUNET_NO == insert_in_view_scheduled (peer_ctx))
1195 {
1196 out_op.op = insert_in_view;
1197 out_op.op_cls = NULL;
1198 GNUNET_array_append (peer_ctx->outstanding_ops,
1199 peer_ctx->num_outstanding_ops,
1200 out_op);
1201 }
1202 736
1203 /* Trigger livelyness test on peer */ 737/**
1204 check_peer_live (peer_ctx); 738 * @brief Remove data that is not needed anymore.
739 *
740 * If the sending channel is no longer needed it is destroyed.
741 *
742 * @param peer the peer whose data is about to be cleaned
743 */
744static void
745clean_peer (const struct GNUNET_PeerIdentity *peer)
746{
747 if (GNUNET_NO == check_sending_channel_needed (peer))
748 {
749 #ifdef ENABLE_MALICIOUS
750 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
751 Peers_destroy_sending_channel (peer);
752 #else /* ENABLE_MALICIOUS */
753 Peers_destroy_sending_channel (peer);
754 #endif /* ENABLE_MALICIOUS */
1205 } 755 }
1206 // else...?
1207 756
1208 // send push/pull to each of those peers? 757 if ( (GNUNET_NO == Peers_check_peer_send_intention (peer)) &&
758 (GNUNET_NO == View_contains_peer (peer)) &&
759 (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
760 (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
761 (0 == RPS_sampler_count_id (prot_sampler, peer)) &&
762 (0 == RPS_sampler_count_id (client_sampler, peer)) )
763 { /* We can safely remov this peer */
764 remove_peer (peer);
765 return;
766 }
767 Peers_clean_peer (peer);
1209} 768}
1210 769
770/**
771 * @brief This is called when a channel is destroyed.
772 *
773 * Removes peer completely from our knowledge if the send_channel was destroyed
774 * Otherwise simply delete the recv_channel
775 *
776 * @param cls The closure
777 * @param channel The channel being closed
778 * @param channel_ctx The context associated with this channel
779 */
780static void
781cleanup_destroyed_channel (void *cls,
782 const struct GNUNET_CADET_Channel *channel,
783 void *channel_ctx)
784{
785 struct GNUNET_PeerIdentity *peer;
786
787 peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
788 (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
789 // FIXME wait for cadet to change this function
790
791 if (GNUNET_NO == Peers_check_peer_known (peer))
792 { /* We don't know a context to that peer */
793 LOG (GNUNET_ERROR_TYPE_WARNING,
794 "channel (%s) without associated context was destroyed\n",
795 GNUNET_i2s (peer));
796 return;
797 }
798
799 if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY))
800 { /* We are in the middle of removing that peer from our knowledge. In this
801 case simply make sure that the channels are cleaned. */
802 Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
803 to_file (file_name_view_log,
804 "-%s\t(cleanup channel, ourself)",
805 GNUNET_i2s_full (peer));
806 return;
807 }
808
809 if (GNUNET_YES ==
810 Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING))
811 { /* Channel used for sending was destroyed */
812 /* Possible causes of channel destruction:
813 * - ourselves -> cleaning send channel -> clean context
814 * - other peer -> peer probably went down -> remove
815 */
816 if (GNUNET_YES == Peers_check_channel_flag (channel_ctx, Peers_CHANNEL_CLEAN))
817 { /* We are about to clean the sending channel. Clean the respective
818 * context */
819 Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
820 return;
821 }
822 else
823 { /* Other peer destroyed our sending channel that he is supposed to keep
824 * open. It probably went down. Remove it from our knowledge. */
825 Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
826 remove_peer (peer);
827 return;
828 }
829 }
830 else if (GNUNET_YES ==
831 Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING))
832 { /* Channel used for receiving was destroyed */
833 /* Possible causes of channel destruction:
834 * - ourselves -> peer tried to establish channel twice -> clean context
835 * - other peer -> peer doesn't want to send us data -> clean
836 */
837 if (GNUNET_YES ==
838 Peers_check_channel_flag (channel_ctx, Peers_CHANNEL_ESTABLISHED_TWICE))
839 { /* Other peer tried to establish a channel to us twice. We do not accept
840 * that. Clean the context. */
841 Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
842 return;
843 }
844 else
845 { /* Other peer doesn't want to send us data anymore. We are free to clean
846 * it. */
847 Peers_cleanup_destroyed_channel (cls, channel, channel_ctx);
848 clean_peer (peer);
849 return;
850 }
851 }
852 else
853 {
854 LOG (GNUNET_ERROR_TYPE_WARNING,
855 "Destroyed channel is neither sending nor receiving channel\n");
856 }
857}
1211 858
1212/*********************************************************************** 859/***********************************************************************
1213 * /Util functions 860 * /Util functions
@@ -1285,8 +932,10 @@ nse_callback (void *cls, struct GNUNET_TIME_Absolute timestamp,
1285 * 932 *
1286 * Sends those to the requesting client. 933 * Sends those to the requesting client.
1287 */ 934 */
1288void client_respond (void *cls, 935void
1289 struct GNUNET_PeerIdentity *peer_ids, uint32_t num_peers) 936client_respond (void *cls,
937 struct GNUNET_PeerIdentity *peer_ids,
938 uint32_t num_peers)
1290{ 939{
1291 uint32_t i; 940 uint32_t i;
1292 struct GNUNET_MQ_Envelope *ev; 941 struct GNUNET_MQ_Envelope *ev;
@@ -1466,14 +1115,18 @@ handle_client_seed (void *cls,
1466 "Client seeded peers:\n"); 1115 "Client seeded peers:\n");
1467 print_peer_list (peers, num_peers); 1116 print_peer_list (peers, num_peers);
1468 1117
1469 for (i = 0 ; i < num_peers ; i++) 1118 for (i = 0; i < num_peers; i++)
1470 { 1119 {
1471 LOG (GNUNET_ERROR_TYPE_DEBUG, 1120 LOG (GNUNET_ERROR_TYPE_DEBUG,
1472 "Updating samplers with seed %" PRIu32 ": %s\n", 1121 "Updating samplers with seed %" PRIu32 ": %s\n",
1473 i, 1122 i,
1474 GNUNET_i2s (&peers[i])); 1123 GNUNET_i2s (&peers[i]));
1475 1124
1476 new_peer_id (&peers[i]); 1125 if (GNUNET_YES == Peers_insert_peer (&peers[i]))
1126 {
1127 Peers_schedule_operation (&peers[i], insert_in_sampler);
1128 Peers_schedule_operation (&peers[i], insert_in_view);
1129 }
1477 1130
1478 //RPS_sampler_update (prot_sampler, &peers[i]); 1131 //RPS_sampler_update (prot_sampler, &peers[i]);
1479 //RPS_sampler_update (client_sampler, &peers[i]); 1132 //RPS_sampler_update (client_sampler, &peers[i]);
@@ -1505,7 +1158,7 @@ handle_peer_push (void *cls,
1505{ 1158{
1506 const struct GNUNET_PeerIdentity *peer; 1159 const struct GNUNET_PeerIdentity *peer;
1507 1160
1508 // (check the proof of work) 1161 // (check the proof of work (?))
1509 1162
1510 peer = (const struct GNUNET_PeerIdentity *) 1163 peer = (const struct GNUNET_PeerIdentity *)
1511 GNUNET_CADET_channel_get_info (channel, GNUNET_CADET_OPTION_PEER); 1164 GNUNET_CADET_channel_get_info (channel, GNUNET_CADET_OPTION_PEER);
@@ -1626,10 +1279,7 @@ handle_peer_pull_reply (void *cls,
1626{ 1279{
1627 struct GNUNET_RPS_P2P_PullReplyMessage *in_msg; 1280 struct GNUNET_RPS_P2P_PullReplyMessage *in_msg;
1628 struct GNUNET_PeerIdentity *peers; 1281 struct GNUNET_PeerIdentity *peers;
1629 struct PeerContext *peer_ctx;
1630 struct GNUNET_PeerIdentity *sender; 1282 struct GNUNET_PeerIdentity *sender;
1631 struct PeerContext *sender_ctx;
1632 struct PeerOutstandingOp out_op;
1633 uint32_t i; 1283 uint32_t i;
1634#ifdef ENABLE_MALICIOUS 1284#ifdef ENABLE_MALICIOUS
1635 struct AttackedPeer *tmp_att_peer; 1285 struct AttackedPeer *tmp_att_peer;
@@ -1661,11 +1311,10 @@ handle_peer_pull_reply (void *cls,
1661 // FIXME wait for cadet to change this function 1311 // FIXME wait for cadet to change this function
1662 sender = (struct GNUNET_PeerIdentity *) 1312 sender = (struct GNUNET_PeerIdentity *)
1663 GNUNET_CADET_channel_get_info (channel, GNUNET_CADET_OPTION_PEER); 1313 GNUNET_CADET_channel_get_info (channel, GNUNET_CADET_OPTION_PEER);
1664 sender_ctx = get_peer_ctx (sender);
1665 1314
1666 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (sender)); 1315 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (sender));
1667 1316
1668 if (GNUNET_YES != get_peer_flag (sender_ctx, PULL_REPLY_PENDING)) 1317 if (GNUNET_YES != Peers_check_peer_flag (sender, Peers_PULL_REPLY_PENDING))
1669 { 1318 {
1670 LOG (GNUNET_ERROR_TYPE_WARNING, 1319 LOG (GNUNET_ERROR_TYPE_WARNING,
1671 "Received a pull reply from a peer we didn't request one from!\n"); 1320 "Received a pull reply from a peer we didn't request one from!\n");
@@ -1720,31 +1369,23 @@ handle_peer_pull_reply (void *cls,
1720 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, 1369 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity,
1721 &peers[i])) 1370 &peers[i]))
1722 { 1371 {
1723 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, 1372 /* Make sure we 'know' about this peer */
1724 &peers[i])) 1373 (void) Peers_insert_peer (&peers[i]);
1725 peer_ctx = create_peer_ctx (&peers[i]);
1726 else
1727 peer_ctx = get_peer_ctx (&peers[i]);
1728 1374
1729 if (GNUNET_YES == get_peer_flag (peer_ctx, VALID)) 1375 if (GNUNET_YES == Peers_check_peer_flag (&peers[i], Peers_VALID))
1730 { 1376 {
1731 CustomPeerMap_put (pull_map, &peers[i]); 1377 CustomPeerMap_put (pull_map, &peers[i]);
1732 } 1378 }
1733 else if (GNUNET_NO == insert_in_pull_map_scheduled (peer_ctx)) 1379 else
1734 { 1380 {
1735 out_op.op = insert_in_pull_map; 1381 Peers_schedule_operation (&peers[i], insert_in_pull_map);
1736 out_op.op_cls = NULL; 1382 Peers_issue_peer_liveliness_check (&peers[i]);
1737 GNUNET_array_append (peer_ctx->outstanding_ops,
1738 peer_ctx->num_outstanding_ops,
1739 out_op);
1740 check_peer_live (peer_ctx);
1741 } 1383 }
1742 } 1384 }
1743 } 1385 }
1744 1386
1745 unset_peer_flag (sender_ctx, PULL_REPLY_PENDING); 1387 Peers_unset_peer_flag (sender, Peers_PULL_REPLY_PENDING);
1746 1388 clean_peer (sender);
1747 peer_clean (sender);
1748 1389
1749 GNUNET_CADET_receive_done (channel); 1390 GNUNET_CADET_receive_done (channel);
1750 return GNUNET_OK; 1391 return GNUNET_OK;
@@ -1803,28 +1444,20 @@ compute_rand_delay (struct GNUNET_TIME_Relative mean, unsigned int spread)
1803 * @param peer_id the peer to send the pull request to. 1444 * @param peer_id the peer to send the pull request to.
1804 */ 1445 */
1805static void 1446static void
1806send_pull_request (const struct GNUNET_PeerIdentity *peer_id) 1447send_pull_request (const struct GNUNET_PeerIdentity *peer)
1807{ 1448{
1808 struct GNUNET_MQ_Envelope *ev; 1449 struct GNUNET_MQ_Envelope *ev;
1809 struct GNUNET_MQ_Handle *mq;
1810 struct PeerContext *peer_ctx;
1811 struct PendingMessage *pending_msg;
1812 1450
1813 peer_ctx = get_peer_ctx (peer_id); 1451 GNUNET_assert (GNUNET_NO == Peers_check_peer_flag (peer,
1814 GNUNET_assert (GNUNET_NO == get_peer_flag (peer_ctx, PULL_REPLY_PENDING)); 1452 Peers_PULL_REPLY_PENDING));
1815 set_peer_flag (peer_ctx, PULL_REPLY_PENDING); 1453 Peers_set_peer_flag (peer, Peers_PULL_REPLY_PENDING);
1816 1454
1817 LOG (GNUNET_ERROR_TYPE_DEBUG, 1455 LOG (GNUNET_ERROR_TYPE_DEBUG,
1818 "Going to send PULL REQUEST to peer %s.\n", 1456 "Going to send PULL REQUEST to peer %s.\n",
1819 GNUNET_i2s (peer_id)); 1457 GNUNET_i2s (peer));
1820 1458
1821 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST); 1459 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST);
1822 mq = get_mq (peer_id); 1460 Peers_send_message (peer, ev, "PULL REQUEST");
1823 pending_msg = insert_pending_message (peer_id, ev, "PULL REQUEST");
1824 GNUNET_MQ_notify_sent (ev,
1825 mq_notify_sent_cb,
1826 pending_msg);
1827 GNUNET_MQ_send (mq, ev);
1828} 1461}
1829 1462
1830 1463
@@ -1837,20 +1470,13 @@ static void
1837send_push (const struct GNUNET_PeerIdentity *peer_id) 1470send_push (const struct GNUNET_PeerIdentity *peer_id)
1838{ 1471{
1839 struct GNUNET_MQ_Envelope *ev; 1472 struct GNUNET_MQ_Envelope *ev;
1840 struct GNUNET_MQ_Handle *mq;
1841 struct PendingMessage *pending_msg;
1842 1473
1843 LOG (GNUNET_ERROR_TYPE_DEBUG, 1474 LOG (GNUNET_ERROR_TYPE_DEBUG,
1844 "Going to send PUSH to peer %s.\n", 1475 "Going to send PUSH to peer %s.\n",
1845 GNUNET_i2s (peer_id)); 1476 GNUNET_i2s (peer_id));
1846 1477
1847 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PUSH); 1478 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_PUSH);
1848 mq = get_mq (peer_id); 1479 Peers_send_message (peer_id, ev, "PUSH");
1849 pending_msg = insert_pending_message (peer_id, ev, "PUSH");
1850 GNUNET_MQ_notify_sent (ev,
1851 mq_notify_sent_cb,
1852 pending_msg);
1853 GNUNET_MQ_send (mq, ev);
1854} 1480}
1855 1481
1856 1482
@@ -1932,11 +1558,10 @@ handle_client_act_malicious (void *cls,
1932 do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, NULL); 1558 do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, NULL);
1933 } 1559 }
1934 1560
1935 else if (2 == mal_type 1561 else if ( (2 == mal_type) ||
1936 || 3 == mal_type) 1562 (3 == mal_type) )
1937 { /* Try to partition the network */ 1563 { /* Try to partition the network */
1938 /* Add other malicious peers to those we already know */ 1564 /* Add other malicious peers to those we already know */
1939 struct PeerContext *att_ctx;
1940 1565
1941 num_mal_peers_sent = ntohl (in_msg->num_peers) - 1; 1566 num_mal_peers_sent = ntohl (in_msg->num_peers) - 1;
1942 num_mal_peers_old = num_mal_peers; 1567 num_mal_peers_old = num_mal_peers;
@@ -1961,11 +1586,10 @@ handle_client_act_malicious (void *cls,
1961 &in_msg->attacked_peer, 1586 &in_msg->attacked_peer,
1962 sizeof (struct GNUNET_PeerIdentity)); 1587 sizeof (struct GNUNET_PeerIdentity));
1963 /* Set the flag of the attacked peer to valid to avoid problems */ 1588 /* Set the flag of the attacked peer to valid to avoid problems */
1964 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, 1589 if (GNUNET_NO == Peers_check_peer_known (&attacked_peer))
1965 &attacked_peer))
1966 { 1590 {
1967 att_ctx = create_peer_ctx (&attacked_peer); 1591 Peers_insert_peer (&attacked_peer);
1968 check_peer_live (att_ctx); 1592 Peers_issue_peer_liveliness_check (&attacked_peer);
1969 } 1593 }
1970 1594
1971 LOG (GNUNET_ERROR_TYPE_DEBUG, 1595 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -2005,7 +1629,6 @@ do_mal_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2005 uint32_t i; 1629 uint32_t i;
2006 struct GNUNET_TIME_Relative time_next_round; 1630 struct GNUNET_TIME_Relative time_next_round;
2007 struct AttackedPeer *tmp_att_peer; 1631 struct AttackedPeer *tmp_att_peer;
2008 struct PeerContext *peer_ctx;
2009 1632
2010 LOG (GNUNET_ERROR_TYPE_DEBUG, "Going to execute next round maliciously type %" PRIu32 ".\n", 1633 LOG (GNUNET_ERROR_TYPE_DEBUG, "Going to execute next round maliciously type %" PRIu32 ".\n",
2011 mal_type); 1634 mal_type);
@@ -2055,8 +1678,8 @@ do_mal_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2055 * Send as many pushes to the attacked peer as possible 1678 * Send as many pushes to the attacked peer as possible
2056 * That is one push per round as it will ignore more. 1679 * That is one push per round as it will ignore more.
2057 */ 1680 */
2058 peer_ctx = get_peer_ctx (&attacked_peer); 1681 Peers_insert_peer (&attacked_peer);
2059 if (GNUNET_YES == get_peer_flag (peer_ctx, VALID)) 1682 if (GNUNET_YES == Peers_check_peer_flag (&attacked_peer, Peers_VALID))
2060 send_push (&attacked_peer); 1683 send_push (&attacked_peer);
2061 } 1684 }
2062 1685
@@ -2065,11 +1688,10 @@ do_mal_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2065 { /* Combined attack */ 1688 { /* Combined attack */
2066 1689
2067 /* Send PUSH to attacked peers */ 1690 /* Send PUSH to attacked peers */
2068 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (peer_map, 1691 if (GNUNET_YES == Peers_check_peer_known (&attacked_peer))
2069 &attacked_peer))
2070 { 1692 {
2071 peer_ctx = get_peer_ctx (&attacked_peer); 1693 Peers_insert_peer (&attacked_peer);
2072 if (GNUNET_YES == get_peer_flag (peer_ctx, VALID)) 1694 if (GNUNET_YES == Peers_check_peer_flag (&attacked_peer, Peers_VALID))
2073 { 1695 {
2074 LOG (GNUNET_ERROR_TYPE_DEBUG, 1696 LOG (GNUNET_ERROR_TYPE_DEBUG,
2075 "Goding to send push to attacked peer (%s)\n", 1697 "Goding to send push to attacked peer (%s)\n",
@@ -2077,11 +1699,11 @@ do_mal_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2077 send_push (&attacked_peer); 1699 send_push (&attacked_peer);
2078 } 1700 }
2079 else 1701 else
2080 check_peer_live (peer_ctx); 1702 Peers_issue_peer_liveliness_check (&attacked_peer);
2081 } 1703 }
2082 else 1704 else
2083 peer_ctx = create_peer_ctx (&attacked_peer); 1705 Peers_insert_peer (&attacked_peer);
2084 check_peer_live (peer_ctx); 1706 Peers_issue_peer_liveliness_check (&attacked_peer);
2085 1707
2086 /* The maximum of pushes we're going to send this round */ 1708 /* The maximum of pushes we're going to send this round */
2087 num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1, 1709 num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1,
@@ -2092,7 +1714,7 @@ do_mal_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2092 "Going to send %" PRIu32 " pushes\n", 1714 "Going to send %" PRIu32 " pushes\n",
2093 num_pushes); 1715 num_pushes);
2094 1716
2095 for (i = 0 ; i < num_pushes ; i++) 1717 for (i = 0; i < num_pushes; i++)
2096 { 1718 {
2097 if (att_peers_tail == att_peer_index) 1719 if (att_peers_tail == att_peer_index)
2098 att_peer_index = att_peers_head; 1720 att_peer_index = att_peers_head;
@@ -2104,7 +1726,7 @@ do_mal_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2104 1726
2105 /* Send PULLs to some peers to learn about additional peers to attack */ 1727 /* Send PULLs to some peers to learn about additional peers to attack */
2106 tmp_att_peer = att_peer_index; 1728 tmp_att_peer = att_peer_index;
2107 for (i = 0 ; i < num_pushes * alpha ; i++) 1729 for (i = 0; i < num_pushes * alpha; i++)
2108 { 1730 {
2109 if (att_peers_tail == tmp_att_peer) 1731 if (att_peers_tail == tmp_att_peer)
2110 tmp_att_peer = att_peers_head; 1732 tmp_att_peer = att_peers_head;
@@ -2145,7 +1767,6 @@ do_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2145 uint32_t first_border; 1767 uint32_t first_border;
2146 uint32_t second_border; 1768 uint32_t second_border;
2147 struct GNUNET_PeerIdentity peer; 1769 struct GNUNET_PeerIdentity peer;
2148 struct PeerContext *peer_ctx;
2149 struct GNUNET_PeerIdentity *update_peer; 1770 struct GNUNET_PeerIdentity *update_peer;
2150 1771
2151 do_round_task = NULL; 1772 do_round_task = NULL;
@@ -2200,9 +1821,8 @@ do_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2200 for (i = first_border; i < second_border; i++) 1821 for (i = first_border; i < second_border; i++)
2201 { 1822 {
2202 peer = view_array[permut[i]]; 1823 peer = view_array[permut[i]];
2203 peer_ctx = get_peer_ctx (&peer);
2204 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer) && 1824 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&own_identity, &peer) &&
2205 GNUNET_NO == get_peer_flag (peer_ctx, PULL_REPLY_PENDING)) // TODO 1825 GNUNET_NO == Peers_check_peer_flag (&peer, Peers_PULL_REPLY_PENDING)) // TODO
2206 { // FIXME if this fails schedule/loop this for later 1826 { // FIXME if this fails schedule/loop this for later
2207 send_pull_request (&peer); 1827 send_pull_request (&peer);
2208 } 1828 }
@@ -2292,7 +1912,8 @@ do_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2292 to_file (file_name_view_log, 1912 to_file (file_name_view_log,
2293 "-%s", 1913 "-%s",
2294 GNUNET_i2s_full (&peers_to_clean[i])); 1914 GNUNET_i2s_full (&peers_to_clean[i]));
2295 peer_clean (&peers_to_clean[i]); 1915 Peers_clean_peer (&peers_to_clean[i]);
1916 //peer_destroy_channel_send (sender);
2296 } 1917 }
2297 1918
2298 GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0); 1919 GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
@@ -2320,7 +1941,8 @@ do_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2320 "Updating with peer %s from push list\n", 1941 "Updating with peer %s from push list\n",
2321 GNUNET_i2s (update_peer)); 1942 GNUNET_i2s (update_peer));
2322 insert_in_sampler (NULL, update_peer); 1943 insert_in_sampler (NULL, update_peer);
2323 peer_clean (update_peer); /* This cleans only if it is not in the view */ 1944 Peers_clean_peer (update_peer); /* This cleans only if it is not in the view */
1945 //peer_destroy_channel_send (sender);
2324 } 1946 }
2325 1947
2326 for (i = 0; i < CustomPeerMap_size (pull_map); i++) 1948 for (i = 0; i < CustomPeerMap_size (pull_map); i++)
@@ -2330,7 +1952,8 @@ do_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2330 GNUNET_i2s (CustomPeerMap_get_peer_by_index (pull_map, i))); 1952 GNUNET_i2s (CustomPeerMap_get_peer_by_index (pull_map, i)));
2331 insert_in_sampler (NULL, CustomPeerMap_get_peer_by_index (pull_map, i)); 1953 insert_in_sampler (NULL, CustomPeerMap_get_peer_by_index (pull_map, i));
2332 /* This cleans only if it is not in the view */ 1954 /* This cleans only if it is not in the view */
2333 peer_clean (CustomPeerMap_get_peer_by_index (pull_map, i)); 1955 Peers_clean_peer (CustomPeerMap_get_peer_by_index (pull_map, i));
1956 //peer_destroy_channel_send (sender);
2334 } 1957 }
2335 1958
2336 1959
@@ -2371,7 +1994,9 @@ init_peer_cb (void *cls,
2371 LOG (GNUNET_ERROR_TYPE_DEBUG, 1994 LOG (GNUNET_ERROR_TYPE_DEBUG,
2372 "Got peer_id %s from cadet\n", 1995 "Got peer_id %s from cadet\n",
2373 GNUNET_i2s (peer)); 1996 GNUNET_i2s (peer));
2374 new_peer_id (peer); 1997 Peers_insert_peer (peer);
1998 Peers_schedule_operation (peer, insert_in_sampler);
1999 Peers_schedule_operation (peer, insert_in_view);
2375 } 2000 }
2376} 2001}
2377 2002
@@ -2395,145 +2020,9 @@ process_peerinfo_peers (void *cls,
2395 LOG (GNUNET_ERROR_TYPE_DEBUG, 2020 LOG (GNUNET_ERROR_TYPE_DEBUG,
2396 "Got peer_id %s from peerinfo\n", 2021 "Got peer_id %s from peerinfo\n",
2397 GNUNET_i2s (peer)); 2022 GNUNET_i2s (peer));
2398 new_peer_id (peer); 2023 Peers_insert_peer (peer);
2399 } 2024 Peers_schedule_operation (peer, insert_in_sampler);
2400} 2025 Peers_schedule_operation (peer, insert_in_view);
2401
2402
2403/**
2404 * Callback used to remove peers from the multipeermap.
2405 */
2406 int
2407peer_remove_cb (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
2408{
2409 struct PeerContext *peer_ctx;
2410 const struct GNUNET_CADET_Channel *channel =
2411 (const struct GNUNET_CADET_Channel *) cls;
2412
2413 peer_ctx = (struct PeerContext *) value;
2414 set_peer_flag (peer_ctx, TO_DESTROY);
2415
2416 LOG (GNUNET_ERROR_TYPE_DEBUG,
2417 "Going to remove peer %s\n",
2418 GNUNET_i2s (&peer_ctx->peer_id));
2419
2420 /* Remove it from the sampler used for the Brahms protocol */
2421 RPS_sampler_reinitialise_by_value (prot_sampler, key);
2422
2423 /* If operations are still scheduled for this peer cancel those */
2424 if (0 != peer_ctx->num_outstanding_ops)
2425 {
2426 GNUNET_array_grow (peer_ctx->outstanding_ops,
2427 peer_ctx->num_outstanding_ops,
2428 0);
2429 }
2430
2431 /* If we are still waiting for notification whether this peer is live
2432 * cancel the according task */
2433 if (NULL != peer_ctx->transmit_handle)
2434 {
2435 LOG (GNUNET_ERROR_TYPE_DEBUG,
2436 "Trying to cancle transmit_handle for peer %s\n",
2437 GNUNET_i2s (key));
2438 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
2439 peer_ctx->transmit_handle = NULL;
2440 }
2441
2442 unset_peer_flag (peer_ctx, PULL_REPLY_PENDING);
2443
2444 /* Remove peer from view */
2445 if (View_contains_peer (key))
2446 {
2447 to_file (file_name_view_log,
2448 "-%s\t(cleanup channel, other peer)",
2449 GNUNET_i2s_full (key));
2450 View_remove_peer (key);
2451 }
2452
2453 /* Remove from push and pull lists */
2454 CustomPeerMap_remove_peer (push_map, key);
2455 CustomPeerMap_remove_peer (pull_map, key);
2456
2457 /* Cancle messages that have not been sent yet */
2458 while (NULL != peer_ctx->pending_messages_head)
2459 {
2460 LOG (GNUNET_ERROR_TYPE_DEBUG,
2461 "Removing unsent %s\n",
2462 peer_ctx->pending_messages_head->type);
2463 /* We are not able to cancel messages as #GNUNET_CADET_mq_create () does not
2464 * set a #GNUNET_MQ_CancelImpl */
2465 /* GNUNET_MQ_send_cancel (peer_ctx->pending_messages_head->ev); */
2466 remove_pending_message (peer_ctx->pending_messages_head);
2467 }
2468
2469 /* If there is still a mq destroy it */
2470 if (NULL != peer_ctx->mq)
2471 {
2472 GNUNET_MQ_destroy (peer_ctx->mq);
2473 peer_ctx->mq = NULL;
2474 }
2475
2476
2477 /* Remove the send_channel
2478 * This function should be called again from #cleanup_channel (callback
2479 * called on the destruction of channels) and clean up the rest. */
2480 if (NULL != peer_ctx->send_channel &&
2481 channel != peer_ctx->send_channel)
2482 {
2483 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
2484 peer_ctx->send_channel = NULL;
2485 }
2486
2487 /* Remove the recv_channel
2488 * This function should be called again from #cleanup_channel (callback
2489 * called on the destruction of channels) and clean up the rest. */
2490 if (NULL != peer_ctx->recv_channel &&
2491 channel != peer_ctx->recv_channel)
2492 {
2493 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
2494 peer_ctx->recv_channel = NULL;
2495 }
2496
2497 /* If there is no channel we have to remove the context now */
2498 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, key))
2499 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
2500
2501 GNUNET_free (peer_ctx);
2502
2503 return GNUNET_YES;
2504}
2505
2506
2507/**
2508 * Clean the send channel of a peer
2509 * If there is also no channel to receive messages from that peer, remove it
2510 * from the peermap.
2511 */
2512void
2513peer_clean (const struct GNUNET_PeerIdentity *peer)
2514{
2515 struct PeerContext *peer_ctx;
2516 /* struct GNUNET_CADET_Channel *channel; */
2517
2518 if ( (0 == RPS_sampler_count_id (prot_sampler, peer)) &&
2519 (GNUNET_NO == View_contains_peer (peer)) &&
2520 (GNUNET_NO == CustomPeerMap_contains_peer (push_map, peer)) &&
2521 (GNUNET_NO == CustomPeerMap_contains_peer (pull_map, peer)) &&
2522 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) )
2523 {
2524 peer_ctx = get_peer_ctx (peer);
2525
2526 if ( (NULL == peer_ctx->recv_channel) &&
2527 (NULL == peer_ctx->pending_messages_head) &&
2528 (GNUNET_NO == get_peer_flag (peer_ctx, PULL_REPLY_PENDING)) )
2529 {
2530 #ifdef ENABLE_MALICIOUS
2531 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&attacked_peer, peer))
2532 peer_remove_cb (NULL, peer, peer_ctx);
2533 #else /* ENABLE_MALICIOUS */
2534 peer_remove_cb (NULL, peer, peer_ctx);
2535 #endif /* ENABLE_MALICIOUS */
2536 }
2537 } 2026 }
2538} 2027}
2539 2028
@@ -2560,22 +2049,12 @@ shutdown_task (void *cls,
2560 do_round_task = NULL; 2049 do_round_task = NULL;
2561 } 2050 }
2562 2051
2563 { 2052 Peers_terminate ();
2564 if (GNUNET_SYSERR ==
2565 GNUNET_CONTAINER_multipeermap_iterate (peer_map, peer_remove_cb, NULL))
2566 LOG (GNUNET_ERROR_TYPE_WARNING,
2567 "Iterating over peers to disconnect from them was cancelled\n");
2568 }
2569 2053
2570 GNUNET_NSE_disconnect (nse); 2054 GNUNET_NSE_disconnect (nse);
2571 RPS_sampler_destroy (prot_sampler); 2055 RPS_sampler_destroy (prot_sampler);
2572 RPS_sampler_destroy (client_sampler); 2056 RPS_sampler_destroy (client_sampler);
2573 LOG (GNUNET_ERROR_TYPE_DEBUG,
2574 "Size of the peermap: %u\n",
2575 GNUNET_CONTAINER_multipeermap_size (peer_map));
2576 GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (peer_map));
2577 GNUNET_CADET_disconnect (cadet_handle); 2057 GNUNET_CADET_disconnect (cadet_handle);
2578 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
2579 View_destroy (); 2058 View_destroy ();
2580 CustomPeerMap_destroy (push_map); 2059 CustomPeerMap_destroy (push_map);
2581 CustomPeerMap_destroy (pull_map); 2060 CustomPeerMap_destroy (pull_map);
@@ -2645,119 +2124,6 @@ handle_client_disconnect (void *cls,
2645 2124
2646 2125
2647/** 2126/**
2648 * Handle the channel a peer opens to us.
2649 *
2650 * @param cls The closure
2651 * @param channel The channel the peer wants to establish
2652 * @param initiator The peer's peer ID
2653 * @param port The port the channel is being established over
2654 * @param options Further options
2655 */
2656 static void *
2657handle_inbound_channel (void *cls,
2658 struct GNUNET_CADET_Channel *channel,
2659 const struct GNUNET_PeerIdentity *initiator,
2660 uint32_t port,
2661 enum GNUNET_CADET_ChannelOption options)
2662{
2663 struct PeerContext *peer_ctx;
2664
2665 LOG (GNUNET_ERROR_TYPE_DEBUG,
2666 "New channel was established to us (Peer %s).\n",
2667 GNUNET_i2s (initiator));
2668 GNUNET_assert (NULL != channel); /* according to cadet API */
2669 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, initiator))
2670 peer_ctx = create_peer_ctx (initiator);
2671 else
2672 peer_ctx = get_peer_ctx (initiator);
2673 /* We only accept one incoming channel from peers */
2674 if (NULL != peer_ctx->recv_channel)
2675 {
2676 GNUNET_CADET_channel_destroy (channel);
2677 return NULL;
2678 }
2679 peer_ctx->recv_channel = channel;
2680 peer_is_live (peer_ctx);
2681 return NULL;
2682}
2683
2684
2685/**
2686 * This is called when a channel is destroyed.
2687 *
2688 * @param cls The closure
2689 * @param channel The channel being closed
2690 * @param channel_ctx The context associated with this channel
2691 */
2692 static void
2693cleanup_channel (void *cls,
2694 const struct GNUNET_CADET_Channel *channel,
2695 void *channel_ctx)
2696{
2697 struct GNUNET_PeerIdentity *peer;
2698 struct PeerContext *peer_ctx;
2699
2700 peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
2701 (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
2702 // Guess simply casting isn't the nicest way...
2703 // FIXME wait for cadet to change this function
2704
2705 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
2706 {/* We don't want to implicitly create a context that we're about to kill */
2707 peer_ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
2708 if (NULL == peer_ctx) /* It could have been removed by shutdown_task */
2709 return;
2710
2711 if (get_peer_flag (peer_ctx, TO_DESTROY))
2712 {/* We initiatad the destruction of this particular peer */
2713 if (channel == peer_ctx->send_channel)
2714 peer_ctx->send_channel = NULL;
2715 else if (channel == peer_ctx->recv_channel)
2716 peer_ctx->recv_channel = NULL;
2717
2718 to_file (file_name_view_log,
2719 "-%s\t(cleanup channel, ourself)",
2720 GNUNET_i2s_full (peer));
2721 }
2722
2723 else
2724 { /* We did not initiate the destruction of this peer */
2725 if (channel == peer_ctx->send_channel)
2726 { /* Something (but us) killd the channel - clean up peer */
2727 LOG (GNUNET_ERROR_TYPE_DEBUG,
2728 "send channel (%s) was destroyed - cleaning up\n",
2729 GNUNET_i2s (peer));
2730 peer_ctx->send_channel = NULL;
2731 /* Somwewhat {ab,re}use the iterator function */
2732 /* Cast to void is ok, because it's used as void in peer_remove_cb */
2733 (void) peer_remove_cb ((void *) channel, peer, peer_ctx);
2734 }
2735 else if (channel == peer_ctx->recv_channel)
2736 { /* Other peer doesn't want to send us messages anymore */
2737 LOG (GNUNET_ERROR_TYPE_DEBUG,
2738 "Peer %s destroyed recv channel - cleaning up channel\n",
2739 GNUNET_i2s (peer));
2740 peer_ctx->recv_channel = NULL;
2741 }
2742 else
2743 {
2744 LOG (GNUNET_ERROR_TYPE_WARNING,
2745 "unknown channel (%s) was destroyed\n",
2746 GNUNET_i2s (peer));
2747 }
2748 }
2749 }
2750
2751 else
2752 { /* We don't know a context to that peer */
2753 LOG (GNUNET_ERROR_TYPE_DEBUG,
2754 "channel (%s) without associated context was destroyed\n",
2755 GNUNET_i2s (peer));
2756 }
2757}
2758
2759
2760/**
2761 * Actually start the service. 2127 * Actually start the service.
2762 */ 2128 */
2763 static void 2129 static void
@@ -2809,8 +2175,6 @@ run (void *cls,
2809 int size; 2175 int size;
2810 int out_size; 2176 int out_size;
2811 2177
2812 // TODO check what this does -- copied from gnunet-boss
2813 // - seems to work as expected
2814 GNUNET_log_setup ("rps", GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_DEBUG), NULL); 2178 GNUNET_log_setup ("rps", GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_DEBUG), NULL);
2815 cfg = c; 2179 cfg = c;
2816 2180
@@ -2883,8 +2247,6 @@ run (void *cls,
2883 alpha = 0.45; 2247 alpha = 0.45;
2884 beta = 0.45; 2248 beta = 0.45;
2885 2249
2886 peer_map = GNUNET_CONTAINER_multipeermap_create (sampler_size_est_need, GNUNET_NO);
2887
2888 2250
2889 /* Initialise cadet */ 2251 /* Initialise cadet */
2890 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = { 2252 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
@@ -2899,12 +2261,12 @@ run (void *cls,
2899 const uint32_t ports[] = {GNUNET_RPS_CADET_PORT, 0}; // _PORT specified in src/rps/rps.h 2261 const uint32_t ports[] = {GNUNET_RPS_CADET_PORT, 0}; // _PORT specified in src/rps/rps.h
2900 cadet_handle = GNUNET_CADET_connect (cfg, 2262 cadet_handle = GNUNET_CADET_connect (cfg,
2901 cls, 2263 cls,
2902 &handle_inbound_channel, 2264 &Peers_handle_inbound_channel,
2903 &cleanup_channel, 2265 &cleanup_destroyed_channel,
2904 cadet_handlers, 2266 cadet_handlers,
2905 ports); 2267 ports);
2906
2907 peerinfo_handle = GNUNET_PEERINFO_connect (cfg); 2268 peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
2269 Peers_initialise (cadet_handle, &own_identity);
2908 2270
2909 /* Initialise sampler */ 2271 /* Initialise sampler */
2910 struct GNUNET_TIME_Relative half_round_interval; 2272 struct GNUNET_TIME_Relative half_round_interval;
@@ -2944,7 +2306,7 @@ run (void *cls,
2944 * @param argv command line arguments 2306 * @param argv command line arguments
2945 * @return 0 ok, 1 on error 2307 * @return 0 ok, 1 on error
2946 */ 2308 */
2947 int 2309int
2948main (int argc, char *const *argv) 2310main (int argc, char *const *argv)
2949{ 2311{
2950 return (GNUNET_OK == 2312 return (GNUNET_OK ==
diff --git a/src/rps/gnunet-service-rps_peers.c b/src/rps/gnunet-service-rps_peers.c
new file mode 100644
index 000000000..7f656ec94
--- /dev/null
+++ b/src/rps/gnunet-service-rps_peers.c
@@ -0,0 +1,1158 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
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_peers.c
23 * @brief utilities for managing (information about) peers
24 * @author Julius Bünger
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_cadet_service.h"
29#include <inttypes.h>
30#include "rps.h"
31#include "gnunet-service-rps_peers.h"
32
33
34
35#define LOG(kind, ...) GNUNET_log(kind, __VA_ARGS__)
36
37
38/**
39 * Set a peer flag of given peer context.
40 */
41#define set_peer_flag(peer_ctx, mask) (peer_ctx->peer_flags |= mask)
42
43/**
44 * Get peer flag of given peer context.
45 */
46#define check_peer_flag_set(peer_ctx, mask) (peer_ctx->peer_flags & mask ? GNUNET_YES : GNUNET_NO)
47
48/**
49 * Unset flag of given peer context.
50 */
51#define unset_peer_flag(peer_ctx, mask) (peer_ctx->peer_flags &= (~mask))
52
53/**
54 * Set a channel flag of given channel context.
55 */
56#define set_channel_flag(channel_flags, mask) ((*channel_flags) |= mask)
57
58/**
59 * Get channel flag of given channel context.
60 */
61#define check_channel_flag_set(channel_flags, mask) ((*channel_flags) & mask ? GNUNET_YES : GNUNET_NO)
62
63/**
64 * Unset flag of given channel context.
65 */
66#define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= (~mask))
67
68
69
70/**
71 * Pending operation on peer consisting of callback and closure
72 *
73 * When an operation cannot be executed right now this struct is used to store
74 * the callback and closure for later execution.
75 */
76struct PeerPendingOp
77{
78 /**
79 * Callback
80 */
81 PeerOp op;
82
83 /**
84 * Closure
85 */
86 void *op_cls;
87};
88
89/**
90 * List containing all messages that are yet to be send
91 *
92 * This is used to keep track of all messages that have not been sent yet. When
93 * a peer is to be removed the pending messages can be removed properly.
94 */
95struct PendingMessage
96{
97 /**
98 * DLL next, prev
99 */
100 struct PendingMessage *next;
101 struct PendingMessage *prev;
102
103 /**
104 * The envelope to the corresponding message
105 */
106 struct GNUNET_MQ_Envelope *ev;
107
108 /**
109 * The corresponding context
110 */
111 struct PeerContext *peer_ctx;
112
113 /**
114 * The message type
115 */
116 const char *type;
117};
118
119/**
120 * Struct used to keep track of other peer's status
121 *
122 * This is stored in a multipeermap.
123 * It contains information such as cadet channels, a message queue for sending,
124 * status about the channels, the pending operations on this peer and some flags
125 * about the status of the peer itself. (live, valid, ...)
126 */
127struct PeerContext
128{
129 /**
130 * Message queue open to client
131 */
132 struct GNUNET_MQ_Handle *mq;
133
134 /**
135 * Channel open to client.
136 */
137 struct GNUNET_CADET_Channel *send_channel;
138
139 /**
140 * Flags to the sending channel
141 */
142 uint32_t *send_channel_flags;
143
144 /**
145 * Channel open from client.
146 */
147 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
148
149 /**
150 * Flags to the receiving channel
151 */
152 uint32_t *recv_channel_flags;
153
154 /**
155 * Array of pending operations on this peer.
156 */
157 struct PeerPendingOp *pending_ops;
158
159 /**
160 * Handle to the callback given to cadet_ntfy_tmt_rdy()
161 *
162 * To be canceled on shutdown.
163 */
164 struct GNUNET_CADET_TransmitHandle *transmit_handle;
165
166 /**
167 * Number of pending operations.
168 */
169 unsigned int num_pending_ops;
170
171 /**
172 * Identity of the peer
173 */
174 struct GNUNET_PeerIdentity peer_id;
175
176 /**
177 * Flags indicating status of peer
178 */
179 uint32_t peer_flags;
180
181 /**
182 * Last time we received something from that peer.
183 */
184 struct GNUNET_TIME_Absolute last_message_recv;
185
186 /**
187 * Last time we received a keepalive message.
188 */
189 struct GNUNET_TIME_Absolute last_keepalive;
190
191 /**
192 * DLL with all messages that are yet to be sent
193 */
194 struct PendingMessage *pending_messages_head;
195 struct PendingMessage *pending_messages_tail;
196
197 /**
198 * This is pobably followed by 'statistical' data (when we first saw
199 * him, how did we get his ID, how many pushes (in a timeinterval),
200 * ...)
201 */
202};
203
204
205/**
206 * Set of all peers to keep track of them.
207 */
208static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
209
210/**
211 * Own #GNUNET_PeerIdentity.
212 */
213static const struct GNUNET_PeerIdentity *own_identity;
214
215/**
216 * Cadet handle.
217 */
218static struct GNUNET_CADET_Handle *cadet_handle;
219
220
221
222/**
223 * @brief Get the #PeerContext associated with a peer
224 *
225 * @param peer the peer id
226 *
227 * @return the #PeerContext
228 */
229static struct PeerContext *
230get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
231{
232 struct PeerContext *ctx;
233 int ret;
234
235 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
236 GNUNET_assert (GNUNET_YES == ret);
237 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
238 GNUNET_assert (NULL != ctx);
239 return ctx;
240}
241
242/**
243 * @brief Create a new #PeerContext and insert it into the peer map
244 *
245 * @param peer the peer to create the #PeerContext for
246 *
247 * @return the #PeerContext
248 */
249static struct PeerContext *
250create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
251{
252 struct PeerContext *ctx;
253 int ret;
254
255 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
256
257 ctx = GNUNET_new (struct PeerContext);
258 ctx->peer_id = *peer;
259 ctx->send_channel_flags = GNUNET_new (uint32_t);
260 ctx->recv_channel_flags = GNUNET_new (uint32_t);
261 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
262 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
263 GNUNET_assert (GNUNET_OK == ret);
264 return ctx;
265}
266
267/**
268 * @brief Create or get a #PeerContext
269 *
270 * @param peer the peer to get the associated context to
271 *
272 * @return the context
273 */
274static struct PeerContext *
275create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
276{
277 if (GNUNET_NO == Peers_check_peer_known (peer))
278 {
279 return create_peer_ctx (peer);
280 }
281 return get_peer_ctx (peer);
282}
283
284/**
285 * @brief Set the peer flag to living and
286 * call the pending operations on this peer.
287 *
288 * Also sets the #Peers_VALID flag
289 *
290 * @param peer_ctx the #PeerContext of the peer to set live
291 */
292static void
293set_peer_live (struct PeerContext *peer_ctx)
294{
295 struct GNUNET_PeerIdentity *peer;
296 unsigned int i;
297
298 /* Cancle cadet transmit_handle if still scheduled */
299 if (NULL != peer_ctx->transmit_handle)
300 {
301 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
302 peer_ctx->transmit_handle = NULL;
303 }
304
305 peer = &peer_ctx->peer_id;
306 set_peer_flag (peer_ctx, Peers_VALID);
307 // TODO LIVE/ONLINE
308 LOG (GNUNET_ERROR_TYPE_DEBUG,
309 "Peer %s is live and valid\n",
310 GNUNET_i2s (peer));
311
312 /* Call pending operations */
313 for (i = 0; i < peer_ctx->num_pending_ops; i++)
314 {
315 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
316 }
317 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
318}
319
320/**
321 * @brief Get the channel of a peer. If not existing, create.
322 *
323 * @param peer the peer id
324 * @return the #GNUNET_CADET_Channel used to send data to @a peer
325 */
326struct GNUNET_CADET_Channel *
327get_channel (const struct GNUNET_PeerIdentity *peer)
328{
329 struct PeerContext *peer_ctx;
330
331 peer_ctx = get_peer_ctx (peer);
332 if (NULL == peer_ctx->send_channel)
333 {
334 LOG (GNUNET_ERROR_TYPE_DEBUG,
335 "Trying to establish channel to peer %s\n",
336 GNUNET_i2s (peer));
337 peer_ctx->send_channel =
338 GNUNET_CADET_channel_create (cadet_handle,
339 peer_ctx->send_channel_flags, /* context */
340 peer,
341 GNUNET_RPS_CADET_PORT,
342 GNUNET_CADET_OPTION_RELIABLE);
343 }
344 return peer_ctx->send_channel;
345}
346
347/**
348 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
349 *
350 * If we already have a message queue open to this client,
351 * simply return it, otherways create one.
352 *
353 * @param peer the peer to get the mq to
354 * @return the #GNUNET_MQ_Handle
355 */
356static struct GNUNET_MQ_Handle *
357get_mq (const struct GNUNET_PeerIdentity *peer)
358{
359 struct PeerContext *peer_ctx;
360
361 peer_ctx = get_peer_ctx (peer);
362 GNUNET_assert (NULL == peer_ctx->transmit_handle);
363
364 if (NULL == peer_ctx->mq)
365 {
366 (void) get_channel (peer);
367 peer_ctx->mq = GNUNET_CADET_mq_create (peer_ctx->send_channel);
368 }
369 return peer_ctx->mq;
370}
371
372/**
373 * @brief Callback that is called when a channel was effectively established.
374 *
375 * This is an implementation of #GNUNET_CONNECTION_TransmitReadyNotify and
376 * given to #GNUNET_CADET_notify_transmit_ready_cancel and called when the
377 * channel was successfully established.
378 *
379 * This function type was originally ment to be called to provide the data to
380 * be sent. This is called when the connection is ready to queue more data.
381 * However we use it to get notified about the successful establishement of a
382 * cadet channel.
383 *
384 * @a buf will be NULL and @a size zero if the
385 * connection was closed for writing in the meantime.
386 *
387 * @param cls closure
388 * @param size number of bytes available in @a buf
389 * @param buf where the callee should write the message
390 * @return number of bytes written to @a buf
391 */
392//TODO
393static size_t
394cadet_notify_transmit_ready_cb (void *cls, size_t size, void *buf)
395{
396 struct PeerContext *peer_ctx = (struct PeerContext *) cls;
397 // TODO make sure the context is not deleted or the establishing of the
398 // channel is cancelled
399
400 peer_ctx->transmit_handle = NULL;
401 LOG (GNUNET_ERROR_TYPE_DEBUG,
402 "Set ->transmit_handle = NULL for peer %s\n",
403 GNUNET_i2s (&peer_ctx->peer_id));
404
405 if ( (NULL != buf) &&
406 (0 != size) )
407 {
408 set_peer_live (peer_ctx);
409 }
410 else
411 {
412 LOG (GNUNET_ERROR_TYPE_WARNING,
413 "Problems establishing a connection to peer %s in order to check liveliness\n",
414 GNUNET_i2s (&peer_ctx->peer_id));
415 // TODO reschedule? cleanup?
416 }
417 return 0;
418}
419
420/**
421 * Issue a check whether peer is live
422 *
423 * @param peer_ctx the context of the peer
424 */
425static void
426check_peer_live (struct PeerContext *peer_ctx)
427{
428 LOG (GNUNET_ERROR_TYPE_DEBUG,
429 "Get informed about peer %s getting live\n",
430 GNUNET_i2s (&peer_ctx->peer_id));
431
432 if (NULL == peer_ctx->transmit_handle &&
433 NULL == peer_ctx->send_channel)
434 {
435 (void) get_channel (&peer_ctx->peer_id);
436 peer_ctx->transmit_handle =
437 GNUNET_CADET_notify_transmit_ready (peer_ctx->send_channel,
438 GNUNET_NO,
439 GNUNET_TIME_UNIT_FOREVER_REL,
440 sizeof (struct GNUNET_MessageHeader),
441 cadet_notify_transmit_ready_cb,
442 peer_ctx);
443 }
444 else if (NULL != peer_ctx->transmit_handle)
445 LOG (GNUNET_ERROR_TYPE_DEBUG,
446 "Already waiting for notification\n");
447 else if (NULL != peer_ctx->send_channel)
448 LOG (GNUNET_ERROR_TYPE_DEBUG,
449 "Already have established channel to peer\n");
450}
451
452/**
453 * @brief Add an envelope to a message passed to mq to list of pending messages
454 *
455 * @param peer peer the message was sent to
456 * @param ev envelope to the message
457 * @param type type of the message to be sent
458 * @return pointer to pending message
459 */
460static struct PendingMessage *
461insert_pending_message (const struct GNUNET_PeerIdentity *peer,
462 struct GNUNET_MQ_Envelope *ev,
463 const char *type)
464{
465 struct PendingMessage *pending_msg;
466 struct PeerContext *peer_ctx;
467
468 peer_ctx = get_peer_ctx (peer);
469 pending_msg = GNUNET_new (struct PendingMessage);
470 pending_msg->ev = ev;
471 pending_msg->peer_ctx = peer_ctx;
472 pending_msg->type = type;
473 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
474 peer_ctx->pending_messages_tail,
475 pending_msg);
476 return pending_msg;
477}
478
479/**
480 * @brief Remove a pending message from the respective DLL
481 *
482 * @param pending_msg the pending message to remove
483 */
484static void
485remove_pending_message (struct PendingMessage *pending_msg)
486{
487 struct PeerContext *peer_ctx;
488
489 peer_ctx = pending_msg->peer_ctx;
490 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
491 peer_ctx->pending_messages_tail,
492 pending_msg);
493 /* FIXME We are not able to cancel messages as #GNUNET_CADET_mq_create () does
494 * not set a #GNUNET_MQ_CancelImpl */
495 /* GNUNET_MQ_send_cancel (peer_ctx->pending_messages_head->ev); */
496 GNUNET_free (pending_msg);
497}
498
499/**
500 * @brief Check whether function of type #PeerOp was already scheduled
501 *
502 * The array with pending operations will probably never grow really big, so
503 * iterating over it should be ok.
504 *
505 * @param peer the peer to check
506 * @param peer_op the operation (#PeerOp) on the peer
507 *
508 * @return #GNUNET_YES if this operation is scheduled on that peer
509 * #GNUNET_NO otherwise
510 */
511static int
512check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
513 const PeerOp peer_op)
514{
515 const struct PeerContext *peer_ctx;
516 unsigned int i;
517
518 peer_ctx = get_peer_ctx (peer);
519 for (i = 0; i < peer_ctx->num_pending_ops; i++)
520 if (peer_op == peer_ctx->pending_ops[i].op)
521 return GNUNET_YES;
522 return GNUNET_NO;
523}
524
525/**
526 * Iterator over hash map entries. Deletes all contexts of peers.
527 *
528 * @param cls closure
529 * @param key current public key
530 * @param value value in the hash map
531 * @return #GNUNET_YES if we should continue to iterate,
532 * #GNUNET_NO if not.
533 */
534static int
535peermap_clear_iterator (void *cls,
536 const struct GNUNET_PeerIdentity *key,
537 void *value)
538{
539 Peers_remove_peer (key);
540 return GNUNET_YES;
541}
542
543/**
544 * @brief This is called once a message is sent.
545 *
546 * Removes the pending message
547 *
548 * @param cls type of the message that was sent
549 */
550static void
551mq_notify_sent_cb (void *cls)
552{
553 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
554 LOG (GNUNET_ERROR_TYPE_DEBUG,
555 "%s was sent.\n",
556 pending_msg->type);
557 remove_pending_message (pending_msg);
558}
559
560
561/**
562 * @brief Initialise storage of peers
563 *
564 * @param cadet_h cadet handle
565 * @param own_id own peer identity
566 */
567void
568Peers_initialise (struct GNUNET_CADET_Handle *cadet_h,
569 const struct GNUNET_PeerIdentity *own_id)
570{
571 cadet_handle = cadet_h;
572 own_identity = own_id;
573 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
574}
575
576/**
577 * @brief Delete storage of peers that was created with #Peers_initialise ()
578 */
579void
580Peers_terminate ()
581{
582 if (GNUNET_SYSERR ==
583 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
584 peermap_clear_iterator,
585 NULL))
586 {
587 LOG (GNUNET_ERROR_TYPE_WARNING,
588 "Iteration destroying peers was aborted.\n");
589 }
590 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
591}
592
593/**
594 * @brief Add peer to known peers.
595 *
596 * This function is called on new peer_ids from 'external' sources
597 * (client seed, cadet get_peers(), ...)
598 *
599 * @param peer the new peer
600 *
601 * @return #GNUNET_YES if peer was inserted
602 * #GNUNET_NO if peer was already known
603 */
604int
605Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
606{
607 struct PeerContext *peer_ctx;
608
609 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
610 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) )
611 {
612 return GNUNET_NO; /* We already know this peer - nothing to do */
613 }
614 peer_ctx = create_peer_ctx (peer);
615 // TODO LIVE
616 if (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_VALID))
617 {
618 check_peer_live (peer_ctx);
619 }
620 return GNUNET_YES;
621}
622
623/**
624 * @brief Remove unecessary data
625 *
626 * If the other peer is not intending to send messages, we have messages pending
627 * to be sent to this peer and we are not waiting for a reply, remove the
628 * information about it (its #PeerContext).
629 *
630 * @param peer the peer to clean
631 * @return #GNUNET_YES if peer was removed
632 * #GNUNET_NO otherwise
633 */
634int
635Peers_clean_peer (const struct GNUNET_PeerIdentity *peer)
636{
637 struct PeerContext *peer_ctx;
638
639 // TODO actually remove unnecessary data
640
641 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
642 {
643 return GNUNET_NO;
644 }
645
646 peer_ctx = get_peer_ctx (peer);
647 if ( (NULL != peer_ctx->recv_channel) ||
648 (NULL != peer_ctx->pending_messages_head) ||
649 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
650 {
651 return GNUNET_NO;
652 }
653 Peers_remove_peer (peer);
654 return GNUNET_YES;
655}
656
657/**
658 * @brief Remove peer
659 *
660 * @param peer the peer to clean
661 * @return #GNUNET_YES if peer was removed
662 * #GNUNET_NO otherwise
663 */
664int
665Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
666{
667 struct PeerContext *peer_ctx;
668
669 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
670 {
671 return GNUNET_NO;
672 }
673
674 peer_ctx = get_peer_ctx (peer);
675 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
676 LOG (GNUNET_ERROR_TYPE_DEBUG,
677 "Going to remove peer %s\n",
678 GNUNET_i2s (&peer_ctx->peer_id));
679
680 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
681 // TODO delete struct GNUNET_TRANSPORT_TransmitHandle *transmit_handle
682 /* Cancle messages that have not been sent yet */
683 while (NULL != peer_ctx->pending_messages_head)
684 {
685 LOG (GNUNET_ERROR_TYPE_DEBUG,
686 "Removing unsent %s\n",
687 peer_ctx->pending_messages_head->type);
688 remove_pending_message (peer_ctx->pending_messages_head);
689 }
690 /* If we are still waiting for notification whether this peer is live
691 * cancel the according task */
692 if (NULL != peer_ctx->transmit_handle)
693 {
694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
695 "Trying to cancle transmit_handle for peer %s\n",
696 GNUNET_i2s (&peer_ctx->peer_id));
697 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
698 peer_ctx->transmit_handle = NULL;
699 }
700 if (NULL != peer_ctx->send_channel)
701 {
702 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
703 peer_ctx->send_channel = NULL;
704 }
705 if (NULL != peer_ctx->recv_channel)
706 {
707 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
708 peer_ctx->recv_channel = NULL;
709 }
710 if (NULL != peer_ctx->mq)
711 {
712 GNUNET_MQ_destroy (peer_ctx->mq);
713 peer_ctx->mq = NULL;
714 }
715
716 GNUNET_free (peer_ctx->send_channel_flags);
717 GNUNET_free (peer_ctx->recv_channel_flags);
718
719 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
720 {
721 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
722 }
723 GNUNET_free (peer_ctx);
724 return GNUNET_YES;
725}
726
727/**
728 * @brief set flags on a given peer.
729 *
730 * @param peer the peer to set flags on
731 * @param flags the flags
732 */
733void
734Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
735{
736 struct PeerContext *peer_ctx;
737
738 peer_ctx = get_peer_ctx (peer);
739 set_peer_flag (peer_ctx, flags);
740}
741
742/**
743 * @brief unset flags on a given peer.
744 *
745 * @param peer the peer to unset flags on
746 * @param flags the flags
747 */
748void
749Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
750{
751 struct PeerContext *peer_ctx;
752
753 peer_ctx = get_peer_ctx (peer);
754 unset_peer_flag (peer_ctx, flags);
755}
756
757/**
758 * @brief Check whether flags on a peer are set.
759 *
760 * @param peer the peer to check the flag of
761 * @param flags the flags to check
762 *
763 * @return #GNUNET_YES if all given flags are set
764 * #GNUNET_NO otherwise
765 */
766int
767Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
768{
769 struct PeerContext *peer_ctx;
770
771 peer_ctx = get_peer_ctx (peer);
772 return check_peer_flag_set (peer_ctx, flags);
773}
774
775
776/**
777 * @brief set flags on a given channel.
778 *
779 * @param channel the channel to set flags on
780 * @param flags the flags
781 */
782void
783Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
784{
785 set_channel_flag (channel_flags, flags);
786}
787
788/**
789 * @brief unset flags on a given channel.
790 *
791 * @param channel the channel to unset flags on
792 * @param flags the flags
793 */
794void
795Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
796{
797 unset_channel_flag (channel_flags, flags);
798}
799
800/**
801 * @brief Check whether flags on a channel are set.
802 *
803 * @param channel the channel to check the flag of
804 * @param flags the flags to check
805 *
806 * @return #GNUNET_YES if all given flags are set
807 * #GNUNET_NO otherwise
808 */
809int
810Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
811{
812 return check_channel_flag_set (channel_flags, flags);
813}
814
815/**
816 * @brief Check whether we have information about the given peer.
817 *
818 * @param peer peer in question
819 *
820 * @return #GNUNET_YES if peer is known
821 * #GNUNET_NO if peer is not knwon
822 */
823int
824Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
825{
826 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
827}
828
829/**
830 * @brief Indicate that we want to send to the other peer
831 *
832 * This establishes a sending channel
833 *
834 * @param peer the peer to establish channel to
835 */
836void
837Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
838{
839 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
840 (void) get_channel (peer);
841}
842
843/**
844 * @brief Check whether other peer has the intention to send/opened channel
845 * towars us
846 *
847 * @param peer the peer in question
848 *
849 * @return #GNUNET_YES if peer has the intention to send
850 * #GNUNET_NO otherwise
851 */
852int
853Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
854{
855 const struct PeerContext *peer_ctx;
856
857 peer_ctx = get_peer_ctx (peer);
858 if (NULL != peer_ctx->recv_channel)
859 {
860 return GNUNET_YES;
861 }
862 return GNUNET_NO;
863}
864
865/**
866 * Handle the channel a peer opens to us.
867 *
868 * @param cls The closure
869 * @param channel The channel the peer wants to establish
870 * @param initiator The peer's peer ID
871 * @param port The port the channel is being established over
872 * @param options Further options
873 *
874 * @return initial channel context for the channel
875 * (can be NULL -- that's not an error)
876 */
877void *
878Peers_handle_inbound_channel (void *cls,
879 struct GNUNET_CADET_Channel *channel,
880 const struct GNUNET_PeerIdentity *initiator,
881 uint32_t port,
882 enum GNUNET_CADET_ChannelOption options)
883{
884 struct PeerContext *peer_ctx;
885
886 LOG (GNUNET_ERROR_TYPE_DEBUG,
887 "New channel was established to us (Peer %s).\n",
888 GNUNET_i2s (initiator));
889 GNUNET_assert (NULL != channel); /* according to cadet API */
890 /* Make sure we 'know' about this peer */
891 peer_ctx = create_or_get_peer_ctx (initiator);
892 set_peer_live (peer_ctx);
893 /* We only accept one incoming channel per peer */
894 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
895 {
896 set_channel_flag (peer_ctx->recv_channel_flags,
897 Peers_CHANNEL_ESTABLISHED_TWICE);
898 GNUNET_CADET_channel_destroy (channel);
899 /* return the channel context */
900 return peer_ctx->recv_channel_flags;
901 }
902 peer_ctx->recv_channel = channel;
903 return peer_ctx->recv_channel_flags;
904}
905
906/**
907 * @brief Check whether a sending channel towards the given peer exists
908 *
909 * @param peer the peer to check for
910 *
911 * @return #GNUNET_YES if a sending channel towards that peer exists
912 * #GNUNET_NO otherwise
913 */
914int
915Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
916{
917 struct PeerContext *peer_ctx;
918
919 if (GNUNET_NO == Peers_check_peer_known (peer))
920 { /* If no such peer exists, there is no channel */
921 return GNUNET_NO;
922 }
923 peer_ctx = get_peer_ctx (peer);
924 if (NULL == peer_ctx->send_channel)
925 {
926 return GNUNET_NO;
927 }
928 return GNUNET_YES;
929}
930
931/**
932 * @brief check whether the given channel is the sending channel of the given
933 * peer
934 *
935 * @param peer the peer in question
936 * @param channel the channel to check for
937 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
938 * #Peers_CHANNEL_ROLE_RECEIVING
939 *
940 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
941 * #GNUNET_NO otherwise
942 */
943int
944Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
945 const struct GNUNET_CADET_Channel *channel,
946 enum Peers_ChannelRole role)
947{
948 const struct PeerContext *peer_ctx;
949
950 if (GNUNET_NO == Peers_check_peer_known (peer))
951 {
952 return GNUNET_NO;
953 }
954 peer_ctx = get_peer_ctx (peer);
955 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
956 (channel == peer_ctx->send_channel) )
957 {
958 return GNUNET_YES;
959 }
960 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
961 (channel == peer_ctx->recv_channel) )
962 {
963 return GNUNET_YES;
964 }
965 return GNUNET_NO;
966}
967
968/**
969 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
970 * intention to another peer
971 *
972 * If there is also no channel to receive messages from that peer, remove it
973 * from the peermap.
974 * TODO really?
975 *
976 * @peer the peer identity of the peer whose sending channel to destroy
977 * @return #GNUNET_YES if channel was destroyed
978 * #GNUNET_NO otherwise
979 */
980int
981Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
982{
983 struct PeerContext *peer_ctx;
984
985 if (GNUNET_NO == Peers_check_peer_known (peer))
986 {
987 return GNUNET_NO;
988 }
989 peer_ctx = get_peer_ctx (peer);
990 if (NULL != peer_ctx->send_channel)
991 {
992 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
993 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
994 peer_ctx->send_channel = NULL;
995 return GNUNET_YES;
996 }
997 return GNUNET_NO;
998}
999
1000/**
1001 * This is called when a channel is destroyed.
1002 *
1003 * Removes peer completely from our knowledge if the send_channel was destroyed
1004 * Otherwise simply delete the recv_channel
1005 *
1006 * @param cls The closure
1007 * @param channel The channel being closed
1008 * @param channel_ctx The context associated with this channel
1009 */
1010void
1011Peers_cleanup_destroyed_channel (void *cls,
1012 const struct GNUNET_CADET_Channel *channel,
1013 void *channel_ctx)
1014{
1015 struct GNUNET_PeerIdentity *peer;
1016 struct PeerContext *peer_ctx;
1017
1018 peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
1019 (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
1020 // FIXME wait for cadet to change this function
1021
1022 if (GNUNET_NO == Peers_check_peer_known (peer))
1023 {/* We don't want to implicitly create a context that we're about to kill */
1024 LOG (GNUNET_ERROR_TYPE_DEBUG,
1025 "channel (%s) without associated context was destroyed\n",
1026 GNUNET_i2s (peer));
1027 return;
1028 }
1029
1030 peer_ctx = get_peer_ctx (peer);
1031 GNUNET_assert (NULL != peer_ctx); /* It could have been removed by shutdown_task */
1032
1033 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1034 * flag will be set. In this case simply make sure that the channels are
1035 * cleaned. */
1036 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1037 {/* We initiatad the destruction of this particular peer */
1038 if (channel == peer_ctx->send_channel)
1039 peer_ctx->send_channel = NULL;
1040 else if (channel == peer_ctx->recv_channel)
1041 peer_ctx->recv_channel = NULL;
1042
1043 return;
1044 }
1045
1046 else
1047 { /* We did not initiate the destruction of this peer */
1048 if (channel == peer_ctx->send_channel)
1049 { /* Something (but us) killd the channel - clean up peer */
1050 LOG (GNUNET_ERROR_TYPE_DEBUG,
1051 "send channel (%s) was destroyed - cleaning up\n",
1052 GNUNET_i2s (peer));
1053 peer_ctx->send_channel = NULL;
1054 }
1055 else if (channel == peer_ctx->recv_channel)
1056 { /* Other peer doesn't want to send us messages anymore */
1057 LOG (GNUNET_ERROR_TYPE_DEBUG,
1058 "Peer %s destroyed recv channel - cleaning up channel\n",
1059 GNUNET_i2s (peer));
1060 peer_ctx->recv_channel = NULL;
1061 }
1062 else
1063 {
1064 LOG (GNUNET_ERROR_TYPE_WARNING,
1065 "unknown channel (%s) was destroyed\n",
1066 GNUNET_i2s (peer));
1067 }
1068 }
1069}
1070
1071/**
1072 * @brief Issue a check whether peer is live
1073 *
1074 * This tries to establish a channel to the given peer. Once the channel is
1075 * established successfully, we know the peer is live.
1076 *
1077 * @param peer the peer to check liveliness
1078 */
1079void
1080Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1081{
1082 struct PeerContext *peer_ctx;
1083
1084 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1085 {
1086 return; /* We know that we are online */
1087 }
1088
1089 peer_ctx = create_or_get_peer_ctx (peer);
1090 // TODO if LIVE/ONLINE
1091 check_peer_live (peer_ctx);
1092}
1093
1094/**
1095 * @brief Send a message to another peer.
1096 *
1097 * Keeps track about pending messages so they can be properly removed when the
1098 * peer is destroyed.
1099 *
1100 * @param peer receeiver of the message
1101 * @param ev envelope of the message
1102 * @param type type of the message
1103 */
1104void
1105Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1106 struct GNUNET_MQ_Envelope *ev,
1107 const char *type)
1108{
1109 struct PendingMessage *pending_msg;
1110 struct GNUNET_MQ_Handle *mq;
1111
1112 pending_msg = insert_pending_message (peer, ev, "PULL REPLY");
1113 mq = get_mq (peer);
1114 GNUNET_MQ_notify_sent (ev,
1115 mq_notify_sent_cb,
1116 pending_msg);
1117 GNUNET_MQ_send (mq, ev);
1118}
1119
1120/**
1121 * @brief Schedule a operation on given peer
1122 *
1123 * Avoids scheduling an operation twice.
1124 *
1125 * @param peer the peer we want to schedule the operation for once it gets live
1126 *
1127 * @return #GNUNET_YES if the operation was scheduled
1128 * #GNUNET_NO otherwise
1129 */
1130int
1131Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1132 const PeerOp peer_op)
1133{
1134 struct PeerPendingOp pending_op;
1135 struct PeerContext *peer_ctx;
1136
1137 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1138 {
1139 return GNUNET_NO;
1140 }
1141 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1142
1143 //TODO if LIVE/ONLINE execute immediately
1144
1145 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1146 {
1147 peer_ctx = get_peer_ctx (peer);
1148 pending_op.op = peer_op;
1149 pending_op.op_cls = NULL;
1150 GNUNET_array_append (peer_ctx->pending_ops,
1151 peer_ctx->num_pending_ops,
1152 pending_op);
1153 return GNUNET_YES;
1154 }
1155 return GNUNET_NO;
1156}
1157
1158/* end of gnunet-service-rps_peers.c */
diff --git a/src/rps/gnunet-service-rps_peers.h b/src/rps/gnunet-service-rps_peers.h
new file mode 100644
index 000000000..718890762
--- /dev/null
+++ b/src/rps/gnunet-service-rps_peers.h
@@ -0,0 +1,371 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
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_peers.h
23 * @brief utilities for managing (information about) peers
24 * @author Julius Bünger
25 */
26#include "gnunet_util_lib.h"
27#include <inttypes.h>
28#include "gnunet_cadet_service.h"
29
30
31/**
32 * Different flags indicating the status of another peer.
33 */
34enum Peers_PeerFlags
35{
36 /**
37 * If we are waiting for a reply from that peer (sent a pull request).
38 */
39 Peers_PULL_REPLY_PENDING = 0x01,
40
41 /* IN_OTHER_GOSSIP_LIST = 0x02, unneeded? */
42 /* IN_OWN_SAMPLER_LIST = 0x04, unneeded? */
43 /* IN_OWN_GOSSIP_LIST = 0x08, unneeded? */
44
45 /**
46 * We set this bit when we can be sure the other peer is/was live.
47 */
48 Peers_VALID = 0x10,
49
50 /**
51 * We set this bit when we know the peer is online.
52 */
53 Peers_ONLINE = 0x20,
54
55 /**
56 * We set this bit when we are going to destroy the channel to this peer.
57 * When cleanup_channel is called, we know that we wanted to destroy it.
58 * Otherwise the channel to the other peer was destroyed.
59 */
60 Peers_TO_DESTROY = 0x40,
61};
62
63/**
64 * Keep track of the status of a channel.
65 *
66 * This is needed in order to know what to do with a channel when it's
67 * destroyed.
68 */
69enum Peers_ChannelFlags
70{
71 /**
72 * We destroyed the channel because the other peer established a second one.
73 */
74 Peers_CHANNEL_ESTABLISHED_TWICE = 0x1,
75
76 /**
77 * The channel was removed because it was not needed any more. This should be
78 * the sending channel.
79 */
80 Peers_CHANNEL_CLEAN = 0x2,
81};
82
83/**
84 * @brief The role of a channel. Sending or receiving.
85 */
86enum Peers_ChannelRole
87{
88 /**
89 * Channel is used for sending
90 */
91 Peers_CHANNEL_ROLE_SENDING = 0x01,
92
93 /**
94 * Channel is used for receiving
95 */
96 Peers_CHANNEL_ROLE_RECEIVING = 0x02,
97};
98
99/**
100 * @brief Functions of this type can be used to be stored at a peer for later execution.
101 *
102 * @param cls closure
103 * @param peer peer to execute function on
104 */
105typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer);
106
107/**
108 * @brief Initialise storage of peers
109 *
110 * @param cadet_h cadet handle
111 * @param own_id own peer identity
112 */
113void
114Peers_initialise (struct GNUNET_CADET_Handle *cadet_h,
115 const struct GNUNET_PeerIdentity *own_id);
116
117/**
118 * @brief Delete storage of peers that was created with #Peers_initialise ()
119 */
120void
121Peers_terminate ();
122
123/**
124 * @brief Add peer to known peers.
125 *
126 * This function is called on new peer_ids from 'external' sources
127 * (client seed, cadet get_peers(), ...)
128 *
129 * @param peer the new peer
130 *
131 * @return #GNUNET_YES if peer was inserted
132 * #GNUNET_NO if peer was already known
133 */
134int
135Peers_insert_peer (const struct GNUNET_PeerIdentity *peer);
136
137/**
138 * @brief Remove unecessary data
139 *
140 * If the other peer is not intending to send messages, we have messages pending
141 * to be sent to this peer and we are not waiting for a reply, remove the
142 * information about it (its #PeerContext).
143 *
144 * @param peer the peer to clean
145 * @return #GNUNET_YES if peer was removed
146 * #GNUNET_NO otherwise
147 */
148int
149Peers_clean_peer (const struct GNUNET_PeerIdentity *peer);
150
151/**
152 * @brief Remove peer
153 *
154 * @param peer the peer to clean
155 * @return #GNUNET_YES if peer was removed
156 * #GNUNET_NO otherwise
157 */
158int
159Peers_remove_peer (const struct GNUNET_PeerIdentity *peer);
160
161/**
162 * @brief set flags on a given peer.
163 *
164 * @param peer the peer to set flags on
165 * @param flags the flags
166 */
167void
168Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
169
170/**
171 * @brief unset flags on a given peer.
172 *
173 * @param peer the peer to unset flags on
174 * @param flags the flags
175 */
176void
177Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
178
179/**
180 * @brief Check whether flags on a peer are set.
181 *
182 * @param peer the peer to check the flag of
183 * @param flags the flags to check
184 *
185 * @return #GNUNET_YES if all given flags are set
186 * ##GNUNET_NO otherwise
187 */
188int
189Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
190
191
192/**
193 * @brief set flags on a given channel.
194 *
195 * @param channel the channel to set flags on
196 * @param flags the flags
197 */
198void
199Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
200
201/**
202 * @brief unset flags on a given channel.
203 *
204 * @param channel the channel to unset flags on
205 * @param flags the flags
206 */
207void
208Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
209
210/**
211 * @brief Check whether flags on a channel are set.
212 *
213 * @param channel the channel to check the flag of
214 * @param flags the flags to check
215 *
216 * @return #GNUNET_YES if all given flags are set
217 * #GNUNET_NO otherwise
218 */
219int
220Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
221
222/**
223 * @brief Check whether we have information about the given peer.
224 *
225 * @param peer peer in question
226 *
227 * @return #GNUNET_YES if peer is known
228 * #GNUNET_NO if peer is not knwon
229 */
230int
231Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer);
232
233/**
234 * @brief Indicate that we want to send to the other peer
235 *
236 * This establishes a sending channel
237 *
238 * @param peer the peer to establish channel to
239 */
240void
241Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer);
242
243/**
244 * @brief Check whether other peer has the intention to send/opened channel
245 * towars us
246 *
247 * @param peer the peer in question
248 *
249 * @return #GNUNET_YES if peer has the intention to send
250 * #GNUNET_NO otherwise
251 */
252int
253Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer);
254
255/**
256 * Handle the channel a peer opens to us.
257 *
258 * @param cls The closure
259 * @param channel The channel the peer wants to establish
260 * @param initiator The peer's peer ID
261 * @param port The port the channel is being established over
262 * @param options Further options
263 *
264 * @return initial channel context for the channel
265 * (can be NULL -- that's not an error)
266 */
267void *
268Peers_handle_inbound_channel (void *cls,
269 struct GNUNET_CADET_Channel *channel,
270 const struct GNUNET_PeerIdentity *initiator,
271 uint32_t port,
272 enum GNUNET_CADET_ChannelOption options);
273
274/**
275 * @brief Check whether a sending channel towards the given peer exists
276 *
277 * @param peer the peer to check for
278 *
279 * @return #GNUNET_YES if a sending channel towards that peer exists
280 * #GNUNET_NO otherwise
281 */
282int
283Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer);
284
285/**
286 * @brief check whether the given channel is the sending channel of the given
287 * peer
288 *
289 * @param peer the peer in question
290 * @param channel the channel to check for
291 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
292 * #Peers_CHANNEL_ROLE_RECEIVING
293 *
294 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
295 * #GNUNET_NO otherwise
296 */
297int
298Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
299 const struct GNUNET_CADET_Channel *channel,
300 enum Peers_ChannelRole role);
301
302/**
303 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
304 * intention to another peer
305 *
306 * If there is also no channel to receive messages from that peer, remove it
307 * from the peermap.
308 *
309 * @peer the peer identity of the peer whose sending channel to destroy
310 * @return #GNUNET_YES if channel was destroyed
311 * #GNUNET_NO otherwise
312 */
313int
314Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer);
315
316/**
317 * This is called when a channel is destroyed.
318 *
319 * Removes peer completely from our knowledge if the send_channel was destroyed
320 * Otherwise simply delete the recv_channel
321 *
322 * @param cls The closure
323 * @param channel The channel being closed
324 * @param channel_ctx The context associated with this channel
325 */
326void
327Peers_cleanup_destroyed_channel (void *cls,
328 const struct GNUNET_CADET_Channel *channel,
329 void *channel_ctx);
330
331/**
332 * @brief Issue a check whether peer is live
333 *
334 * This tries to establish a channel to the given peer. Once the channel is
335 * established successfully, we know the peer is live.
336 *
337 * @param peer the peer to check liveliness
338 */
339void
340Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer);
341
342/**
343 * @brief Send a message to another peer.
344 *
345 * Keeps track about pending messages so they can be properly removed when the
346 * peer is destroyed.
347 *
348 * @param peer receeiver of the message
349 * @param ev envelope of the message
350 * @param type type of the message
351 */
352void
353Peers_send_message (const struct GNUNET_PeerIdentity *peer,
354 struct GNUNET_MQ_Envelope *ev,
355 const char *type);
356
357/**
358 * @brief Schedule a operation on given peer
359 *
360 * Avoids scheduling an operation twice.
361 *
362 * @param peer the peer we want to schedule the operation for once it gets live
363 *
364 * @return #GNUNET_YES if the operation was scheduled
365 * #GNUNET_NO otherwise
366 */
367int
368Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
369 const PeerOp peer_op);
370
371/* end of gnunet-service-rps_peers.h */