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) (peer_ctx->peer_flags & mask ? GNUNET_YES : GNUNET_NO)
49 * Unset flag of given peer context.
51 #define unset_peer_flag(peer_ctx, mask) (peer_ctx->peer_flags &= (~mask))
54 * Set a channel flag of given channel context.
56 #define set_channel_flag(channel_flags, mask) ((*channel_flags) |= mask)
59 * Get channel flag of given channel context.
61 #define check_channel_flag_set(channel_flags, mask) ((*channel_flags) & mask ? GNUNET_YES : GNUNET_NO)
64 * Unset flag of given channel context.
66 #define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= (~mask))
71 * Pending operation on peer consisting of callback and closure
73 * When an operation cannot be executed right now this struct is used to store
74 * the callback and closure for later execution.
90 * List containing all messages that are yet to be send
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.
100 struct PendingMessage *next;
101 struct PendingMessage *prev;
104 * The envelope to the corresponding message
106 struct GNUNET_MQ_Envelope *ev;
109 * The corresponding context
111 struct PeerContext *peer_ctx;
120 * Struct used to keep track of other peer's status
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, ...)
130 * Message queue open to client
132 struct GNUNET_MQ_Handle *mq;
135 * Channel open to client.
137 struct GNUNET_CADET_Channel *send_channel;
140 * Flags to the sending channel
142 uint32_t *send_channel_flags;
145 * Channel open from client.
147 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
150 * Flags to the receiving channel
152 uint32_t *recv_channel_flags;
155 * Array of pending operations on this peer.
157 struct PeerPendingOp *pending_ops;
160 * Handle to the callback given to cadet_ntfy_tmt_rdy()
162 * To be canceled on shutdown.
164 struct GNUNET_CADET_TransmitHandle *transmit_handle;
167 * Number of pending operations.
169 unsigned int num_pending_ops;
172 * Identity of the peer
174 struct GNUNET_PeerIdentity peer_id;
177 * Flags indicating status of peer
182 * Last time we received something from that peer.
184 struct GNUNET_TIME_Absolute last_message_recv;
187 * Last time we received a keepalive message.
189 struct GNUNET_TIME_Absolute last_keepalive;
192 * DLL with all messages that are yet to be sent
194 struct PendingMessage *pending_messages_head;
195 struct PendingMessage *pending_messages_tail;
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),
206 * Set of all peers to keep track of them.
208 static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
211 * Own #GNUNET_PeerIdentity.
213 static const struct GNUNET_PeerIdentity *own_identity;
218 static struct GNUNET_CADET_Handle *cadet_handle;
223 * @brief Get the #PeerContext associated with a peer
225 * @param peer the peer id
227 * @return the #PeerContext
229 static struct PeerContext *
230 get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
232 struct PeerContext *ctx;
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);
243 * @brief Create a new #PeerContext and insert it into the peer map
245 * @param peer the peer to create the #PeerContext for
247 * @return the #PeerContext
249 static struct PeerContext *
250 create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
252 struct PeerContext *ctx;
255 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
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);
268 * @brief Create or get a #PeerContext
270 * @param peer the peer to get the associated context to
272 * @return the context
274 static struct PeerContext *
275 create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
277 if (GNUNET_NO == Peers_check_peer_known (peer))
279 return create_peer_ctx (peer);
281 return get_peer_ctx (peer);
285 * @brief Set the peer flag to living and
286 * call the pending operations on this peer.
288 * Also sets the #Peers_VALID flag
290 * @param peer_ctx the #PeerContext of the peer to set live
293 set_peer_live (struct PeerContext *peer_ctx)
295 struct GNUNET_PeerIdentity *peer;
298 /* Cancle cadet transmit_handle if still scheduled */
299 if (NULL != peer_ctx->transmit_handle)
301 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
302 peer_ctx->transmit_handle = NULL;
305 peer = &peer_ctx->peer_id;
306 set_peer_flag (peer_ctx, Peers_VALID);
308 LOG (GNUNET_ERROR_TYPE_DEBUG,
309 "Peer %s is live and valid\n",
312 /* Call pending operations */
313 for (i = 0; i < peer_ctx->num_pending_ops; i++)
315 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
317 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
321 * @brief Get the channel of a peer. If not existing, create.
323 * @param peer the peer id
324 * @return the #GNUNET_CADET_Channel used to send data to @a peer
326 struct GNUNET_CADET_Channel *
327 get_channel (const struct GNUNET_PeerIdentity *peer)
329 struct PeerContext *peer_ctx;
331 peer_ctx = get_peer_ctx (peer);
332 if (NULL == peer_ctx->send_channel)
334 LOG (GNUNET_ERROR_TYPE_DEBUG,
335 "Trying to establish channel to peer %s\n",
337 peer_ctx->send_channel =
338 GNUNET_CADET_channel_create (cadet_handle,
339 peer_ctx->send_channel_flags, /* context */
341 GNUNET_RPS_CADET_PORT,
342 GNUNET_CADET_OPTION_RELIABLE);
344 return peer_ctx->send_channel;
348 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
350 * If we already have a message queue open to this client,
351 * simply return it, otherways create one.
353 * @param peer the peer to get the mq to
354 * @return the #GNUNET_MQ_Handle
356 static struct GNUNET_MQ_Handle *
357 get_mq (const struct GNUNET_PeerIdentity *peer)
359 struct PeerContext *peer_ctx;
361 peer_ctx = get_peer_ctx (peer);
362 GNUNET_assert (NULL == peer_ctx->transmit_handle);
364 if (NULL == peer_ctx->mq)
366 (void) get_channel (peer);
367 peer_ctx->mq = GNUNET_CADET_mq_create (peer_ctx->send_channel);
373 * @brief Callback that is called when a channel was effectively established.
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.
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
384 * @a buf will be NULL and @a size zero if the
385 * connection was closed for writing in the meantime.
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
394 cadet_notify_transmit_ready_cb (void *cls, size_t size, void *buf)
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
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));
405 if ( (NULL != buf) &&
408 set_peer_live (peer_ctx);
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?
421 * Issue a check whether peer is live
423 * @param peer_ctx the context of the peer
426 check_peer_live (struct PeerContext *peer_ctx)
428 LOG (GNUNET_ERROR_TYPE_DEBUG,
429 "Get informed about peer %s getting live\n",
430 GNUNET_i2s (&peer_ctx->peer_id));
432 if (NULL == peer_ctx->transmit_handle &&
433 NULL == peer_ctx->send_channel)
435 (void) get_channel (&peer_ctx->peer_id);
436 peer_ctx->transmit_handle =
437 GNUNET_CADET_notify_transmit_ready (peer_ctx->send_channel,
439 GNUNET_TIME_UNIT_FOREVER_REL,
440 sizeof (struct GNUNET_MessageHeader),
441 cadet_notify_transmit_ready_cb,
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");
453 * @brief Add an envelope to a message passed to mq to list of pending messages
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
460 static struct PendingMessage *
461 insert_pending_message (const struct GNUNET_PeerIdentity *peer,
462 struct GNUNET_MQ_Envelope *ev,
465 struct PendingMessage *pending_msg;
466 struct PeerContext *peer_ctx;
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,
480 * @brief Remove a pending message from the respective DLL
482 * @param pending_msg the pending message to remove
485 remove_pending_message (struct PendingMessage *pending_msg)
487 struct PeerContext *peer_ctx;
489 peer_ctx = pending_msg->peer_ctx;
490 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
491 peer_ctx->pending_messages_tail,
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);
500 * @brief Check whether function of type #PeerOp was already scheduled
502 * The array with pending operations will probably never grow really big, so
503 * iterating over it should be ok.
505 * @param peer the peer to check
506 * @param peer_op the operation (#PeerOp) on the peer
508 * @return #GNUNET_YES if this operation is scheduled on that peer
509 * #GNUNET_NO otherwise
512 check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
513 const PeerOp peer_op)
515 const struct PeerContext *peer_ctx;
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)
526 * Iterator over hash map entries. Deletes all contexts of peers.
529 * @param key current public key
530 * @param value value in the hash map
531 * @return #GNUNET_YES if we should continue to iterate,
535 peermap_clear_iterator (void *cls,
536 const struct GNUNET_PeerIdentity *key,
539 Peers_remove_peer (key);
544 * @brief This is called once a message is sent.
546 * Removes the pending message
548 * @param cls type of the message that was sent
551 mq_notify_sent_cb (void *cls)
553 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
554 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 remove_pending_message (pending_msg);
562 * @brief Initialise storage of peers
564 * @param cadet_h cadet handle
565 * @param own_id own peer identity
568 Peers_initialise (struct GNUNET_CADET_Handle *cadet_h,
569 const struct GNUNET_PeerIdentity *own_id)
571 cadet_handle = cadet_h;
572 own_identity = own_id;
573 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
577 * @brief Delete storage of peers that was created with #Peers_initialise ()
583 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
584 peermap_clear_iterator,
587 LOG (GNUNET_ERROR_TYPE_WARNING,
588 "Iteration destroying peers was aborted.\n");
590 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
594 * @brief Add peer to known peers.
596 * This function is called on new peer_ids from 'external' sources
597 * (client seed, cadet get_peers(), ...)
599 * @param peer the new #GNUNET_PeerIdentity
601 * @return #GNUNET_YES if peer was inserted
602 * #GNUNET_NO if peer was already known
605 Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
607 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
608 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) )
610 return GNUNET_NO; /* We already know this peer - nothing to do */
612 (void) create_peer_ctx (peer);
618 * @brief Add peer to known peers and check for liveliness.
620 * This function is called on new peer_ids from 'external' sources
621 * (client seed, cadet get_peers(), ...)
623 * @param peer the new #GNUNET_PeerIdentity
625 * @return #GNUNET_YES if peer was inserted
626 * #GNUNET_NO if peer was already known
629 Peers_insert_peer_check_liveliness (const struct GNUNET_PeerIdentity *peer)
631 struct PeerContext *peer_ctx;
634 ret = Peers_insert_peer (peer);
635 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
639 peer_ctx = get_peer_ctx (peer);
640 if (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_VALID))
642 check_peer_live (peer_ctx);
648 * @brief Remove unecessary data
650 * If the other peer is not intending to send messages, we have messages pending
651 * to be sent to this peer and we are not waiting for a reply, remove the
652 * information about it (its #PeerContext).
654 * @param peer the peer to clean
655 * @return #GNUNET_YES if peer was removed
656 * #GNUNET_NO otherwise
659 Peers_clean_peer (const struct GNUNET_PeerIdentity *peer)
661 struct PeerContext *peer_ctx;
663 // TODO actually remove unnecessary data
665 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
670 peer_ctx = get_peer_ctx (peer);
671 if ( (NULL != peer_ctx->recv_channel) ||
672 (NULL != peer_ctx->pending_messages_head) ||
673 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
677 Peers_remove_peer (peer);
684 * @param peer the peer to clean
685 * @return #GNUNET_YES if peer was removed
686 * #GNUNET_NO otherwise
689 Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
691 struct PeerContext *peer_ctx;
693 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
698 peer_ctx = get_peer_ctx (peer);
699 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
700 LOG (GNUNET_ERROR_TYPE_DEBUG,
701 "Going to remove peer %s\n",
702 GNUNET_i2s (&peer_ctx->peer_id));
704 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
705 // TODO delete struct GNUNET_TRANSPORT_TransmitHandle *transmit_handle
706 /* Cancle messages that have not been sent yet */
707 while (NULL != peer_ctx->pending_messages_head)
709 LOG (GNUNET_ERROR_TYPE_DEBUG,
710 "Removing unsent %s\n",
711 peer_ctx->pending_messages_head->type);
712 remove_pending_message (peer_ctx->pending_messages_head);
714 /* If we are still waiting for notification whether this peer is live
715 * cancel the according task */
716 if (NULL != peer_ctx->transmit_handle)
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719 "Trying to cancle transmit_handle for peer %s\n",
720 GNUNET_i2s (&peer_ctx->peer_id));
721 GNUNET_CADET_notify_transmit_ready_cancel (peer_ctx->transmit_handle);
722 peer_ctx->transmit_handle = NULL;
724 if (NULL != peer_ctx->send_channel)
726 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
727 peer_ctx->send_channel = NULL;
729 if (NULL != peer_ctx->recv_channel)
731 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
732 peer_ctx->recv_channel = NULL;
734 if (NULL != peer_ctx->mq)
736 GNUNET_MQ_destroy (peer_ctx->mq);
740 GNUNET_free (peer_ctx->send_channel_flags);
741 GNUNET_free (peer_ctx->recv_channel_flags);
743 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
745 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
747 GNUNET_free (peer_ctx);
752 * @brief set flags on a given peer.
754 * @param peer the peer to set flags on
755 * @param flags the flags
758 Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
760 struct PeerContext *peer_ctx;
762 peer_ctx = get_peer_ctx (peer);
763 set_peer_flag (peer_ctx, flags);
767 * @brief unset flags on a given peer.
769 * @param peer the peer to unset flags on
770 * @param flags the flags
773 Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
775 struct PeerContext *peer_ctx;
777 peer_ctx = get_peer_ctx (peer);
778 unset_peer_flag (peer_ctx, flags);
782 * @brief Check whether flags on a peer are set.
784 * @param peer the peer to check the flag of
785 * @param flags the flags to check
787 * @return #GNUNET_YES if all given flags are set
788 * #GNUNET_NO otherwise
791 Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
793 struct PeerContext *peer_ctx;
795 peer_ctx = get_peer_ctx (peer);
796 return check_peer_flag_set (peer_ctx, flags);
801 * @brief set flags on a given channel.
803 * @param channel the channel to set flags on
804 * @param flags the flags
807 Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
809 set_channel_flag (channel_flags, flags);
813 * @brief unset flags on a given channel.
815 * @param channel the channel to unset flags on
816 * @param flags the flags
819 Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
821 unset_channel_flag (channel_flags, flags);
825 * @brief Check whether flags on a channel are set.
827 * @param channel the channel to check the flag of
828 * @param flags the flags to check
830 * @return #GNUNET_YES if all given flags are set
831 * #GNUNET_NO otherwise
834 Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
836 return check_channel_flag_set (channel_flags, flags);
840 * @brief Check whether we have information about the given peer.
842 * @param peer peer in question
844 * @return #GNUNET_YES if peer is known
845 * #GNUNET_NO if peer is not knwon
848 Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
850 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
854 * @brief Indicate that we want to send to the other peer
856 * This establishes a sending channel
858 * @param peer the peer to establish channel to
861 Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
863 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
864 (void) get_channel (peer);
868 * @brief Check whether other peer has the intention to send/opened channel
871 * @param peer the peer in question
873 * @return #GNUNET_YES if peer has the intention to send
874 * #GNUNET_NO otherwise
877 Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
879 const struct PeerContext *peer_ctx;
881 peer_ctx = get_peer_ctx (peer);
882 if (NULL != peer_ctx->recv_channel)
890 * Handle the channel a peer opens to us.
892 * @param cls The closure
893 * @param channel The channel the peer wants to establish
894 * @param initiator The peer's peer ID
895 * @param port The port the channel is being established over
896 * @param options Further options
898 * @return initial channel context for the channel
899 * (can be NULL -- that's not an error)
902 Peers_handle_inbound_channel (void *cls,
903 struct GNUNET_CADET_Channel *channel,
904 const struct GNUNET_PeerIdentity *initiator,
906 enum GNUNET_CADET_ChannelOption options)
908 struct PeerContext *peer_ctx;
910 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 "New channel was established to us (Peer %s).\n",
912 GNUNET_i2s (initiator));
913 GNUNET_assert (NULL != channel); /* according to cadet API */
914 /* Make sure we 'know' about this peer */
915 peer_ctx = create_or_get_peer_ctx (initiator);
916 set_peer_live (peer_ctx);
917 /* We only accept one incoming channel per peer */
918 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
920 set_channel_flag (peer_ctx->recv_channel_flags,
921 Peers_CHANNEL_ESTABLISHED_TWICE);
922 GNUNET_CADET_channel_destroy (channel);
923 /* return the channel context */
924 return peer_ctx->recv_channel_flags;
926 peer_ctx->recv_channel = channel;
927 return peer_ctx->recv_channel_flags;
931 * @brief Check whether a sending channel towards the given peer exists
933 * @param peer the peer to check for
935 * @return #GNUNET_YES if a sending channel towards that peer exists
936 * #GNUNET_NO otherwise
939 Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
941 struct PeerContext *peer_ctx;
943 if (GNUNET_NO == Peers_check_peer_known (peer))
944 { /* If no such peer exists, there is no channel */
947 peer_ctx = get_peer_ctx (peer);
948 if (NULL == peer_ctx->send_channel)
956 * @brief check whether the given channel is the sending channel of the given
959 * @param peer the peer in question
960 * @param channel the channel to check for
961 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
962 * #Peers_CHANNEL_ROLE_RECEIVING
964 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
965 * #GNUNET_NO otherwise
968 Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
969 const struct GNUNET_CADET_Channel *channel,
970 enum Peers_ChannelRole role)
972 const struct PeerContext *peer_ctx;
974 if (GNUNET_NO == Peers_check_peer_known (peer))
978 peer_ctx = get_peer_ctx (peer);
979 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
980 (channel == peer_ctx->send_channel) )
984 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
985 (channel == peer_ctx->recv_channel) )
993 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
994 * intention to another peer
996 * If there is also no channel to receive messages from that peer, remove it
1000 * @peer the peer identity of the peer whose sending channel to destroy
1001 * @return #GNUNET_YES if channel was destroyed
1002 * #GNUNET_NO otherwise
1005 Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1007 struct PeerContext *peer_ctx;
1009 if (GNUNET_NO == Peers_check_peer_known (peer))
1013 peer_ctx = get_peer_ctx (peer);
1014 if (NULL != peer_ctx->send_channel)
1016 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1017 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1018 peer_ctx->send_channel = NULL;
1025 * This is called when a channel is destroyed.
1027 * Removes peer completely from our knowledge if the send_channel was destroyed
1028 * Otherwise simply delete the recv_channel
1030 * @param cls The closure
1031 * @param channel The channel being closed
1032 * @param channel_ctx The context associated with this channel
1035 Peers_cleanup_destroyed_channel (void *cls,
1036 const struct GNUNET_CADET_Channel *channel,
1039 struct GNUNET_PeerIdentity *peer;
1040 struct PeerContext *peer_ctx;
1042 peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
1043 (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
1044 // FIXME wait for cadet to change this function
1046 if (GNUNET_NO == Peers_check_peer_known (peer))
1047 {/* We don't want to implicitly create a context that we're about to kill */
1048 LOG (GNUNET_ERROR_TYPE_DEBUG,
1049 "channel (%s) without associated context was destroyed\n",
1054 peer_ctx = get_peer_ctx (peer);
1055 GNUNET_assert (NULL != peer_ctx); /* It could have been removed by shutdown_task */
1057 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1058 * flag will be set. In this case simply make sure that the channels are
1060 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1061 {/* We initiatad the destruction of this particular peer */
1062 if (channel == peer_ctx->send_channel)
1063 peer_ctx->send_channel = NULL;
1064 else if (channel == peer_ctx->recv_channel)
1065 peer_ctx->recv_channel = NULL;
1071 { /* We did not initiate the destruction of this peer */
1072 if (channel == peer_ctx->send_channel)
1073 { /* Something (but us) killd the channel - clean up peer */
1074 LOG (GNUNET_ERROR_TYPE_DEBUG,
1075 "send channel (%s) was destroyed - cleaning up\n",
1077 peer_ctx->send_channel = NULL;
1079 else if (channel == peer_ctx->recv_channel)
1080 { /* Other peer doesn't want to send us messages anymore */
1081 LOG (GNUNET_ERROR_TYPE_DEBUG,
1082 "Peer %s destroyed recv channel - cleaning up channel\n",
1084 peer_ctx->recv_channel = NULL;
1088 LOG (GNUNET_ERROR_TYPE_WARNING,
1089 "unknown channel (%s) was destroyed\n",
1096 * @brief Issue a check whether peer is live
1098 * This tries to establish a channel to the given peer. Once the channel is
1099 * established successfully, we know the peer is live.
1101 * @param peer the peer to check liveliness
1104 Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1106 struct PeerContext *peer_ctx;
1108 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1110 return; /* We know that we are online */
1113 peer_ctx = create_or_get_peer_ctx (peer);
1114 // TODO if LIVE/ONLINE
1115 check_peer_live (peer_ctx);
1119 * @brief Send a message to another peer.
1121 * Keeps track about pending messages so they can be properly removed when the
1122 * peer is destroyed.
1124 * @param peer receeiver of the message
1125 * @param ev envelope of the message
1126 * @param type type of the message
1129 Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1130 struct GNUNET_MQ_Envelope *ev,
1133 struct PendingMessage *pending_msg;
1134 struct GNUNET_MQ_Handle *mq;
1136 pending_msg = insert_pending_message (peer, ev, "PULL REPLY");
1138 GNUNET_MQ_notify_sent (ev,
1141 GNUNET_MQ_send (mq, ev);
1145 * @brief Schedule a operation on given peer
1147 * Avoids scheduling an operation twice.
1149 * @param peer the peer we want to schedule the operation for once it gets live
1151 * @return #GNUNET_YES if the operation was scheduled
1152 * #GNUNET_NO otherwise
1155 Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1156 const PeerOp peer_op)
1158 struct PeerPendingOp pending_op;
1159 struct PeerContext *peer_ctx;
1161 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1165 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1167 //TODO if LIVE/ONLINE execute immediately
1169 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1171 peer_ctx = get_peer_ctx (peer);
1172 pending_op.op = peer_op;
1173 pending_op.op_cls = NULL;
1174 GNUNET_array_append (peer_ctx->pending_ops,
1175 peer_ctx->num_pending_ops,
1182 /* end of gnunet-service-rps_peers.c */