diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rps/Makefile.am | 1 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps.c | 1164 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_peers.c | 1158 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_peers.h | 371 |
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 | |||
49 | gnunet_service_rps_SOURCES = \ | 49 | gnunet_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 | |||
129 | struct ClientContext *cli_ctx_head; | 127 | struct ClientContext *cli_ctx_head; |
130 | struct ClientContext *cli_ctx_tail; | 128 | struct ClientContext *cli_ctx_tail; |
131 | 129 | ||
132 | /** | ||
133 | * Used to keep track in what lists single peerIDs are. | ||
134 | */ | ||
135 | enum 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 | */ | ||
163 | typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer); | ||
164 | |||
165 | /** | ||
166 | * Outstanding operation on peer consisting of callback and closure | ||
167 | */ | ||
168 | struct 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 | */ | ||
185 | struct 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 | */ | ||
215 | struct 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 | */ |
292 | static struct RPS_Sampler *client_sampler; | 150 | static struct RPS_Sampler *client_sampler; |
293 | 151 | ||
294 | /** | ||
295 | * Set of all peers to keep track of them. | ||
296 | */ | ||
297 | static 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 | */ | ||
537 | void | ||
538 | peer_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 * | ||
601 | get_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 | */ | ||
616 | struct PeerContext * | ||
617 | create_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 | */ | ||
634 | static size_t | ||
635 | peer_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 | */ | ||
669 | static size_t | ||
670 | cadet_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 * | ||
709 | get_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 * | ||
739 | get_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 | */ | ||
764 | void | ||
765 | check_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 | ||
826 | insert_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 | ||
835 | insert_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 | ||
852 | insert_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 | ||
861 | insert_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 | ||
876 | insert_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 | */ | ||
895 | static int | ||
896 | insert_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 | */ | ||
1053 | static struct PendingMessage * | ||
1054 | insert_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 | |||
1072 | static void | ||
1073 | remove_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 | */ | ||
1090 | static void | ||
1091 | mq_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 | */ |
1162 | static void | 649 | void |
1163 | new_peer_id (const struct GNUNET_PeerIdentity *peer_id) | 650 | insert_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 | ||
661 | insert_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 | ||
670 | insert_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 | */ | ||
696 | static int | ||
697 | check_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 | */ | ||
725 | static void | ||
726 | remove_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 | */ | ||
744 | static void | ||
745 | clean_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 | */ | ||
780 | static void | ||
781 | cleanup_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 | */ |
1288 | void client_respond (void *cls, | 935 | void |
1289 | struct GNUNET_PeerIdentity *peer_ids, uint32_t num_peers) | 936 | client_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 | */ |
1805 | static void | 1446 | static void |
1806 | send_pull_request (const struct GNUNET_PeerIdentity *peer_id) | 1447 | send_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 | |||
1837 | send_push (const struct GNUNET_PeerIdentity *peer_id) | 1470 | send_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 | ||
2407 | peer_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 | */ | ||
2512 | void | ||
2513 | peer_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 * | ||
2657 | handle_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 | ||
2693 | cleanup_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 | 2309 | int |
2948 | main (int argc, char *const *argv) | 2310 | main (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 | */ | ||
76 | struct 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 | */ | ||
95 | struct 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 | */ | ||
127 | struct 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 | */ | ||
208 | static struct GNUNET_CONTAINER_MultiPeerMap *peer_map; | ||
209 | |||
210 | /** | ||
211 | * Own #GNUNET_PeerIdentity. | ||
212 | */ | ||
213 | static const struct GNUNET_PeerIdentity *own_identity; | ||
214 | |||
215 | /** | ||
216 | * Cadet handle. | ||
217 | */ | ||
218 | static 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 | */ | ||
229 | static struct PeerContext * | ||
230 | get_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 | */ | ||
249 | static struct PeerContext * | ||
250 | create_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 | */ | ||
274 | static struct PeerContext * | ||
275 | create_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 | */ | ||
292 | static void | ||
293 | set_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 | */ | ||
326 | struct GNUNET_CADET_Channel * | ||
327 | get_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 | */ | ||
356 | static struct GNUNET_MQ_Handle * | ||
357 | get_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 | ||
393 | static size_t | ||
394 | cadet_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 | */ | ||
425 | static void | ||
426 | check_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 | */ | ||
460 | static struct PendingMessage * | ||
461 | insert_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 | */ | ||
484 | static void | ||
485 | remove_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 | */ | ||
511 | static int | ||
512 | check_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 | */ | ||
534 | static int | ||
535 | peermap_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 | */ | ||
550 | static void | ||
551 | mq_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 | */ | ||
567 | void | ||
568 | Peers_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 | */ | ||
579 | void | ||
580 | Peers_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 | */ | ||
604 | int | ||
605 | Peers_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 | */ | ||
634 | int | ||
635 | Peers_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 | */ | ||
664 | int | ||
665 | Peers_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 | */ | ||
733 | void | ||
734 | Peers_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 | */ | ||
748 | void | ||
749 | Peers_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 | */ | ||
766 | int | ||
767 | Peers_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 | */ | ||
782 | void | ||
783 | Peers_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 | */ | ||
794 | void | ||
795 | Peers_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 | */ | ||
809 | int | ||
810 | Peers_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 | */ | ||
823 | int | ||
824 | Peers_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 | */ | ||
836 | void | ||
837 | Peers_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 | */ | ||
852 | int | ||
853 | Peers_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 | */ | ||
877 | void * | ||
878 | Peers_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 | */ | ||
914 | int | ||
915 | Peers_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 | */ | ||
943 | int | ||
944 | Peers_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 | */ | ||
980 | int | ||
981 | Peers_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 | */ | ||
1010 | void | ||
1011 | Peers_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 | */ | ||
1079 | void | ||
1080 | Peers_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 | */ | ||
1104 | void | ||
1105 | Peers_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 | */ | ||
1130 | int | ||
1131 | Peers_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 | */ | ||
34 | enum 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 | */ | ||
69 | enum 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 | */ | ||
86 | enum 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 | */ | ||
105 | typedef 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 | */ | ||
113 | void | ||
114 | Peers_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 | */ | ||
120 | void | ||
121 | Peers_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 | */ | ||
134 | int | ||
135 | Peers_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 | */ | ||
148 | int | ||
149 | Peers_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 | */ | ||
158 | int | ||
159 | Peers_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 | */ | ||
167 | void | ||
168 | Peers_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 | */ | ||
176 | void | ||
177 | Peers_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 | */ | ||
188 | int | ||
189 | Peers_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 | */ | ||
198 | void | ||
199 | Peers_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 | */ | ||
207 | void | ||
208 | Peers_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 | */ | ||
219 | int | ||
220 | Peers_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 | */ | ||
230 | int | ||
231 | Peers_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 | */ | ||
240 | void | ||
241 | Peers_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 | */ | ||
252 | int | ||
253 | Peers_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 | */ | ||
267 | void * | ||
268 | Peers_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 | */ | ||
282 | int | ||
283 | Peers_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 | */ | ||
297 | int | ||
298 | Peers_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 | */ | ||
313 | int | ||
314 | Peers_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 | */ | ||
326 | void | ||
327 | Peers_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 | */ | ||
339 | void | ||
340 | Peers_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 | */ | ||
352 | void | ||
353 | Peers_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 | */ | ||
367 | int | ||
368 | Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer, | ||
369 | const PeerOp peer_op); | ||
370 | |||
371 | /* end of gnunet-service-rps_peers.h */ | ||