2 This file is part of GNUnet.
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.
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.
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.
22 * @file rps/gnunet-service-rps_peers.c
23 * @brief utilities for managing (information about) peers
24 * @author Julius Bünger
27 #include "gnunet_util_lib.h"
28 #include "gnunet_cadet_service.h"
31 #include "gnunet-service-rps_peers.h"
35 #define LOG(kind, ...) GNUNET_log(kind, __VA_ARGS__)
39 * Set a peer flag of given peer context.
41 #define set_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
44 * Get peer flag of given peer context.
46 #define check_peer_flag_set(peer_ctx, mask)\
47 ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
50 * Unset flag of given peer context.
52 #define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
55 * Set a channel flag of given channel context.
57 #define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask))
60 * Get channel flag of given channel context.
62 #define check_channel_flag_set(channel_flags, mask)\
63 ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
66 * Unset flag of given channel context.
68 #define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
73 * Pending operation on peer consisting of callback and closure
75 * When an operation cannot be executed right now this struct is used to store
76 * the callback and closure for later execution.
92 * List containing all messages that are yet to be send
94 * This is used to keep track of all messages that have not been sent yet. When
95 * a peer is to be removed the pending messages can be removed properly.
102 struct PendingMessage *next;
103 struct PendingMessage *prev;
106 * The envelope to the corresponding message
108 struct GNUNET_MQ_Envelope *ev;
111 * The corresponding context
113 struct PeerContext *peer_ctx;
122 * Struct used to keep track of other peer's status
124 * This is stored in a multipeermap.
125 * It contains information such as cadet channels, a message queue for sending,
126 * status about the channels, the pending operations on this peer and some flags
127 * about the status of the peer itself. (live, valid, ...)
132 * Message queue open to client
134 struct GNUNET_MQ_Handle *mq;
137 * Channel open to client.
139 struct GNUNET_CADET_Channel *send_channel;
142 * Flags to the sending channel
144 uint32_t *send_channel_flags;
147 * Channel open from client.
149 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
152 * Flags to the receiving channel
154 uint32_t *recv_channel_flags;
157 * Array of pending operations on this peer.
159 struct PeerPendingOp *pending_ops;
162 * Handle to the callback given to cadet_ntfy_tmt_rdy()
164 * To be canceled on shutdown.
166 struct GNUNET_CADET_TransmitHandle *transmit_handle;
169 * Number of pending operations.
171 unsigned int num_pending_ops;
174 * Identity of the peer
176 struct GNUNET_PeerIdentity peer_id;
179 * Flags indicating status of peer
184 * Last time we received something from that peer.
186 struct GNUNET_TIME_Absolute last_message_recv;
189 * Last time we received a keepalive message.
191 struct GNUNET_TIME_Absolute last_keepalive;
194 * DLL with all messages that are yet to be sent
196 struct PendingMessage *pending_messages_head;
197 struct PendingMessage *pending_messages_tail;
200 * This is pobably followed by 'statistical' data (when we first saw
201 * him, how did we get his ID, how many pushes (in a timeinterval),
208 * Set of all peers to keep track of them.
210 static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
213 * Own #GNUNET_PeerIdentity.
215 static const struct GNUNET_PeerIdentity *own_identity;
220 static struct GNUNET_CADET_Handle *cadet_handle;
225 * @brief Get the #PeerContext associated with a peer
227 * @param peer the peer id
229 * @return the #PeerContext
231 static struct PeerContext *
232 get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
234 struct PeerContext *ctx;
237 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
238 GNUNET_assert (GNUNET_YES == ret);
239 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
240 GNUNET_assert (NULL != ctx);
245 * @brief Create a new #PeerContext and insert it into the peer map
247 * @param peer the peer to create the #PeerContext for
249 * @return the #PeerContext
251 static struct PeerContext *
252 create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
254 struct PeerContext *ctx;
257 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
259 ctx = GNUNET_new (struct PeerContext);
260 ctx->peer_id = *peer;
261 ctx->send_channel_flags = GNUNET_new (uint32_t);
262 ctx->recv_channel_flags = GNUNET_new (uint32_t);
263 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
264 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
265 GNUNET_assert (GNUNET_OK == ret);
270 * @brief Create or get a #PeerContext
272 * @param peer the peer to get the associated context to
274 * @return the context
276 static struct PeerContext *
277 create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
279 if (GNUNET_NO == Peers_check_peer_known (peer))
281 return create_peer_ctx (peer);
283 return get_peer_ctx (peer);
287 * @brief Set the peer flag to living and
288 * call the pending operations on this peer.
290 * Also sets the #Peers_VALID flag
292 * @param peer_ctx the #PeerContext of the peer to set live
295 set_peer_live (struct PeerContext *peer_ctx)
297 struct GNUNET_PeerIdentity *peer;
300 /* Cancle cadet transmit_handle if still scheduled */
301 if (NULL != peer_ctx->transmit_handle)
303 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
304 peer_ctx->transmit_handle = NULL;
307 peer = &peer_ctx->peer_id;
308 set_peer_flag (peer_ctx, Peers_VALID);
309 set_peer_flag (peer_ctx, Peers_ONLINE);
310 LOG (GNUNET_ERROR_TYPE_DEBUG,
311 "Peer %s is live and valid\n",
314 /* Call pending operations */
315 for (i = 0; i < peer_ctx->num_pending_ops; i++)
317 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
319 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
323 * @brief Get the channel of a peer. If not existing, create.
325 * @param peer the peer id
326 * @return the #GNUNET_CADET_Channel used to send data to @a peer
328 struct GNUNET_CADET_Channel *
329 get_channel (const struct GNUNET_PeerIdentity *peer)
331 struct PeerContext *peer_ctx;
333 peer_ctx = get_peer_ctx (peer);
334 if (NULL == peer_ctx->send_channel)
336 LOG (GNUNET_ERROR_TYPE_DEBUG,
337 "Trying to establish channel to peer %s\n",
339 peer_ctx->send_channel =
340 GNUNET_CADET_channel_create (cadet_handle,
341 peer_ctx->send_channel_flags, /* context */
343 GNUNET_RPS_CADET_PORT,
344 GNUNET_CADET_OPTION_RELIABLE);
346 return peer_ctx->send_channel;
350 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
352 * If we already have a message queue open to this client,
353 * simply return it, otherways create one.
355 * @param peer the peer to get the mq to
356 * @return the #GNUNET_MQ_Handle
358 static struct GNUNET_MQ_Handle *
359 get_mq (const struct GNUNET_PeerIdentity *peer)
361 struct PeerContext *peer_ctx;
363 peer_ctx = get_peer_ctx (peer);
364 GNUNET_assert (NULL == peer_ctx->transmit_handle);
366 if (NULL == peer_ctx->mq)
368 (void) get_channel (peer);
369 peer_ctx->mq = GNUNET_CADET_mq_create (peer_ctx->send_channel);
375 * @brief Callback that is called when a channel was effectively established.
377 * This is an implementation of #GNUNET_CONNECTION_TransmitReadyNotify and
378 * given to #GNUNET_CADET_notify_transmit_ready_cancel and called when the
379 * channel was successfully established.
381 * This function type was originally ment to be called to provide the data to
382 * be sent. This is called when the connection is ready to queue more data.
383 * However we use it to get notified about the successful establishement of a
386 * @a buf will be NULL and @a size zero if the
387 * connection was closed for writing in the meantime.
390 * @param size number of bytes available in @a buf
391 * @param buf where the callee should write the message
392 * @return number of bytes written to @a buf
396 cadet_notify_transmit_ready_cb (void *cls, size_t size, void *buf)
398 struct PeerContext *peer_ctx = (struct PeerContext *) cls;
399 // TODO make sure the context is not deleted or the establishing of the
400 // channel is cancelled
402 peer_ctx->transmit_handle = NULL;
403 LOG (GNUNET_ERROR_TYPE_DEBUG,
404 "Set ->transmit_handle = NULL for peer %s\n",
405 GNUNET_i2s (&peer_ctx->peer_id));
407 if ( (NULL != buf) &&
410 set_peer_live (peer_ctx);
414 LOG (GNUNET_ERROR_TYPE_WARNING,
415 "Problems establishing a connection to peer %s in order to check liveliness\n",
416 GNUNET_i2s (&peer_ctx->peer_id));
417 // TODO reschedule? cleanup?
423 * Issue a check whether peer is live
425 * @param peer_ctx the context of the peer
428 check_peer_live (struct PeerContext *peer_ctx)
430 LOG (GNUNET_ERROR_TYPE_DEBUG,
431 "Get informed about peer %s getting live\n",
432 GNUNET_i2s (&peer_ctx->peer_id));
434 if (NULL == peer_ctx->transmit_handle &&
435 NULL == peer_ctx->send_channel)
437 (void) get_channel (&peer_ctx->peer_id);
438 peer_ctx->transmit_handle =
439 GNUNET_CADET_notify_transmit_ready (peer_ctx->send_channel,
441 GNUNET_TIME_UNIT_FOREVER_REL,
442 sizeof (struct GNUNET_MessageHeader),
443 cadet_notify_transmit_ready_cb,
446 else if (NULL != peer_ctx->transmit_handle)
447 LOG (GNUNET_ERROR_TYPE_DEBUG,
448 "Already waiting for notification\n");
449 else if (NULL != peer_ctx->send_channel)
450 LOG (GNUNET_ERROR_TYPE_DEBUG,
451 "Already have established channel to peer\n");
455 * @brief Add an envelope to a message passed to mq to list of pending messages
457 * @param peer peer the message was sent to
458 * @param ev envelope to the message
459 * @param type type of the message to be sent
460 * @return pointer to pending message
462 static struct PendingMessage *
463 insert_pending_message (const struct GNUNET_PeerIdentity *peer,
464 struct GNUNET_MQ_Envelope *ev,
467 struct PendingMessage *pending_msg;
468 struct PeerContext *peer_ctx;
470 peer_ctx = get_peer_ctx (peer);
471 pending_msg = GNUNET_new (struct PendingMessage);
472 pending_msg->ev = ev;
473 pending_msg->peer_ctx = peer_ctx;
474 pending_msg->type = type;
475 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
476 peer_ctx->pending_messages_tail,
482 * @brief Remove a pending message from the respective DLL
484 * @param pending_msg the pending message to remove
487 remove_pending_message (struct PendingMessage *pending_msg)
489 struct PeerContext *peer_ctx;
491 peer_ctx = pending_msg->peer_ctx;
492 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
493 peer_ctx->pending_messages_tail,
495 /* FIXME We are not able to cancel messages as #GNUNET_CADET_mq_create () does
496 * not set a #GNUNET_MQ_CancelImpl */
497 /* GNUNET_MQ_send_cancel (peer_ctx->pending_messages_head->ev); */
498 GNUNET_free (pending_msg);
502 * @brief Check whether function of type #PeerOp was already scheduled
504 * The array with pending operations will probably never grow really big, so
505 * iterating over it should be ok.
507 * @param peer the peer to check
508 * @param peer_op the operation (#PeerOp) on the peer
510 * @return #GNUNET_YES if this operation is scheduled on that peer
511 * #GNUNET_NO otherwise
514 check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
515 const PeerOp peer_op)
517 const struct PeerContext *peer_ctx;
520 peer_ctx = get_peer_ctx (peer);
521 for (i = 0; i < peer_ctx->num_pending_ops; i++)
522 if (peer_op == peer_ctx->pending_ops[i].op)
528 * Iterator over hash map entries. Deletes all contexts of peers.
531 * @param key current public key
532 * @param value value in the hash map
533 * @return #GNUNET_YES if we should continue to iterate,
537 peermap_clear_iterator (void *cls,
538 const struct GNUNET_PeerIdentity *key,
541 Peers_remove_peer (key);
546 * @brief This is called once a message is sent.
548 * Removes the pending message
550 * @param cls type of the message that was sent
553 mq_notify_sent_cb (void *cls)
555 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
559 remove_pending_message (pending_msg);
564 * @brief Initialise storage of peers
566 * @param cadet_h cadet handle
567 * @param own_id own peer identity
570 Peers_initialise (struct GNUNET_CADET_Handle *cadet_h,
571 const struct GNUNET_PeerIdentity *own_id)
573 cadet_handle = cadet_h;
574 own_identity = own_id;
575 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
579 * @brief Delete storage of peers that was created with #Peers_initialise ()
585 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
586 peermap_clear_iterator,
589 LOG (GNUNET_ERROR_TYPE_WARNING,
590 "Iteration destroying peers was aborted.\n");
592 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
596 * @brief Add peer to known peers.
598 * This function is called on new peer_ids from 'external' sources
599 * (client seed, cadet get_peers(), ...)
601 * @param peer the new #GNUNET_PeerIdentity
603 * @return #GNUNET_YES if peer was inserted
604 * #GNUNET_NO if peer was already known
607 Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
609 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
610 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) )
612 return GNUNET_NO; /* We already know this peer - nothing to do */
614 (void) create_peer_ctx (peer);
620 * @brief Add peer to known peers and check for liveliness.
622 * This function is called on new peer_ids from 'external' sources
623 * (client seed, cadet get_peers(), ...)
625 * @param peer the new #GNUNET_PeerIdentity
627 * @return #GNUNET_YES if peer was inserted
628 * #GNUNET_NO if peer was already known
631 Peers_insert_peer_check_liveliness (const struct GNUNET_PeerIdentity *peer)
633 struct PeerContext *peer_ctx;
636 ret = Peers_insert_peer (peer);
637 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
641 peer_ctx = get_peer_ctx (peer);
642 if (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_VALID))
644 check_peer_live (peer_ctx);
650 * @brief Remove unecessary data
652 * If the other peer is not intending to send messages, we have messages pending
653 * to be sent to this peer and we are not waiting for a reply, remove the
654 * information about it (its #PeerContext).
656 * @param peer the peer to clean
657 * @return #GNUNET_YES if peer was removed
658 * #GNUNET_NO otherwise
661 Peers_clean_peer (const struct GNUNET_PeerIdentity *peer)
663 struct PeerContext *peer_ctx;
665 // TODO actually remove unnecessary data
667 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
672 peer_ctx = get_peer_ctx (peer);
673 if ( (NULL != peer_ctx->recv_channel) ||
674 (NULL != peer_ctx->pending_messages_head) ||
675 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
679 Peers_remove_peer (peer);
686 * @param peer the peer to clean
687 * @return #GNUNET_YES if peer was removed
688 * #GNUNET_NO otherwise
691 Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
693 struct PeerContext *peer_ctx;
695 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
700 peer_ctx = get_peer_ctx (peer);
701 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
702 LOG (GNUNET_ERROR_TYPE_DEBUG,
703 "Going to remove peer %s\n",
704 GNUNET_i2s (&peer_ctx->peer_id));
706 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
707 // TODO delete struct GNUNET_TRANSPORT_TransmitHandle *transmit_handle
708 /* Cancle messages that have not been sent yet */
709 while (NULL != peer_ctx->pending_messages_head)
711 LOG (GNUNET_ERROR_TYPE_DEBUG,
712 "Removing unsent %s\n",
713 peer_ctx->pending_messages_head->type);
714 remove_pending_message (peer_ctx->pending_messages_head);
716 /* If we are still waiting for notification whether this peer is live
717 * cancel the according task */
718 if (NULL != peer_ctx->transmit_handle)
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
721 "Trying to cancle transmit_handle for peer %s\n",
722 GNUNET_i2s (&peer_ctx->peer_id));
723 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
724 peer_ctx->transmit_handle = NULL;
726 if (NULL != peer_ctx->send_channel)
728 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
729 peer_ctx->send_channel = NULL;
731 if (NULL != peer_ctx->recv_channel)
733 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
734 peer_ctx->recv_channel = NULL;
736 if (NULL != peer_ctx->mq)
738 GNUNET_MQ_destroy (peer_ctx->mq);
742 GNUNET_free (peer_ctx->send_channel_flags);
743 GNUNET_free (peer_ctx->recv_channel_flags);
745 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
747 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
749 GNUNET_free (peer_ctx);
754 * @brief set flags on a given peer.
756 * @param peer the peer to set flags on
757 * @param flags the flags
760 Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
762 struct PeerContext *peer_ctx;
764 peer_ctx = get_peer_ctx (peer);
765 set_peer_flag (peer_ctx, flags);
769 * @brief unset flags on a given peer.
771 * @param peer the peer to unset flags on
772 * @param flags the flags
775 Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
777 struct PeerContext *peer_ctx;
779 peer_ctx = get_peer_ctx (peer);
780 unset_peer_flag (peer_ctx, flags);
784 * @brief Check whether flags on a peer are set.
786 * @param peer the peer to check the flag of
787 * @param flags the flags to check
789 * @return #GNUNET_YES if all given flags are set
790 * #GNUNET_NO otherwise
793 Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
795 struct PeerContext *peer_ctx;
797 peer_ctx = get_peer_ctx (peer);
798 return check_peer_flag_set (peer_ctx, flags);
803 * @brief set flags on a given channel.
805 * @param channel the channel to set flags on
806 * @param flags the flags
809 Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
811 set_channel_flag (channel_flags, flags);
815 * @brief unset flags on a given channel.
817 * @param channel the channel to unset flags on
818 * @param flags the flags
821 Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
823 unset_channel_flag (channel_flags, flags);
827 * @brief Check whether flags on a channel are set.
829 * @param channel the channel to check the flag of
830 * @param flags the flags to check
832 * @return #GNUNET_YES if all given flags are set
833 * #GNUNET_NO otherwise
836 Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
838 return check_channel_flag_set (channel_flags, flags);
842 * @brief Check whether we have information about the given peer.
844 * @param peer peer in question
846 * @return #GNUNET_YES if peer is known
847 * #GNUNET_NO if peer is not knwon
850 Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
852 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
856 * @brief Indicate that we want to send to the other peer
858 * This establishes a sending channel
860 * @param peer the peer to establish channel to
863 Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
865 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
866 (void) get_channel (peer);
870 * @brief Check whether other peer has the intention to send/opened channel
873 * @param peer the peer in question
875 * @return #GNUNET_YES if peer has the intention to send
876 * #GNUNET_NO otherwise
879 Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
881 const struct PeerContext *peer_ctx;
883 peer_ctx = get_peer_ctx (peer);
884 if (NULL != peer_ctx->recv_channel)
892 * Handle the channel a peer opens to us.
894 * @param cls The closure
895 * @param channel The channel the peer wants to establish
896 * @param initiator The peer's peer ID
897 * @param port The port the channel is being established over
898 * @param options Further options
900 * @return initial channel context for the channel
901 * (can be NULL -- that's not an error)
904 Peers_handle_inbound_channel (void *cls,
905 struct GNUNET_CADET_Channel *channel,
906 const struct GNUNET_PeerIdentity *initiator,
908 enum GNUNET_CADET_ChannelOption options)
910 struct PeerContext *peer_ctx;
912 LOG (GNUNET_ERROR_TYPE_DEBUG,
913 "New channel was established to us (Peer %s).\n",
914 GNUNET_i2s (initiator));
915 GNUNET_assert (NULL != channel); /* according to cadet API */
916 /* Make sure we 'know' about this peer */
917 peer_ctx = create_or_get_peer_ctx (initiator);
918 set_peer_live (peer_ctx);
919 /* We only accept one incoming channel per peer */
920 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
922 set_channel_flag (peer_ctx->recv_channel_flags,
923 Peers_CHANNEL_ESTABLISHED_TWICE);
924 GNUNET_CADET_channel_destroy (channel);
925 /* return the channel context */
926 return peer_ctx->recv_channel_flags;
928 peer_ctx->recv_channel = channel;
929 return peer_ctx->recv_channel_flags;
933 * @brief Check whether a sending channel towards the given peer exists
935 * @param peer the peer to check for
937 * @return #GNUNET_YES if a sending channel towards that peer exists
938 * #GNUNET_NO otherwise
941 Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
943 struct PeerContext *peer_ctx;
945 if (GNUNET_NO == Peers_check_peer_known (peer))
946 { /* If no such peer exists, there is no channel */
949 peer_ctx = get_peer_ctx (peer);
950 if (NULL == peer_ctx->send_channel)
958 * @brief check whether the given channel is the sending channel of the given
961 * @param peer the peer in question
962 * @param channel the channel to check for
963 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
964 * #Peers_CHANNEL_ROLE_RECEIVING
966 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
967 * #GNUNET_NO otherwise
970 Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
971 const struct GNUNET_CADET_Channel *channel,
972 enum Peers_ChannelRole role)
974 const struct PeerContext *peer_ctx;
976 if (GNUNET_NO == Peers_check_peer_known (peer))
980 peer_ctx = get_peer_ctx (peer);
981 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
982 (channel == peer_ctx->send_channel) )
986 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
987 (channel == peer_ctx->recv_channel) )
995 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
996 * intention to another peer
998 * If there is also no channel to receive messages from that peer, remove it
1002 * @peer the peer identity of the peer whose sending channel to destroy
1003 * @return #GNUNET_YES if channel was destroyed
1004 * #GNUNET_NO otherwise
1007 Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1009 struct PeerContext *peer_ctx;
1011 if (GNUNET_NO == Peers_check_peer_known (peer))
1015 peer_ctx = get_peer_ctx (peer);
1016 if (NULL != peer_ctx->send_channel)
1018 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1019 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1020 peer_ctx->send_channel = NULL;
1027 * This is called when a channel is destroyed.
1029 * Removes peer completely from our knowledge if the send_channel was destroyed
1030 * Otherwise simply delete the recv_channel
1032 * @param cls The closure
1033 * @param channel The channel being closed
1034 * @param channel_ctx The context associated with this channel
1037 Peers_cleanup_destroyed_channel (void *cls,
1038 const struct GNUNET_CADET_Channel *channel,
1041 struct GNUNET_PeerIdentity *peer;
1042 struct PeerContext *peer_ctx;
1044 peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
1045 (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
1046 // FIXME wait for cadet to change this function
1048 if (GNUNET_NO == Peers_check_peer_known (peer))
1049 {/* We don't want to implicitly create a context that we're about to kill */
1050 LOG (GNUNET_ERROR_TYPE_DEBUG,
1051 "channel (%s) without associated context was destroyed\n",
1056 peer_ctx = get_peer_ctx (peer);
1057 GNUNET_assert (NULL != peer_ctx); /* It could have been removed by shutdown_task */
1059 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1060 * flag will be set. In this case simply make sure that the channels are
1062 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1063 {/* We initiatad the destruction of this particular peer */
1064 if (channel == peer_ctx->send_channel)
1065 peer_ctx->send_channel = NULL;
1066 else if (channel == peer_ctx->recv_channel)
1067 peer_ctx->recv_channel = NULL;
1073 { /* We did not initiate the destruction of this peer */
1074 if (channel == peer_ctx->send_channel)
1075 { /* Something (but us) killd the channel - clean up peer */
1076 LOG (GNUNET_ERROR_TYPE_DEBUG,
1077 "send channel (%s) was destroyed - cleaning up\n",
1079 peer_ctx->send_channel = NULL;
1081 else if (channel == peer_ctx->recv_channel)
1082 { /* Other peer doesn't want to send us messages anymore */
1083 LOG (GNUNET_ERROR_TYPE_DEBUG,
1084 "Peer %s destroyed recv channel - cleaning up channel\n",
1086 peer_ctx->recv_channel = NULL;
1090 LOG (GNUNET_ERROR_TYPE_WARNING,
1091 "unknown channel (%s) was destroyed\n",
1098 * @brief Issue a check whether peer is live
1100 * This tries to establish a channel to the given peer. Once the channel is
1101 * established successfully, we know the peer is live.
1103 * @param peer the peer to check liveliness
1106 Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1108 struct PeerContext *peer_ctx;
1110 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1112 return; /* We know that we are online */
1115 peer_ctx = create_or_get_peer_ctx (peer);
1116 // TODO if LIVE/ONLINE
1117 check_peer_live (peer_ctx);
1121 * @brief Send a message to another peer.
1123 * Keeps track about pending messages so they can be properly removed when the
1124 * peer is destroyed.
1126 * @param peer receeiver of the message
1127 * @param ev envelope of the message
1128 * @param type type of the message
1131 Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1132 struct GNUNET_MQ_Envelope *ev,
1135 struct PendingMessage *pending_msg;
1136 struct GNUNET_MQ_Handle *mq;
1138 pending_msg = insert_pending_message (peer, ev, "PULL REPLY");
1140 GNUNET_MQ_notify_sent (ev,
1143 GNUNET_MQ_send (mq, ev);
1147 * @brief Schedule a operation on given peer
1149 * Avoids scheduling an operation twice.
1151 * @param peer the peer we want to schedule the operation for once it gets live
1153 * @return #GNUNET_YES if the operation was scheduled
1154 * #GNUNET_NO otherwise
1157 Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1158 const PeerOp peer_op)
1160 struct PeerPendingOp pending_op;
1161 struct PeerContext *peer_ctx;
1163 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1167 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1169 //TODO if LIVE/ONLINE execute immediately
1171 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1173 peer_ctx = get_peer_ctx (peer);
1174 pending_op.op = peer_op;
1175 pending_op.op_cls = NULL;
1176 GNUNET_array_append (peer_ctx->pending_ops,
1177 peer_ctx->num_pending_ops,
1184 /* end of gnunet-service-rps_peers.c */