aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJulius Bünger <buenger@mytum.de>2017-12-29 15:37:48 +0100
committerJulius Bünger <buenger@mytum.de>2017-12-29 15:37:48 +0100
commitf2b64da6fd07c3a20c8f202fa8920f9f2e96e51e (patch)
tree2d774cf2c02dc6b3d49e3fdcbe7eabc41512744f /src
parentc6f178907d4f1ef53a53ed85e12521d07ba4d08e (diff)
downloadgnunet-f2b64da6fd07c3a20c8f202fa8920f9f2e96e51e.tar.gz
gnunet-f2b64da6fd07c3a20c8f202fa8920f9f2e96e51e.zip
refactor rps code
Diffstat (limited to 'src')
-rw-r--r--src/rps/.gitignore1
-rw-r--r--src/rps/Makefile.am9
-rw-r--r--src/rps/gnunet-service-rps.c1723
-rw-r--r--src/rps/gnunet-service-rps_peers.c1701
-rw-r--r--src/rps/gnunet-service-rps_peers.h437
-rw-r--r--src/rps/rps.h96
-rw-r--r--src/rps/test_service_rps_peers.c137
7 files changed, 1818 insertions, 2286 deletions
diff --git a/src/rps/.gitignore b/src/rps/.gitignore
index e45356eda..c8068912b 100644
--- a/src/rps/.gitignore
+++ b/src/rps/.gitignore
@@ -9,7 +9,6 @@ test_rps_seed_big
9test_rps_seed_request 9test_rps_seed_request
10test_rps_single_req 10test_rps_single_req
11test_service_rps_custommap 11test_service_rps_custommap
12test_service_rps_peers
13test_service_rps_sampler_elem 12test_service_rps_sampler_elem
14test_service_rps_view 13test_service_rps_view
15test_rps_churn 14test_rps_churn
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am
index 68424557b..de3469254 100644
--- a/src/rps/Makefile.am
+++ b/src/rps/Makefile.am
@@ -49,7 +49,6 @@ endif
49gnunet_service_rps_SOURCES = \ 49gnunet_service_rps_SOURCES = \
50 gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \ 50 gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \
51 gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \ 51 gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \
52 gnunet-service-rps_peers.h gnunet-service-rps_peers.c \
53 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ 52 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \
54 gnunet-service-rps_view.h gnunet-service-rps_view.c \ 53 gnunet-service-rps_view.h gnunet-service-rps_view.c \
55 rps-test_util.h rps-test_util.c \ 54 rps-test_util.h rps-test_util.c \
@@ -73,7 +72,6 @@ if HAVE_TESTING
73check_PROGRAMS = \ 72check_PROGRAMS = \
74 test_service_rps_view \ 73 test_service_rps_view \
75 test_service_rps_custommap \ 74 test_service_rps_custommap \
76 test_service_rps_peers \
77 test_service_rps_sampler_elem \ 75 test_service_rps_sampler_elem \
78 test_rps_malicious_1 \ 76 test_rps_malicious_1 \
79 test_rps_malicious_2 \ 77 test_rps_malicious_2 \
@@ -106,13 +104,6 @@ test_service_rps_view_SOURCES = \
106 test_service_rps_view.c 104 test_service_rps_view.c
107test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la 105test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la
108 106
109test_service_rps_peers_SOURCES = \
110 gnunet-service-rps_peers.h gnunet-service-rps_peers.c \
111 test_service_rps_peers.c
112test_service_rps_peers_LDADD = \
113 $(top_builddir)/src/util/libgnunetutil.la \
114 $(top_builddir)/src/cadet/libgnunetcadet.la
115
116test_service_rps_custommap_SOURCES = \ 107test_service_rps_custommap_SOURCES = \
117 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ 108 gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \
118 test_service_rps_custommap.c 109 test_service_rps_custommap.c
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index bea3df233..0b9e3e537 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -33,7 +33,6 @@
33#include "rps-test_util.h" 33#include "rps-test_util.h"
34#include "gnunet-service-rps_sampler.h" 34#include "gnunet-service-rps_sampler.h"
35#include "gnunet-service-rps_custommap.h" 35#include "gnunet-service-rps_custommap.h"
36#include "gnunet-service-rps_peers.h"
37#include "gnunet-service-rps_view.h" 36#include "gnunet-service-rps_view.h"
38 37
39#include <math.h> 38#include <math.h>
@@ -66,6 +65,1728 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
66static struct GNUNET_PeerIdentity own_identity; 65static struct GNUNET_PeerIdentity own_identity;
67 66
68 67
68
69/***********************************************************************
70 * Old gnunet-service-rps_peers.c
71***********************************************************************/
72
73/**
74 * Set a peer flag of given peer context.
75 */
76#define set_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
77
78/**
79 * Get peer flag of given peer context.
80 */
81#define check_peer_flag_set(peer_ctx, mask)\
82 ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
83
84/**
85 * Unset flag of given peer context.
86 */
87#define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
88
89/**
90 * Set a channel flag of given channel context.
91 */
92#define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask))
93
94/**
95 * Get channel flag of given channel context.
96 */
97#define check_channel_flag_set(channel_flags, mask)\
98 ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
99
100/**
101 * Unset flag of given channel context.
102 */
103#define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
104
105
106
107/**
108 * Pending operation on peer consisting of callback and closure
109 *
110 * When an operation cannot be executed right now this struct is used to store
111 * the callback and closure for later execution.
112 */
113struct PeerPendingOp
114{
115 /**
116 * Callback
117 */
118 PeerOp op;
119
120 /**
121 * Closure
122 */
123 void *op_cls;
124};
125
126/**
127 * List containing all messages that are yet to be send
128 *
129 * This is used to keep track of all messages that have not been sent yet. When
130 * a peer is to be removed the pending messages can be removed properly.
131 */
132struct PendingMessage
133{
134 /**
135 * DLL next, prev
136 */
137 struct PendingMessage *next;
138 struct PendingMessage *prev;
139
140 /**
141 * The envelope to the corresponding message
142 */
143 struct GNUNET_MQ_Envelope *ev;
144
145 /**
146 * The corresponding context
147 */
148 struct PeerContext *peer_ctx;
149
150 /**
151 * The message type
152 */
153 const char *type;
154};
155
156/**
157 * Struct used to keep track of other peer's status
158 *
159 * This is stored in a multipeermap.
160 * It contains information such as cadet channels, a message queue for sending,
161 * status about the channels, the pending operations on this peer and some flags
162 * about the status of the peer itself. (live, valid, ...)
163 */
164struct PeerContext
165{
166 /**
167 * Message queue open to client
168 */
169 struct GNUNET_MQ_Handle *mq;
170
171 /**
172 * Channel open to client.
173 */
174 struct GNUNET_CADET_Channel *send_channel;
175
176 /**
177 * Flags to the sending channel
178 */
179 uint32_t *send_channel_flags;
180
181 /**
182 * Channel open from client.
183 */
184 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
185
186 /**
187 * Flags to the receiving channel
188 */
189 uint32_t *recv_channel_flags;
190
191 /**
192 * Array of pending operations on this peer.
193 */
194 struct PeerPendingOp *pending_ops;
195
196 /**
197 * Handle to the callback given to cadet_ntfy_tmt_rdy()
198 *
199 * To be canceled on shutdown.
200 */
201 struct PendingMessage *liveliness_check_pending;
202
203 /**
204 * Number of pending operations.
205 */
206 unsigned int num_pending_ops;
207
208 /**
209 * Identity of the peer
210 */
211 struct GNUNET_PeerIdentity peer_id;
212
213 /**
214 * Flags indicating status of peer
215 */
216 uint32_t peer_flags;
217
218 /**
219 * Last time we received something from that peer.
220 */
221 struct GNUNET_TIME_Absolute last_message_recv;
222
223 /**
224 * Last time we received a keepalive message.
225 */
226 struct GNUNET_TIME_Absolute last_keepalive;
227
228 /**
229 * DLL with all messages that are yet to be sent
230 */
231 struct PendingMessage *pending_messages_head;
232 struct PendingMessage *pending_messages_tail;
233
234 /**
235 * This is pobably followed by 'statistical' data (when we first saw
236 * him, how did we get his ID, how many pushes (in a timeinterval),
237 * ...)
238 */
239};
240
241/**
242 * @brief Closure to #valid_peer_iterator
243 */
244struct PeersIteratorCls
245{
246 /**
247 * Iterator function
248 */
249 PeersIterator iterator;
250
251 /**
252 * Closure to iterator
253 */
254 void *cls;
255};
256
257/**
258 * @brief Hashmap of valid peers.
259 */
260static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
261
262/**
263 * @brief Maximum number of valid peers to keep.
264 * TODO read from config
265 */
266static uint32_t num_valid_peers_max = UINT32_MAX;
267
268/**
269 * @brief Filename of the file that stores the valid peers persistently.
270 */
271static char *filename_valid_peers;
272
273/**
274 * Set of all peers to keep track of them.
275 */
276static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
277
278/**
279 * Cadet handle.
280 */
281static struct GNUNET_CADET_Handle *cadet_handle;
282
283
284
285/**
286 * @brief Get the #PeerContext associated with a peer
287 *
288 * @param peer the peer id
289 *
290 * @return the #PeerContext
291 */
292static struct PeerContext *
293get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
294{
295 struct PeerContext *ctx;
296 int ret;
297
298 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
299 GNUNET_assert (GNUNET_YES == ret);
300 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
301 GNUNET_assert (NULL != ctx);
302 return ctx;
303}
304
305int
306Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer);
307
308/**
309 * @brief Create a new #PeerContext and insert it into the peer map
310 *
311 * @param peer the peer to create the #PeerContext for
312 *
313 * @return the #PeerContext
314 */
315static struct PeerContext *
316create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
317{
318 struct PeerContext *ctx;
319 int ret;
320
321 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
322
323 ctx = GNUNET_new (struct PeerContext);
324 ctx->peer_id = *peer;
325 ctx->send_channel_flags = GNUNET_new (uint32_t);
326 ctx->recv_channel_flags = GNUNET_new (uint32_t);
327 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
328 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
329 GNUNET_assert (GNUNET_OK == ret);
330 return ctx;
331}
332
333
334/**
335 * @brief Create or get a #PeerContext
336 *
337 * @param peer the peer to get the associated context to
338 *
339 * @return the context
340 */
341static struct PeerContext *
342create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
343{
344 if (GNUNET_NO == Peers_check_peer_known (peer))
345 {
346 return create_peer_ctx (peer);
347 }
348 return get_peer_ctx (peer);
349}
350
351void
352Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
353
354void
355Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
356
357/**
358 * @brief Check whether we have a connection to this @a peer
359 *
360 * Also sets the #Peers_ONLINE flag accordingly
361 *
362 * @param peer the peer in question
363 *
364 * @return #GNUNET_YES if we are connected
365 * #GNUNET_NO otherwise
366 */
367int
368Peers_check_connected (const struct GNUNET_PeerIdentity *peer)
369{
370 const struct PeerContext *peer_ctx;
371
372 /* If we don't know about this peer we don't know whether it's online */
373 if (GNUNET_NO == Peers_check_peer_known (peer))
374 {
375 return GNUNET_NO;
376 }
377 /* Get the context */
378 peer_ctx = get_peer_ctx (peer);
379 /* If we have no channel to this peer we don't know whether it's online */
380 if ( (NULL == peer_ctx->send_channel) &&
381 (NULL == peer_ctx->recv_channel) )
382 {
383 Peers_unset_peer_flag (peer, Peers_ONLINE);
384 return GNUNET_NO;
385 }
386 /* Otherwise (if we have a channel, we know that it's online */
387 Peers_set_peer_flag (peer, Peers_ONLINE);
388 return GNUNET_YES;
389}
390
391
392/**
393 * @brief The closure to #get_rand_peer_iterator.
394 */
395struct GetRandPeerIteratorCls
396{
397 /**
398 * @brief The index of the peer to return.
399 * Will be decreased until 0.
400 * Then current peer is returned.
401 */
402 uint32_t index;
403
404 /**
405 * @brief Pointer to peer to return.
406 */
407 const struct GNUNET_PeerIdentity *peer;
408};
409
410
411/**
412 * @brief Iterator function for #get_random_peer_from_peermap.
413 *
414 * Implements #GNUNET_CONTAINER_PeerMapIterator.
415 * Decreases the index until the index is null.
416 * Then returns the current peer.
417 *
418 * @param cls the #GetRandPeerIteratorCls containing index and peer
419 * @param peer current peer
420 * @param value unused
421 *
422 * @return #GNUNET_YES if we should continue to
423 * iterate,
424 * #GNUNET_NO if not.
425 */
426static int
427get_rand_peer_iterator (void *cls,
428 const struct GNUNET_PeerIdentity *peer,
429 void *value)
430{
431 struct GetRandPeerIteratorCls *iterator_cls = cls;
432 if (0 >= iterator_cls->index)
433 {
434 iterator_cls->peer = peer;
435 return GNUNET_NO;
436 }
437 iterator_cls->index--;
438 return GNUNET_YES;
439}
440
441
442/**
443 * @brief Get a random peer from @a peer_map
444 *
445 * @param peer_map the peer_map to get the peer from
446 *
447 * @return a random peer
448 */
449static const struct GNUNET_PeerIdentity *
450get_random_peer_from_peermap (const struct
451 GNUNET_CONTAINER_MultiPeerMap *peer_map)
452{
453 struct GetRandPeerIteratorCls *iterator_cls;
454 const struct GNUNET_PeerIdentity *ret;
455
456 iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
457 iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
458 GNUNET_CONTAINER_multipeermap_size (peer_map));
459 (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
460 get_rand_peer_iterator,
461 iterator_cls);
462 ret = iterator_cls->peer;
463 GNUNET_free (iterator_cls);
464 return ret;
465}
466
467
468/**
469 * @brief Add a given @a peer to valid peers.
470 *
471 * If valid peers are already #num_valid_peers_max, delete a peer previously.
472 *
473 * @param peer the peer that is added to the valid peers.
474 *
475 * @return #GNUNET_YES if no other peer had to be removed
476 * #GNUNET_NO otherwise
477 */
478static int
479add_valid_peer (const struct GNUNET_PeerIdentity *peer)
480{
481 const struct GNUNET_PeerIdentity *rand_peer;
482 int ret;
483
484 ret = GNUNET_YES;
485 while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
486 {
487 rand_peer = get_random_peer_from_peermap (valid_peers);
488 GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
489 ret = GNUNET_NO;
490 }
491 (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
492 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
493 return ret;
494}
495
496
497/**
498 * @brief Set the peer flag to living and
499 * call the pending operations on this peer.
500 *
501 * Also adds peer to #valid_peers.
502 *
503 * @param peer_ctx the #PeerContext of the peer to set live
504 */
505static void
506set_peer_live (struct PeerContext *peer_ctx)
507{
508 struct GNUNET_PeerIdentity *peer;
509 unsigned int i;
510
511 peer = &peer_ctx->peer_id;
512 LOG (GNUNET_ERROR_TYPE_DEBUG,
513 "Peer %s is live and valid, calling %i pending operations on it\n",
514 GNUNET_i2s (peer),
515 peer_ctx->num_pending_ops);
516
517 if (NULL != peer_ctx->liveliness_check_pending)
518 {
519 LOG (GNUNET_ERROR_TYPE_DEBUG,
520 "Removing pending liveliness check for peer %s\n",
521 GNUNET_i2s (&peer_ctx->peer_id));
522 // TODO wait until cadet sets mq->cancel_impl
523 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
524 GNUNET_free (peer_ctx->liveliness_check_pending);
525 peer_ctx->liveliness_check_pending = NULL;
526 }
527
528 (void) add_valid_peer (peer);
529 set_peer_flag (peer_ctx, Peers_ONLINE);
530
531 /* Call pending operations */
532 for (i = 0; i < peer_ctx->num_pending_ops; i++)
533 {
534 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
535 }
536 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
537}
538
539static void
540cleanup_destroyed_channel (void *cls,
541 const struct GNUNET_CADET_Channel *channel);
542
543/* Declaration of handlers */
544static void
545handle_peer_check (void *cls,
546 const struct GNUNET_MessageHeader *msg);
547
548static void
549handle_peer_push (void *cls,
550 const struct GNUNET_MessageHeader *msg);
551
552static void
553handle_peer_pull_request (void *cls,
554 const struct GNUNET_MessageHeader *msg);
555
556static int
557check_peer_pull_reply (void *cls,
558 const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
559
560static void
561handle_peer_pull_reply (void *cls,
562 const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
563
564/* End declaration of handlers */
565
566
567/**
568 * @brief Get the channel of a peer. If not existing, create.
569 *
570 * @param peer the peer id
571 * @return the #GNUNET_CADET_Channel used to send data to @a peer
572 */
573struct GNUNET_CADET_Channel *
574get_channel (const struct GNUNET_PeerIdentity *peer)
575{
576 struct PeerContext *peer_ctx;
577 struct GNUNET_HashCode port;
578 /* There exists a copy-paste-clone in run() */
579 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
580 GNUNET_MQ_hd_fixed_size (peer_check,
581 GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE,
582 struct GNUNET_MessageHeader,
583 NULL),
584 GNUNET_MQ_hd_fixed_size (peer_push,
585 GNUNET_MESSAGE_TYPE_RPS_PP_PUSH,
586 struct GNUNET_MessageHeader,
587 NULL),
588 GNUNET_MQ_hd_fixed_size (peer_pull_request,
589 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST,
590 struct GNUNET_MessageHeader,
591 NULL),
592 GNUNET_MQ_hd_var_size (peer_pull_reply,
593 GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY,
594 struct GNUNET_RPS_P2P_PullReplyMessage,
595 NULL),
596 GNUNET_MQ_handler_end ()
597 };
598
599
600 peer_ctx = get_peer_ctx (peer);
601 if (NULL == peer_ctx->send_channel)
602 {
603 LOG (GNUNET_ERROR_TYPE_DEBUG,
604 "Trying to establish channel to peer %s\n",
605 GNUNET_i2s (peer));
606 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
607 strlen (GNUNET_APPLICATION_PORT_RPS),
608 &port);
609 peer_ctx->send_channel =
610 GNUNET_CADET_channel_create (cadet_handle,
611 (struct GNUNET_PeerIdentity *) peer, /* context */
612 peer,
613 &port,
614 GNUNET_CADET_OPTION_RELIABLE,
615 NULL, /* WindowSize handler */
616 cleanup_destroyed_channel, /* Disconnect handler */
617 cadet_handlers);
618 }
619 GNUNET_assert (NULL != peer_ctx->send_channel);
620 return peer_ctx->send_channel;
621}
622
623
624/**
625 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
626 *
627 * If we already have a message queue open to this client,
628 * simply return it, otherways create one.
629 *
630 * @param peer the peer to get the mq to
631 * @return the #GNUNET_MQ_Handle
632 */
633static struct GNUNET_MQ_Handle *
634get_mq (const struct GNUNET_PeerIdentity *peer)
635{
636 struct PeerContext *peer_ctx;
637
638 peer_ctx = get_peer_ctx (peer);
639
640 if (NULL == peer_ctx->mq)
641 {
642 (void) get_channel (peer);
643 peer_ctx->mq = GNUNET_CADET_get_mq (peer_ctx->send_channel);
644 }
645 return peer_ctx->mq;
646}
647
648
649/**
650 * @brief This is called in response to the first message we sent as a
651 * liveliness check.
652 *
653 * @param cls #PeerContext of peer with pending liveliness check
654 */
655static void
656mq_liveliness_check_successful (void *cls)
657{
658 struct PeerContext *peer_ctx = cls;
659
660 if (NULL != peer_ctx->liveliness_check_pending)
661 {
662 LOG (GNUNET_ERROR_TYPE_DEBUG,
663 "Liveliness check for peer %s was successfull\n",
664 GNUNET_i2s (&peer_ctx->peer_id));
665 GNUNET_free (peer_ctx->liveliness_check_pending);
666 peer_ctx->liveliness_check_pending = NULL;
667 set_peer_live (peer_ctx);
668 }
669}
670
671/**
672 * Issue a check whether peer is live
673 *
674 * @param peer_ctx the context of the peer
675 */
676static void
677check_peer_live (struct PeerContext *peer_ctx)
678{
679 LOG (GNUNET_ERROR_TYPE_DEBUG,
680 "Get informed about peer %s getting live\n",
681 GNUNET_i2s (&peer_ctx->peer_id));
682
683 struct GNUNET_MQ_Handle *mq;
684 struct GNUNET_MQ_Envelope *ev;
685
686 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE);
687 peer_ctx->liveliness_check_pending = GNUNET_new (struct PendingMessage);
688 peer_ctx->liveliness_check_pending->ev = ev;
689 peer_ctx->liveliness_check_pending->peer_ctx = peer_ctx;
690 peer_ctx->liveliness_check_pending->type = "Check liveliness";
691 mq = get_mq (&peer_ctx->peer_id);
692 GNUNET_MQ_notify_sent (ev,
693 mq_liveliness_check_successful,
694 peer_ctx);
695 GNUNET_MQ_send (mq, ev);
696}
697
698/**
699 * @brief Add an envelope to a message passed to mq to list of pending messages
700 *
701 * @param peer peer the message was sent to
702 * @param ev envelope to the message
703 * @param type type of the message to be sent
704 * @return pointer to pending message
705 */
706static struct PendingMessage *
707insert_pending_message (const struct GNUNET_PeerIdentity *peer,
708 struct GNUNET_MQ_Envelope *ev,
709 const char *type)
710{
711 struct PendingMessage *pending_msg;
712 struct PeerContext *peer_ctx;
713
714 peer_ctx = get_peer_ctx (peer);
715 pending_msg = GNUNET_new (struct PendingMessage);
716 pending_msg->ev = ev;
717 pending_msg->peer_ctx = peer_ctx;
718 pending_msg->type = type;
719 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
720 peer_ctx->pending_messages_tail,
721 pending_msg);
722 return pending_msg;
723}
724
725
726/**
727 * @brief Remove a pending message from the respective DLL
728 *
729 * @param pending_msg the pending message to remove
730 * @param cancel cancel the pending message, too
731 */
732static void
733remove_pending_message (struct PendingMessage *pending_msg, int cancel)
734{
735 struct PeerContext *peer_ctx;
736
737 peer_ctx = pending_msg->peer_ctx;
738 GNUNET_assert (NULL != peer_ctx);
739 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
740 peer_ctx->pending_messages_tail,
741 pending_msg);
742 // TODO wait for the cadet implementation of message cancellation
743 //if (GNUNET_YES == cancel)
744 //{
745 // GNUNET_MQ_send_cancel (pending_msg->ev);
746 //}
747 GNUNET_free (pending_msg);
748}
749
750
751/**
752 * @brief Check whether function of type #PeerOp was already scheduled
753 *
754 * The array with pending operations will probably never grow really big, so
755 * iterating over it should be ok.
756 *
757 * @param peer the peer to check
758 * @param peer_op the operation (#PeerOp) on the peer
759 *
760 * @return #GNUNET_YES if this operation is scheduled on that peer
761 * #GNUNET_NO otherwise
762 */
763static int
764check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
765 const PeerOp peer_op)
766{
767 const struct PeerContext *peer_ctx;
768 unsigned int i;
769
770 peer_ctx = get_peer_ctx (peer);
771 for (i = 0; i < peer_ctx->num_pending_ops; i++)
772 if (peer_op == peer_ctx->pending_ops[i].op)
773 return GNUNET_YES;
774 return GNUNET_NO;
775}
776
777int
778Peers_remove_peer (const struct GNUNET_PeerIdentity *peer);
779
780/**
781 * Iterator over hash map entries. Deletes all contexts of peers.
782 *
783 * @param cls closure
784 * @param key current public key
785 * @param value value in the hash map
786 * @return #GNUNET_YES if we should continue to iterate,
787 * #GNUNET_NO if not.
788 */
789static int
790peermap_clear_iterator (void *cls,
791 const struct GNUNET_PeerIdentity *key,
792 void *value)
793{
794 Peers_remove_peer (key);
795 return GNUNET_YES;
796}
797
798
799/**
800 * @brief This is called once a message is sent.
801 *
802 * Removes the pending message
803 *
804 * @param cls type of the message that was sent
805 */
806static void
807mq_notify_sent_cb (void *cls)
808{
809 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
810 LOG (GNUNET_ERROR_TYPE_DEBUG,
811 "%s was sent.\n",
812 pending_msg->type);
813 /* Do not cancle message */
814 remove_pending_message (pending_msg, GNUNET_NO);
815}
816
817
818/**
819 * @brief Iterator function for #store_valid_peers.
820 *
821 * Implements #GNUNET_CONTAINER_PeerMapIterator.
822 * Writes single peer to disk.
823 *
824 * @param cls the file handle to write to.
825 * @param peer current peer
826 * @param value unused
827 *
828 * @return #GNUNET_YES if we should continue to
829 * iterate,
830 * #GNUNET_NO if not.
831 */
832static int
833store_peer_presistently_iterator (void *cls,
834 const struct GNUNET_PeerIdentity *peer,
835 void *value)
836{
837 const struct GNUNET_DISK_FileHandle *fh = cls;
838 char peer_string[128];
839 int size;
840 ssize_t ret;
841
842 if (NULL == peer)
843 {
844 return GNUNET_YES;
845 }
846 size = GNUNET_snprintf (peer_string,
847 sizeof (peer_string),
848 "%s\n",
849 GNUNET_i2s_full (peer));
850 GNUNET_assert (53 == size);
851 ret = GNUNET_DISK_file_write (fh,
852 peer_string,
853 size);
854 GNUNET_assert (size == ret);
855 return GNUNET_YES;
856}
857
858
859/**
860 * @brief Store the peers currently in #valid_peers to disk.
861 */
862static void
863store_valid_peers ()
864{
865 struct GNUNET_DISK_FileHandle *fh;
866 uint32_t number_written_peers;
867 int ret;
868
869 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
870 {
871 return;
872 }
873
874 ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers);
875 if (GNUNET_SYSERR == ret)
876 {
877 LOG (GNUNET_ERROR_TYPE_WARNING,
878 "Not able to create directory for file `%s'\n",
879 filename_valid_peers);
880 GNUNET_break (0);
881 }
882 else if (GNUNET_NO == ret)
883 {
884 LOG (GNUNET_ERROR_TYPE_WARNING,
885 "Directory for file `%s' exists but is not writable for us\n",
886 filename_valid_peers);
887 GNUNET_break (0);
888 }
889 fh = GNUNET_DISK_file_open (filename_valid_peers,
890 GNUNET_DISK_OPEN_WRITE |
891 GNUNET_DISK_OPEN_CREATE,
892 GNUNET_DISK_PERM_USER_READ |
893 GNUNET_DISK_PERM_USER_WRITE);
894 if (NULL == fh)
895 {
896 LOG (GNUNET_ERROR_TYPE_WARNING,
897 "Not able to write valid peers to file `%s'\n",
898 filename_valid_peers);
899 return;
900 }
901 LOG (GNUNET_ERROR_TYPE_DEBUG,
902 "Writing %u valid peers to disk\n",
903 GNUNET_CONTAINER_multipeermap_size (valid_peers));
904 number_written_peers =
905 GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
906 store_peer_presistently_iterator,
907 fh);
908 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
909 GNUNET_assert (number_written_peers ==
910 GNUNET_CONTAINER_multipeermap_size (valid_peers));
911}
912
913
914/**
915 * @brief Convert string representation of peer id to peer id.
916 *
917 * Counterpart to #GNUNET_i2s_full.
918 *
919 * @param string_repr The string representation of the peer id
920 *
921 * @return The peer id
922 */
923static const struct GNUNET_PeerIdentity *
924s2i_full (const char *string_repr)
925{
926 struct GNUNET_PeerIdentity *peer;
927 size_t len;
928 int ret;
929
930 peer = GNUNET_new (struct GNUNET_PeerIdentity);
931 len = strlen (string_repr);
932 if (52 > len)
933 {
934 LOG (GNUNET_ERROR_TYPE_WARNING,
935 "Not able to convert string representation of PeerID to PeerID\n"
936 "Sting representation: %s (len %lu) - too short\n",
937 string_repr,
938 len);
939 GNUNET_break (0);
940 }
941 else if (52 < len)
942 {
943 len = 52;
944 }
945 ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
946 len,
947 &peer->public_key);
948 if (GNUNET_OK != ret)
949 {
950 LOG (GNUNET_ERROR_TYPE_WARNING,
951 "Not able to convert string representation of PeerID to PeerID\n"
952 "Sting representation: %s\n",
953 string_repr);
954 GNUNET_break (0);
955 }
956 return peer;
957}
958
959
960/**
961 * @brief Restore the peers on disk to #valid_peers.
962 */
963static void
964restore_valid_peers ()
965{
966 off_t file_size;
967 uint32_t num_peers;
968 struct GNUNET_DISK_FileHandle *fh;
969 char *buf;
970 ssize_t size_read;
971 char *iter_buf;
972 char *str_repr;
973 const struct GNUNET_PeerIdentity *peer;
974
975 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
976 {
977 return;
978 }
979
980 if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers))
981 {
982 return;
983 }
984 fh = GNUNET_DISK_file_open (filename_valid_peers,
985 GNUNET_DISK_OPEN_READ,
986 GNUNET_DISK_PERM_NONE);
987 GNUNET_assert (NULL != fh);
988 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size));
989 num_peers = file_size / 53;
990 buf = GNUNET_malloc (file_size);
991 size_read = GNUNET_DISK_file_read (fh, buf, file_size);
992 GNUNET_assert (size_read == file_size);
993 LOG (GNUNET_ERROR_TYPE_DEBUG,
994 "Restoring %" PRIu32 " peers from file `%s'\n",
995 num_peers,
996 filename_valid_peers);
997 for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
998 {
999 str_repr = GNUNET_strndup (iter_buf, 53);
1000 peer = s2i_full (str_repr);
1001 GNUNET_free (str_repr);
1002 add_valid_peer (peer);
1003 LOG (GNUNET_ERROR_TYPE_DEBUG,
1004 "Restored valid peer %s from disk\n",
1005 GNUNET_i2s_full (peer));
1006 }
1007 iter_buf = NULL;
1008 GNUNET_free (buf);
1009 LOG (GNUNET_ERROR_TYPE_DEBUG,
1010 "num_peers: %" PRIu32 ", _size (valid_peers): %u\n",
1011 num_peers,
1012 GNUNET_CONTAINER_multipeermap_size (valid_peers));
1013 if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers))
1014 {
1015 LOG (GNUNET_ERROR_TYPE_WARNING,
1016 "Number of restored peers does not match file size. Have probably duplicates.\n");
1017 }
1018 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
1019 LOG (GNUNET_ERROR_TYPE_DEBUG,
1020 "Restored %u valid peers from disk\n",
1021 GNUNET_CONTAINER_multipeermap_size (valid_peers));
1022}
1023
1024
1025/**
1026 * @brief Initialise storage of peers
1027 *
1028 * @param fn_valid_peers filename of the file used to store valid peer ids
1029 * @param cadet_h cadet handle
1030 * @param disconnect_handler Disconnect handler
1031 * @param own_id own peer identity
1032 */
1033void
1034Peers_initialise (char* fn_valid_peers,
1035 struct GNUNET_CADET_Handle *cadet_h,
1036 GNUNET_CADET_DisconnectEventHandler disconnect_handler,
1037 const struct GNUNET_PeerIdentity *own_id)
1038{
1039 filename_valid_peers = GNUNET_strdup (fn_valid_peers);
1040 cadet_handle = cadet_h;
1041 own_identity = *own_id;
1042 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
1043 valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
1044 restore_valid_peers ();
1045}
1046
1047
1048/**
1049 * @brief Delete storage of peers that was created with #Peers_initialise ()
1050 */
1051void
1052Peers_terminate ()
1053{
1054 if (GNUNET_SYSERR ==
1055 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
1056 peermap_clear_iterator,
1057 NULL))
1058 {
1059 LOG (GNUNET_ERROR_TYPE_WARNING,
1060 "Iteration destroying peers was aborted.\n");
1061 }
1062 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1063 store_valid_peers ();
1064 GNUNET_free (filename_valid_peers);
1065 GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
1066}
1067
1068
1069/**
1070 * Iterator over #valid_peers hash map entries.
1071 *
1072 * @param cls closure - unused
1073 * @param peer current peer id
1074 * @param value value in the hash map - unused
1075 * @return #GNUNET_YES if we should continue to
1076 * iterate,
1077 * #GNUNET_NO if not.
1078 */
1079static int
1080valid_peer_iterator (void *cls,
1081 const struct GNUNET_PeerIdentity *peer,
1082 void *value)
1083{
1084 struct PeersIteratorCls *it_cls = cls;
1085
1086 return it_cls->iterator (it_cls->cls,
1087 peer);
1088}
1089
1090
1091/**
1092 * @brief Get all currently known, valid peer ids.
1093 *
1094 * @param it function to call on each peer id
1095 * @param it_cls extra argument to @a it
1096 * @return the number of key value pairs processed,
1097 * #GNUNET_SYSERR if it aborted iteration
1098 */
1099int
1100Peers_get_valid_peers (PeersIterator iterator,
1101 void *it_cls)
1102{
1103 struct PeersIteratorCls *cls;
1104 int ret;
1105
1106 cls = GNUNET_new (struct PeersIteratorCls);
1107 cls->iterator = iterator;
1108 cls->cls = it_cls;
1109 ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1110 valid_peer_iterator,
1111 cls);
1112 GNUNET_free (cls);
1113 return ret;
1114}
1115
1116
1117/**
1118 * @brief Add peer to known peers.
1119 *
1120 * This function is called on new peer_ids from 'external' sources
1121 * (client seed, cadet get_peers(), ...)
1122 *
1123 * @param peer the new #GNUNET_PeerIdentity
1124 *
1125 * @return #GNUNET_YES if peer was inserted
1126 * #GNUNET_NO otherwise (if peer was already known or
1127 * peer was #own_identity)
1128 */
1129int
1130Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
1131{
1132 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
1133 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity)) )
1134 {
1135 return GNUNET_NO; /* We already know this peer - nothing to do */
1136 }
1137 (void) create_peer_ctx (peer);
1138 return GNUNET_YES;
1139}
1140
1141int
1142Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
1143
1144/**
1145 * @brief Try connecting to a peer to see whether it is online
1146 *
1147 * If not known yet, insert into known peers
1148 *
1149 * @param peer the peer whose liveliness is to be checked
1150 * @return #GNUNET_YES if peer had to be inserted
1151 * #GNUNET_NO otherwise (if peer was already known or
1152 * peer was #own_identity)
1153 */
1154int
1155Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1156{
1157 struct PeerContext *peer_ctx;
1158 int ret;
1159
1160 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
1161 {
1162 return GNUNET_NO;
1163 }
1164 ret = Peers_insert_peer (peer);
1165 peer_ctx = get_peer_ctx (peer);
1166 if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE))
1167 {
1168 check_peer_live (peer_ctx);
1169 }
1170 return ret;
1171}
1172
1173
1174/**
1175 * @brief Check if peer is removable.
1176 *
1177 * Check if
1178 * - a recv channel exists
1179 * - there are pending messages
1180 * - there is no pending pull reply
1181 *
1182 * @param peer the peer in question
1183 * @return #GNUNET_YES if peer is removable
1184 * #GNUNET_NO if peer is NOT removable
1185 * #GNUNET_SYSERR if peer is not known
1186 */
1187int
1188Peers_check_removable (const struct GNUNET_PeerIdentity *peer)
1189{
1190 struct PeerContext *peer_ctx;
1191
1192 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1193 {
1194 return GNUNET_SYSERR;
1195 }
1196
1197 peer_ctx = get_peer_ctx (peer);
1198 if ( (NULL != peer_ctx->recv_channel) ||
1199 (NULL != peer_ctx->pending_messages_head) ||
1200 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
1201 {
1202 return GNUNET_NO;
1203 }
1204 return GNUNET_YES;
1205}
1206
1207uint32_t *
1208Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1209 enum Peers_ChannelRole role);
1210
1211int
1212Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
1213
1214/**
1215 * @brief Remove peer
1216 *
1217 * @param peer the peer to clean
1218 * @return #GNUNET_YES if peer was removed
1219 * #GNUNET_NO otherwise
1220 */
1221int
1222Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
1223{
1224 struct PeerContext *peer_ctx;
1225 uint32_t *channel_flag;
1226
1227 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1228 {
1229 return GNUNET_NO;
1230 }
1231
1232 peer_ctx = get_peer_ctx (peer);
1233 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
1234 LOG (GNUNET_ERROR_TYPE_DEBUG,
1235 "Going to remove peer %s\n",
1236 GNUNET_i2s (&peer_ctx->peer_id));
1237 Peers_unset_peer_flag (peer, Peers_ONLINE);
1238
1239 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
1240 while (NULL != peer_ctx->pending_messages_head)
1241 {
1242 LOG (GNUNET_ERROR_TYPE_DEBUG,
1243 "Removing unsent %s\n",
1244 peer_ctx->pending_messages_head->type);
1245 /* Cancle pending message, too */
1246 remove_pending_message (peer_ctx->pending_messages_head, GNUNET_YES);
1247 }
1248 /* If we are still waiting for notification whether this peer is live
1249 * cancel the according task */
1250 if (NULL != peer_ctx->liveliness_check_pending)
1251 {
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1253 "Removing pending liveliness check for peer %s\n",
1254 GNUNET_i2s (&peer_ctx->peer_id));
1255 // TODO wait until cadet sets mq->cancel_impl
1256 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
1257 GNUNET_free (peer_ctx->liveliness_check_pending);
1258 peer_ctx->liveliness_check_pending = NULL;
1259 }
1260 channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_SENDING);
1261 if (NULL != peer_ctx->send_channel &&
1262 GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING))
1263 {
1264 LOG (GNUNET_ERROR_TYPE_DEBUG,
1265 "Destroying send channel\n");
1266 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1267 peer_ctx->send_channel = NULL;
1268 }
1269 channel_flag = Peers_get_channel_flag (peer, Peers_CHANNEL_ROLE_RECEIVING);
1270 if (NULL != peer_ctx->recv_channel &&
1271 GNUNET_YES != Peers_check_channel_flag (channel_flag, Peers_CHANNEL_DESTROING))
1272 {
1273 LOG (GNUNET_ERROR_TYPE_DEBUG,
1274 "Destroying recv channel\n");
1275 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1276 peer_ctx->recv_channel = NULL;
1277 }
1278
1279 GNUNET_free (peer_ctx->send_channel_flags);
1280 GNUNET_free (peer_ctx->recv_channel_flags);
1281
1282 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
1283 {
1284 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
1285 }
1286 GNUNET_free (peer_ctx);
1287 return GNUNET_YES;
1288}
1289
1290
1291/**
1292 * @brief set flags on a given peer.
1293 *
1294 * @param peer the peer to set flags on
1295 * @param flags the flags
1296 */
1297void
1298Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1299{
1300 struct PeerContext *peer_ctx;
1301
1302 peer_ctx = get_peer_ctx (peer);
1303 set_peer_flag (peer_ctx, flags);
1304}
1305
1306
1307/**
1308 * @brief unset flags on a given peer.
1309 *
1310 * @param peer the peer to unset flags on
1311 * @param flags the flags
1312 */
1313void
1314Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1315{
1316 struct PeerContext *peer_ctx;
1317
1318 peer_ctx = get_peer_ctx (peer);
1319 unset_peer_flag (peer_ctx, flags);
1320}
1321
1322
1323/**
1324 * @brief Check whether flags on a peer are set.
1325 *
1326 * @param peer the peer to check the flag of
1327 * @param flags the flags to check
1328 *
1329 * @return #GNUNET_SYSERR if peer is not known
1330 * #GNUNET_YES if all given flags are set
1331 * #GNUNET_NO otherwise
1332 */
1333int
1334Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1335{
1336 struct PeerContext *peer_ctx;
1337
1338 if (GNUNET_NO == Peers_check_peer_known (peer))
1339 {
1340 return GNUNET_SYSERR;
1341 }
1342 peer_ctx = get_peer_ctx (peer);
1343 return check_peer_flag_set (peer_ctx, flags);
1344}
1345
1346
1347/**
1348 * @brief set flags on a given channel.
1349 *
1350 * @param channel the channel to set flags on
1351 * @param flags the flags
1352 */
1353void
1354Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1355{
1356 set_channel_flag (channel_flags, flags);
1357}
1358
1359
1360/**
1361 * @brief unset flags on a given channel.
1362 *
1363 * @param channel the channel to unset flags on
1364 * @param flags the flags
1365 */
1366void
1367Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1368{
1369 unset_channel_flag (channel_flags, flags);
1370}
1371
1372
1373/**
1374 * @brief Check whether flags on a channel are set.
1375 *
1376 * @param channel the channel to check the flag of
1377 * @param flags the flags to check
1378 *
1379 * @return #GNUNET_YES if all given flags are set
1380 * #GNUNET_NO otherwise
1381 */
1382int
1383Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1384{
1385 return check_channel_flag_set (channel_flags, flags);
1386}
1387
1388/**
1389 * @brief Get the flags for the channel in @a role for @a peer.
1390 *
1391 * @param peer Peer to get the channel flags for.
1392 * @param role Role of channel to get flags for
1393 *
1394 * @return The flags.
1395 */
1396uint32_t *
1397Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1398 enum Peers_ChannelRole role)
1399{
1400 const struct PeerContext *peer_ctx;
1401
1402 peer_ctx = get_peer_ctx (peer);
1403 if (Peers_CHANNEL_ROLE_SENDING == role)
1404 {
1405 return peer_ctx->send_channel_flags;
1406 }
1407 else if (Peers_CHANNEL_ROLE_RECEIVING == role)
1408 {
1409 return peer_ctx->recv_channel_flags;
1410 }
1411 else
1412 {
1413 GNUNET_assert (0);
1414 }
1415}
1416
1417/**
1418 * @brief Check whether we have information about the given peer.
1419 *
1420 * FIXME probably deprecated. Make this the new _online.
1421 *
1422 * @param peer peer in question
1423 *
1424 * @return #GNUNET_YES if peer is known
1425 * #GNUNET_NO if peer is not knwon
1426 */
1427int
1428Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
1429{
1430 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
1431}
1432
1433
1434/**
1435 * @brief Check whether @a peer is actually a peer.
1436 *
1437 * A valid peer is a peer that we know exists eg. we were connected to once.
1438 *
1439 * @param peer peer in question
1440 *
1441 * @return #GNUNET_YES if peer is valid
1442 * #GNUNET_NO if peer is not valid
1443 */
1444int
1445Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer)
1446{
1447 return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1448}
1449
1450
1451/**
1452 * @brief Indicate that we want to send to the other peer
1453 *
1454 * This establishes a sending channel
1455 *
1456 * @param peer the peer to establish channel to
1457 */
1458void
1459Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
1460{
1461 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1462 (void) get_channel (peer);
1463}
1464
1465
1466/**
1467 * @brief Check whether other peer has the intention to send/opened channel
1468 * towars us
1469 *
1470 * @param peer the peer in question
1471 *
1472 * @return #GNUNET_YES if peer has the intention to send
1473 * #GNUNET_NO otherwise
1474 */
1475int
1476Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
1477{
1478 const struct PeerContext *peer_ctx;
1479
1480 peer_ctx = get_peer_ctx (peer);
1481 if (NULL != peer_ctx->recv_channel)
1482 {
1483 return GNUNET_YES;
1484 }
1485 return GNUNET_NO;
1486}
1487
1488
1489/**
1490 * Handle the channel a peer opens to us.
1491 *
1492 * @param cls The closure
1493 * @param channel The channel the peer wants to establish
1494 * @param initiator The peer's peer ID
1495 *
1496 * @return initial channel context for the channel
1497 * (can be NULL -- that's not an error)
1498 */
1499void *
1500Peers_handle_inbound_channel (void *cls,
1501 struct GNUNET_CADET_Channel *channel,
1502 const struct GNUNET_PeerIdentity *initiator)
1503{
1504 struct PeerContext *peer_ctx;
1505
1506 LOG (GNUNET_ERROR_TYPE_DEBUG,
1507 "New channel was established to us (Peer %s).\n",
1508 GNUNET_i2s (initiator));
1509 GNUNET_assert (NULL != channel); /* according to cadet API */
1510 /* Make sure we 'know' about this peer */
1511 peer_ctx = create_or_get_peer_ctx (initiator);
1512 set_peer_live (peer_ctx);
1513 /* We only accept one incoming channel per peer */
1514 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
1515 {
1516 set_channel_flag (peer_ctx->recv_channel_flags,
1517 Peers_CHANNEL_ESTABLISHED_TWICE);
1518 GNUNET_CADET_channel_destroy (channel);
1519 /* return the channel context */
1520 return &peer_ctx->peer_id;
1521 }
1522 peer_ctx->recv_channel = channel;
1523 return &peer_ctx->peer_id;
1524}
1525
1526
1527/**
1528 * @brief Check whether a sending channel towards the given peer exists
1529 *
1530 * @param peer the peer to check for
1531 *
1532 * @return #GNUNET_YES if a sending channel towards that peer exists
1533 * #GNUNET_NO otherwise
1534 */
1535int
1536Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
1537{
1538 struct PeerContext *peer_ctx;
1539
1540 if (GNUNET_NO == Peers_check_peer_known (peer))
1541 { /* If no such peer exists, there is no channel */
1542 return GNUNET_NO;
1543 }
1544 peer_ctx = get_peer_ctx (peer);
1545 if (NULL == peer_ctx->send_channel)
1546 {
1547 return GNUNET_NO;
1548 }
1549 return GNUNET_YES;
1550}
1551
1552
1553/**
1554 * @brief check whether the given channel is the sending channel of the given
1555 * peer
1556 *
1557 * @param peer the peer in question
1558 * @param channel the channel to check for
1559 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
1560 * #Peers_CHANNEL_ROLE_RECEIVING
1561 *
1562 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
1563 * #GNUNET_NO otherwise
1564 */
1565int
1566Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
1567 const struct GNUNET_CADET_Channel *channel,
1568 enum Peers_ChannelRole role)
1569{
1570 const struct PeerContext *peer_ctx;
1571
1572 if (GNUNET_NO == Peers_check_peer_known (peer))
1573 {
1574 return GNUNET_NO;
1575 }
1576 peer_ctx = get_peer_ctx (peer);
1577 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
1578 (channel == peer_ctx->send_channel) )
1579 {
1580 return GNUNET_YES;
1581 }
1582 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
1583 (channel == peer_ctx->recv_channel) )
1584 {
1585 return GNUNET_YES;
1586 }
1587 return GNUNET_NO;
1588}
1589
1590
1591/**
1592 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
1593 * intention to another peer
1594 *
1595 * If there is also no channel to receive messages from that peer, remove it
1596 * from the peermap.
1597 * TODO really?
1598 *
1599 * @peer the peer identity of the peer whose sending channel to destroy
1600 * @return #GNUNET_YES if channel was destroyed
1601 * #GNUNET_NO otherwise
1602 */
1603int
1604Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1605{
1606 struct PeerContext *peer_ctx;
1607
1608 if (GNUNET_NO == Peers_check_peer_known (peer))
1609 {
1610 return GNUNET_NO;
1611 }
1612 peer_ctx = get_peer_ctx (peer);
1613 if (NULL != peer_ctx->send_channel)
1614 {
1615 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1616 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1617 peer_ctx->send_channel = NULL;
1618 (void) Peers_check_connected (peer);
1619 return GNUNET_YES;
1620 }
1621 return GNUNET_NO;
1622}
1623
1624/**
1625 * This is called when a channel is destroyed.
1626 *
1627 * @param cls The closure
1628 * @param channel The channel being closed
1629 * @param channel_ctx The context associated with this channel
1630 */
1631void
1632Peers_cleanup_destroyed_channel (void *cls,
1633 const struct GNUNET_CADET_Channel *channel)
1634{
1635 struct GNUNET_PeerIdentity *peer = cls;
1636 struct PeerContext *peer_ctx;
1637
1638 if (GNUNET_NO == Peers_check_peer_known (peer))
1639 {/* We don't want to implicitly create a context that we're about to kill */
1640 LOG (GNUNET_ERROR_TYPE_DEBUG,
1641 "channel (%s) without associated context was destroyed\n",
1642 GNUNET_i2s (peer));
1643 return;
1644 }
1645 peer_ctx = get_peer_ctx (peer);
1646
1647 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1648 * flag will be set. In this case simply make sure that the channels are
1649 * cleaned. */
1650 /* FIXME This distinction seems to be redundant */
1651 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1652 {/* We initiatad the destruction of this particular peer */
1653 if (channel == peer_ctx->send_channel)
1654 peer_ctx->send_channel = NULL;
1655 else if (channel == peer_ctx->recv_channel)
1656 peer_ctx->recv_channel = NULL;
1657
1658 if (NULL != peer_ctx->send_channel)
1659 {
1660 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1661 peer_ctx->send_channel = NULL;
1662 }
1663 if (NULL != peer_ctx->recv_channel)
1664 {
1665 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1666 peer_ctx->recv_channel = NULL;
1667 }
1668 /* Set the #Peers_ONLINE flag accordingly */
1669 (void) Peers_check_connected (peer);
1670 return;
1671 }
1672
1673 else
1674 { /* We did not initiate the destruction of this peer */
1675 if (channel == peer_ctx->send_channel)
1676 { /* Something (but us) killd the channel - clean up peer */
1677 LOG (GNUNET_ERROR_TYPE_DEBUG,
1678 "send channel (%s) was destroyed - cleaning up\n",
1679 GNUNET_i2s (peer));
1680 peer_ctx->send_channel = NULL;
1681 }
1682 else if (channel == peer_ctx->recv_channel)
1683 { /* Other peer doesn't want to send us messages anymore */
1684 LOG (GNUNET_ERROR_TYPE_DEBUG,
1685 "Peer %s destroyed recv channel - cleaning up channel\n",
1686 GNUNET_i2s (peer));
1687 peer_ctx->recv_channel = NULL;
1688 }
1689 else
1690 {
1691 LOG (GNUNET_ERROR_TYPE_WARNING,
1692 "unknown channel (%s) was destroyed\n",
1693 GNUNET_i2s (peer));
1694 }
1695 }
1696 (void) Peers_check_connected (peer);
1697}
1698
1699/**
1700 * @brief Send a message to another peer.
1701 *
1702 * Keeps track about pending messages so they can be properly removed when the
1703 * peer is destroyed.
1704 *
1705 * @param peer receeiver of the message
1706 * @param ev envelope of the message
1707 * @param type type of the message
1708 */
1709void
1710Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1711 struct GNUNET_MQ_Envelope *ev,
1712 const char *type)
1713{
1714 struct PendingMessage *pending_msg;
1715 struct GNUNET_MQ_Handle *mq;
1716
1717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1718 "Sending message to %s of type %s\n",
1719 GNUNET_i2s (peer),
1720 type);
1721 pending_msg = insert_pending_message (peer, ev, type);
1722 mq = get_mq (peer);
1723 GNUNET_MQ_notify_sent (ev,
1724 mq_notify_sent_cb,
1725 pending_msg);
1726 GNUNET_MQ_send (mq, ev);
1727}
1728
1729/**
1730 * @brief Schedule a operation on given peer
1731 *
1732 * Avoids scheduling an operation twice.
1733 *
1734 * @param peer the peer we want to schedule the operation for once it gets live
1735 *
1736 * @return #GNUNET_YES if the operation was scheduled
1737 * #GNUNET_NO otherwise
1738 */
1739int
1740Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1741 const PeerOp peer_op)
1742{
1743 struct PeerPendingOp pending_op;
1744 struct PeerContext *peer_ctx;
1745
1746 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, &own_identity))
1747 {
1748 return GNUNET_NO;
1749 }
1750 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1751
1752 //TODO if LIVE/ONLINE execute immediately
1753
1754 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1755 {
1756 peer_ctx = get_peer_ctx (peer);
1757 pending_op.op = peer_op;
1758 pending_op.op_cls = NULL;
1759 GNUNET_array_append (peer_ctx->pending_ops,
1760 peer_ctx->num_pending_ops,
1761 pending_op);
1762 return GNUNET_YES;
1763 }
1764 return GNUNET_NO;
1765}
1766
1767/**
1768 * @brief Get the recv_channel of @a peer.
1769 * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
1770 * messages.
1771 *
1772 * @param peer The peer to get the recv_channel from.
1773 *
1774 * @return The recv_channel.
1775 */
1776struct GNUNET_CADET_Channel *
1777Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer)
1778{
1779 struct PeerContext *peer_ctx;
1780
1781 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1782 peer_ctx = get_peer_ctx (peer);
1783 return peer_ctx->recv_channel;
1784}
1785/***********************************************************************
1786 * /Old gnunet-service-rps_peers.c
1787***********************************************************************/
1788
1789
69/*********************************************************************** 1790/***********************************************************************
70 * Housekeeping with clients 1791 * Housekeeping with clients
71***********************************************************************/ 1792***********************************************************************/
diff --git a/src/rps/gnunet-service-rps_peers.c b/src/rps/gnunet-service-rps_peers.c
deleted file mode 100644
index 933e3cb87..000000000
--- a/src/rps/gnunet-service-rps_peers.c
+++ /dev/null
@@ -1,1701 +0,0 @@
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_applications.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_cadet_service.h"
30#include <inttypes.h>
31#include "rps.h"
32#include "gnunet-service-rps_peers.h"
33
34
35
36#define LOG(kind, ...) GNUNET_log_from(kind,"rps-peers",__VA_ARGS__)
37
38
39/**
40 * Set a peer flag of given peer context.
41 */
42#define set_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
43
44/**
45 * Get peer flag of given peer context.
46 */
47#define check_peer_flag_set(peer_ctx, mask)\
48 ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
49
50/**
51 * Unset flag of given peer context.
52 */
53#define unset_peer_flag(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
54
55/**
56 * Set a channel flag of given channel context.
57 */
58#define set_channel_flag(channel_flags, mask) ((*channel_flags) |= (mask))
59
60/**
61 * Get channel flag of given channel context.
62 */
63#define check_channel_flag_set(channel_flags, mask)\
64 ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
65
66/**
67 * Unset flag of given channel context.
68 */
69#define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
70
71
72
73/**
74 * Pending operation on peer consisting of callback and closure
75 *
76 * When an operation cannot be executed right now this struct is used to store
77 * the callback and closure for later execution.
78 */
79struct PeerPendingOp
80{
81 /**
82 * Callback
83 */
84 PeerOp op;
85
86 /**
87 * Closure
88 */
89 void *op_cls;
90};
91
92/**
93 * List containing all messages that are yet to be send
94 *
95 * This is used to keep track of all messages that have not been sent yet. When
96 * a peer is to be removed the pending messages can be removed properly.
97 */
98struct PendingMessage
99{
100 /**
101 * DLL next, prev
102 */
103 struct PendingMessage *next;
104 struct PendingMessage *prev;
105
106 /**
107 * The envelope to the corresponding message
108 */
109 struct GNUNET_MQ_Envelope *ev;
110
111 /**
112 * The corresponding context
113 */
114 struct PeerContext *peer_ctx;
115
116 /**
117 * The message type
118 */
119 const char *type;
120};
121
122/**
123 * Struct used to keep track of other peer's status
124 *
125 * This is stored in a multipeermap.
126 * It contains information such as cadet channels, a message queue for sending,
127 * status about the channels, the pending operations on this peer and some flags
128 * about the status of the peer itself. (live, valid, ...)
129 */
130struct PeerContext
131{
132 /**
133 * Message queue open to client
134 */
135 struct GNUNET_MQ_Handle *mq;
136
137 /**
138 * Channel open to client.
139 */
140 struct GNUNET_CADET_Channel *send_channel;
141
142 /**
143 * Flags to the sending channel
144 */
145 uint32_t *send_channel_flags;
146
147 /**
148 * Channel open from client.
149 */
150 struct GNUNET_CADET_Channel *recv_channel; // unneeded?
151
152 /**
153 * Flags to the receiving channel
154 */
155 uint32_t *recv_channel_flags;
156
157 /**
158 * Array of pending operations on this peer.
159 */
160 struct PeerPendingOp *pending_ops;
161
162 /**
163 * Handle to the callback given to cadet_ntfy_tmt_rdy()
164 *
165 * To be canceled on shutdown.
166 */
167 struct PendingMessage *liveliness_check_pending;
168
169 /**
170 * Number of pending operations.
171 */
172 unsigned int num_pending_ops;
173
174 /**
175 * Identity of the peer
176 */
177 struct GNUNET_PeerIdentity peer_id;
178
179 /**
180 * Flags indicating status of peer
181 */
182 uint32_t peer_flags;
183
184 /**
185 * Last time we received something from that peer.
186 */
187 struct GNUNET_TIME_Absolute last_message_recv;
188
189 /**
190 * Last time we received a keepalive message.
191 */
192 struct GNUNET_TIME_Absolute last_keepalive;
193
194 /**
195 * DLL with all messages that are yet to be sent
196 */
197 struct PendingMessage *pending_messages_head;
198 struct PendingMessage *pending_messages_tail;
199
200 /**
201 * This is pobably followed by 'statistical' data (when we first saw
202 * him, how did we get his ID, how many pushes (in a timeinterval),
203 * ...)
204 */
205};
206
207/**
208 * @brief Closure to #valid_peer_iterator
209 */
210struct PeersIteratorCls
211{
212 /**
213 * Iterator function
214 */
215 PeersIterator iterator;
216
217 /**
218 * Closure to iterator
219 */
220 void *cls;
221};
222
223/**
224 * @brief Hashmap of valid peers.
225 */
226static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers;
227
228/**
229 * @brief Maximum number of valid peers to keep.
230 * TODO read from config
231 */
232static uint32_t num_valid_peers_max = UINT32_MAX;
233
234/**
235 * @brief Filename of the file that stores the valid peers persistently.
236 */
237static char *filename_valid_peers;
238
239/**
240 * Set of all peers to keep track of them.
241 */
242static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
243
244/**
245 * Own #GNUNET_PeerIdentity.
246 */
247static const struct GNUNET_PeerIdentity *own_identity;
248
249/**
250 * Cadet handle.
251 */
252static struct GNUNET_CADET_Handle *cadet_handle;
253
254/**
255 * @brief Disconnect handler
256 */
257static GNUNET_CADET_DisconnectEventHandler cleanup_destroyed_channel;
258
259/**
260 * @brief cadet handlers
261 */
262static const struct GNUNET_MQ_MessageHandler *cadet_handlers;
263
264
265
266/**
267 * @brief Get the #PeerContext associated with a peer
268 *
269 * @param peer the peer id
270 *
271 * @return the #PeerContext
272 */
273static struct PeerContext *
274get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
275{
276 struct PeerContext *ctx;
277 int ret;
278
279 ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
280 GNUNET_assert (GNUNET_YES == ret);
281 ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
282 GNUNET_assert (NULL != ctx);
283 return ctx;
284}
285
286
287/**
288 * @brief Create a new #PeerContext and insert it into the peer map
289 *
290 * @param peer the peer to create the #PeerContext for
291 *
292 * @return the #PeerContext
293 */
294static struct PeerContext *
295create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
296{
297 struct PeerContext *ctx;
298 int ret;
299
300 GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));
301
302 ctx = GNUNET_new (struct PeerContext);
303 ctx->peer_id = *peer;
304 ctx->send_channel_flags = GNUNET_new (uint32_t);
305 ctx->recv_channel_flags = GNUNET_new (uint32_t);
306 ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
307 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
308 GNUNET_assert (GNUNET_OK == ret);
309 return ctx;
310}
311
312
313/**
314 * @brief Create or get a #PeerContext
315 *
316 * @param peer the peer to get the associated context to
317 *
318 * @return the context
319 */
320static struct PeerContext *
321create_or_get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
322{
323 if (GNUNET_NO == Peers_check_peer_known (peer))
324 {
325 return create_peer_ctx (peer);
326 }
327 return get_peer_ctx (peer);
328}
329
330
331/**
332 * @brief Check whether we have a connection to this @a peer
333 *
334 * Also sets the #Peers_ONLINE flag accordingly
335 *
336 * @param peer the peer in question
337 *
338 * @return #GNUNET_YES if we are connected
339 * #GNUNET_NO otherwise
340 */
341int
342Peers_check_connected (const struct GNUNET_PeerIdentity *peer)
343{
344 const struct PeerContext *peer_ctx;
345
346 /* If we don't know about this peer we don't know whether it's online */
347 if (GNUNET_NO == Peers_check_peer_known (peer))
348 {
349 return GNUNET_NO;
350 }
351 /* Get the context */
352 peer_ctx = get_peer_ctx (peer);
353 /* If we have no channel to this peer we don't know whether it's online */
354 if ( (NULL == peer_ctx->send_channel) &&
355 (NULL == peer_ctx->recv_channel) )
356 {
357 Peers_unset_peer_flag (peer, Peers_ONLINE);
358 return GNUNET_NO;
359 }
360 /* Otherwise (if we have a channel, we know that it's online */
361 Peers_set_peer_flag (peer, Peers_ONLINE);
362 return GNUNET_YES;
363}
364
365
366/**
367 * @brief The closure to #get_rand_peer_iterator.
368 */
369struct GetRandPeerIteratorCls
370{
371 /**
372 * @brief The index of the peer to return.
373 * Will be decreased until 0.
374 * Then current peer is returned.
375 */
376 uint32_t index;
377
378 /**
379 * @brief Pointer to peer to return.
380 */
381 const struct GNUNET_PeerIdentity *peer;
382};
383
384
385/**
386 * @brief Iterator function for #get_random_peer_from_peermap.
387 *
388 * Implements #GNUNET_CONTAINER_PeerMapIterator.
389 * Decreases the index until the index is null.
390 * Then returns the current peer.
391 *
392 * @param cls the #GetRandPeerIteratorCls containing index and peer
393 * @param peer current peer
394 * @param value unused
395 *
396 * @return #GNUNET_YES if we should continue to
397 * iterate,
398 * #GNUNET_NO if not.
399 */
400static int
401get_rand_peer_iterator (void *cls,
402 const struct GNUNET_PeerIdentity *peer,
403 void *value)
404{
405 struct GetRandPeerIteratorCls *iterator_cls = cls;
406 if (0 >= iterator_cls->index)
407 {
408 iterator_cls->peer = peer;
409 return GNUNET_NO;
410 }
411 iterator_cls->index--;
412 return GNUNET_YES;
413}
414
415
416/**
417 * @brief Get a random peer from @a peer_map
418 *
419 * @param peer_map the peer_map to get the peer from
420 *
421 * @return a random peer
422 */
423static const struct GNUNET_PeerIdentity *
424get_random_peer_from_peermap (const struct
425 GNUNET_CONTAINER_MultiPeerMap *peer_map)
426{
427 struct GetRandPeerIteratorCls *iterator_cls;
428 const struct GNUNET_PeerIdentity *ret;
429
430 iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
431 iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
432 GNUNET_CONTAINER_multipeermap_size (peer_map));
433 (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
434 get_rand_peer_iterator,
435 iterator_cls);
436 ret = iterator_cls->peer;
437 GNUNET_free (iterator_cls);
438 return ret;
439}
440
441
442/**
443 * @brief Add a given @a peer to valid peers.
444 *
445 * If valid peers are already #num_valid_peers_max, delete a peer previously.
446 *
447 * @param peer the peer that is added to the valid peers.
448 *
449 * @return #GNUNET_YES if no other peer had to be removed
450 * #GNUNET_NO otherwise
451 */
452static int
453add_valid_peer (const struct GNUNET_PeerIdentity *peer)
454{
455 const struct GNUNET_PeerIdentity *rand_peer;
456 int ret;
457
458 ret = GNUNET_YES;
459 while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
460 {
461 rand_peer = get_random_peer_from_peermap (valid_peers);
462 GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
463 ret = GNUNET_NO;
464 }
465 (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
466 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
467 return ret;
468}
469
470
471/**
472 * @brief Set the peer flag to living and
473 * call the pending operations on this peer.
474 *
475 * Also adds peer to #valid_peers.
476 *
477 * @param peer_ctx the #PeerContext of the peer to set live
478 */
479static void
480set_peer_live (struct PeerContext *peer_ctx)
481{
482 struct GNUNET_PeerIdentity *peer;
483 unsigned int i;
484
485 peer = &peer_ctx->peer_id;
486 LOG (GNUNET_ERROR_TYPE_DEBUG,
487 "Peer %s is live and valid, calling %i pending operations on it\n",
488 GNUNET_i2s (peer),
489 peer_ctx->num_pending_ops);
490
491 if (NULL != peer_ctx->liveliness_check_pending)
492 {
493 LOG (GNUNET_ERROR_TYPE_DEBUG,
494 "Removing pending liveliness check for peer %s\n",
495 GNUNET_i2s (&peer_ctx->peer_id));
496 // TODO wait until cadet sets mq->cancel_impl
497 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
498 GNUNET_free (peer_ctx->liveliness_check_pending);
499 peer_ctx->liveliness_check_pending = NULL;
500 }
501
502 (void) add_valid_peer (peer);
503 set_peer_flag (peer_ctx, Peers_ONLINE);
504
505 /* Call pending operations */
506 for (i = 0; i < peer_ctx->num_pending_ops; i++)
507 {
508 peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
509 }
510 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
511}
512
513
514/**
515 * @brief Get the channel of a peer. If not existing, create.
516 *
517 * @param peer the peer id
518 * @return the #GNUNET_CADET_Channel used to send data to @a peer
519 */
520struct GNUNET_CADET_Channel *
521get_channel (const struct GNUNET_PeerIdentity *peer)
522{
523 struct PeerContext *peer_ctx;
524 struct GNUNET_HashCode port;
525
526 peer_ctx = get_peer_ctx (peer);
527 if (NULL == peer_ctx->send_channel)
528 {
529 LOG (GNUNET_ERROR_TYPE_DEBUG,
530 "Trying to establish channel to peer %s\n",
531 GNUNET_i2s (peer));
532 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS,
533 strlen (GNUNET_APPLICATION_PORT_RPS),
534 &port);
535 peer_ctx->send_channel =
536 GNUNET_CADET_channel_create (cadet_handle,
537 (struct GNUNET_PeerIdentity *) peer, /* context */
538 peer,
539 &port,
540 GNUNET_CADET_OPTION_RELIABLE,
541 NULL, /* WindowSize handler */
542 cleanup_destroyed_channel, /* Disconnect handler */
543 cadet_handlers);
544 }
545 GNUNET_assert (NULL != peer_ctx->send_channel);
546 return peer_ctx->send_channel;
547}
548
549
550/**
551 * Get the message queue (#GNUNET_MQ_Handle) of a specific peer.
552 *
553 * If we already have a message queue open to this client,
554 * simply return it, otherways create one.
555 *
556 * @param peer the peer to get the mq to
557 * @return the #GNUNET_MQ_Handle
558 */
559static struct GNUNET_MQ_Handle *
560get_mq (const struct GNUNET_PeerIdentity *peer)
561{
562 struct PeerContext *peer_ctx;
563
564 peer_ctx = get_peer_ctx (peer);
565
566 if (NULL == peer_ctx->mq)
567 {
568 (void) get_channel (peer);
569 peer_ctx->mq = GNUNET_CADET_get_mq (peer_ctx->send_channel);
570 }
571 return peer_ctx->mq;
572}
573
574
575/**
576 * @brief This is called in response to the first message we sent as a
577 * liveliness check.
578 *
579 * @param cls #PeerContext of peer with pending liveliness check
580 */
581static void
582mq_liveliness_check_successful (void *cls)
583{
584 struct PeerContext *peer_ctx = cls;
585
586 if (NULL != peer_ctx->liveliness_check_pending)
587 {
588 LOG (GNUNET_ERROR_TYPE_DEBUG,
589 "Liveliness check for peer %s was successfull\n",
590 GNUNET_i2s (&peer_ctx->peer_id));
591 GNUNET_free (peer_ctx->liveliness_check_pending);
592 peer_ctx->liveliness_check_pending = NULL;
593 set_peer_live (peer_ctx);
594 }
595}
596
597/**
598 * Issue a check whether peer is live
599 *
600 * @param peer_ctx the context of the peer
601 */
602static void
603check_peer_live (struct PeerContext *peer_ctx)
604{
605 LOG (GNUNET_ERROR_TYPE_DEBUG,
606 "Get informed about peer %s getting live\n",
607 GNUNET_i2s (&peer_ctx->peer_id));
608
609 struct GNUNET_MQ_Handle *mq;
610 struct GNUNET_MQ_Envelope *ev;
611
612 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE);
613 peer_ctx->liveliness_check_pending = GNUNET_new (struct PendingMessage);
614 peer_ctx->liveliness_check_pending->ev = ev;
615 peer_ctx->liveliness_check_pending->peer_ctx = peer_ctx;
616 peer_ctx->liveliness_check_pending->type = "Check liveliness";
617 mq = get_mq (&peer_ctx->peer_id);
618 GNUNET_MQ_notify_sent (ev,
619 mq_liveliness_check_successful,
620 peer_ctx);
621 GNUNET_MQ_send (mq, ev);
622}
623
624/**
625 * @brief Add an envelope to a message passed to mq to list of pending messages
626 *
627 * @param peer peer the message was sent to
628 * @param ev envelope to the message
629 * @param type type of the message to be sent
630 * @return pointer to pending message
631 */
632static struct PendingMessage *
633insert_pending_message (const struct GNUNET_PeerIdentity *peer,
634 struct GNUNET_MQ_Envelope *ev,
635 const char *type)
636{
637 struct PendingMessage *pending_msg;
638 struct PeerContext *peer_ctx;
639
640 peer_ctx = get_peer_ctx (peer);
641 pending_msg = GNUNET_new (struct PendingMessage);
642 pending_msg->ev = ev;
643 pending_msg->peer_ctx = peer_ctx;
644 pending_msg->type = type;
645 GNUNET_CONTAINER_DLL_insert (peer_ctx->pending_messages_head,
646 peer_ctx->pending_messages_tail,
647 pending_msg);
648 return pending_msg;
649}
650
651
652/**
653 * @brief Remove a pending message from the respective DLL
654 *
655 * @param pending_msg the pending message to remove
656 * @param cancel cancel the pending message, too
657 */
658static void
659remove_pending_message (struct PendingMessage *pending_msg, int cancel)
660{
661 struct PeerContext *peer_ctx;
662
663 peer_ctx = pending_msg->peer_ctx;
664 GNUNET_assert (NULL != peer_ctx);
665 GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head,
666 peer_ctx->pending_messages_tail,
667 pending_msg);
668 // TODO wait for the cadet implementation of message cancellation
669 //if (GNUNET_YES == cancel)
670 //{
671 // GNUNET_MQ_send_cancel (pending_msg->ev);
672 //}
673 GNUNET_free (pending_msg);
674}
675
676
677/**
678 * @brief Check whether function of type #PeerOp was already scheduled
679 *
680 * The array with pending operations will probably never grow really big, so
681 * iterating over it should be ok.
682 *
683 * @param peer the peer to check
684 * @param peer_op the operation (#PeerOp) on the peer
685 *
686 * @return #GNUNET_YES if this operation is scheduled on that peer
687 * #GNUNET_NO otherwise
688 */
689static int
690check_operation_scheduled (const struct GNUNET_PeerIdentity *peer,
691 const PeerOp peer_op)
692{
693 const struct PeerContext *peer_ctx;
694 unsigned int i;
695
696 peer_ctx = get_peer_ctx (peer);
697 for (i = 0; i < peer_ctx->num_pending_ops; i++)
698 if (peer_op == peer_ctx->pending_ops[i].op)
699 return GNUNET_YES;
700 return GNUNET_NO;
701}
702
703
704/**
705 * Iterator over hash map entries. Deletes all contexts of peers.
706 *
707 * @param cls closure
708 * @param key current public key
709 * @param value value in the hash map
710 * @return #GNUNET_YES if we should continue to iterate,
711 * #GNUNET_NO if not.
712 */
713static int
714peermap_clear_iterator (void *cls,
715 const struct GNUNET_PeerIdentity *key,
716 void *value)
717{
718 Peers_remove_peer (key);
719 return GNUNET_YES;
720}
721
722
723/**
724 * @brief This is called once a message is sent.
725 *
726 * Removes the pending message
727 *
728 * @param cls type of the message that was sent
729 */
730static void
731mq_notify_sent_cb (void *cls)
732{
733 struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
734 LOG (GNUNET_ERROR_TYPE_DEBUG,
735 "%s was sent.\n",
736 pending_msg->type);
737 /* Do not cancle message */
738 remove_pending_message (pending_msg, GNUNET_NO);
739}
740
741
742/**
743 * @brief Iterator function for #store_valid_peers.
744 *
745 * Implements #GNUNET_CONTAINER_PeerMapIterator.
746 * Writes single peer to disk.
747 *
748 * @param cls the file handle to write to.
749 * @param peer current peer
750 * @param value unused
751 *
752 * @return #GNUNET_YES if we should continue to
753 * iterate,
754 * #GNUNET_NO if not.
755 */
756static int
757store_peer_presistently_iterator (void *cls,
758 const struct GNUNET_PeerIdentity *peer,
759 void *value)
760{
761 const struct GNUNET_DISK_FileHandle *fh = cls;
762 char peer_string[128];
763 int size;
764 ssize_t ret;
765
766 if (NULL == peer)
767 {
768 return GNUNET_YES;
769 }
770 size = GNUNET_snprintf (peer_string,
771 sizeof (peer_string),
772 "%s\n",
773 GNUNET_i2s_full (peer));
774 GNUNET_assert (53 == size);
775 ret = GNUNET_DISK_file_write (fh,
776 peer_string,
777 size);
778 GNUNET_assert (size == ret);
779 return GNUNET_YES;
780}
781
782
783/**
784 * @brief Store the peers currently in #valid_peers to disk.
785 */
786static void
787store_valid_peers ()
788{
789 struct GNUNET_DISK_FileHandle *fh;
790 uint32_t number_written_peers;
791 int ret;
792
793 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
794 {
795 return;
796 }
797
798 ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers);
799 if (GNUNET_SYSERR == ret)
800 {
801 LOG (GNUNET_ERROR_TYPE_WARNING,
802 "Not able to create directory for file `%s'\n",
803 filename_valid_peers);
804 GNUNET_break (0);
805 }
806 else if (GNUNET_NO == ret)
807 {
808 LOG (GNUNET_ERROR_TYPE_WARNING,
809 "Directory for file `%s' exists but is not writable for us\n",
810 filename_valid_peers);
811 GNUNET_break (0);
812 }
813 fh = GNUNET_DISK_file_open (filename_valid_peers,
814 GNUNET_DISK_OPEN_WRITE |
815 GNUNET_DISK_OPEN_CREATE,
816 GNUNET_DISK_PERM_USER_READ |
817 GNUNET_DISK_PERM_USER_WRITE);
818 if (NULL == fh)
819 {
820 LOG (GNUNET_ERROR_TYPE_WARNING,
821 "Not able to write valid peers to file `%s'\n",
822 filename_valid_peers);
823 return;
824 }
825 LOG (GNUNET_ERROR_TYPE_DEBUG,
826 "Writing %u valid peers to disk\n",
827 GNUNET_CONTAINER_multipeermap_size (valid_peers));
828 number_written_peers =
829 GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
830 store_peer_presistently_iterator,
831 fh);
832 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
833 GNUNET_assert (number_written_peers ==
834 GNUNET_CONTAINER_multipeermap_size (valid_peers));
835}
836
837
838/**
839 * @brief Convert string representation of peer id to peer id.
840 *
841 * Counterpart to #GNUNET_i2s_full.
842 *
843 * @param string_repr The string representation of the peer id
844 *
845 * @return The peer id
846 */
847static const struct GNUNET_PeerIdentity *
848s2i_full (const char *string_repr)
849{
850 struct GNUNET_PeerIdentity *peer;
851 size_t len;
852 int ret;
853
854 peer = GNUNET_new (struct GNUNET_PeerIdentity);
855 len = strlen (string_repr);
856 if (52 > len)
857 {
858 LOG (GNUNET_ERROR_TYPE_WARNING,
859 "Not able to convert string representation of PeerID to PeerID\n"
860 "Sting representation: %s (len %u) - too short\n",
861 string_repr,
862 len);
863 GNUNET_break (0);
864 }
865 else if (52 < len)
866 {
867 len = 52;
868 }
869 ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
870 len,
871 &peer->public_key);
872 if (GNUNET_OK != ret)
873 {
874 LOG (GNUNET_ERROR_TYPE_WARNING,
875 "Not able to convert string representation of PeerID to PeerID\n"
876 "Sting representation: %s\n",
877 string_repr);
878 GNUNET_break (0);
879 }
880 return peer;
881}
882
883
884/**
885 * @brief Restore the peers on disk to #valid_peers.
886 */
887static void
888restore_valid_peers ()
889{
890 off_t file_size;
891 uint32_t num_peers;
892 struct GNUNET_DISK_FileHandle *fh;
893 char *buf;
894 ssize_t size_read;
895 char *iter_buf;
896 char *str_repr;
897 const struct GNUNET_PeerIdentity *peer;
898
899 if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
900 {
901 return;
902 }
903
904 if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers))
905 {
906 return;
907 }
908 fh = GNUNET_DISK_file_open (filename_valid_peers,
909 GNUNET_DISK_OPEN_READ,
910 GNUNET_DISK_PERM_NONE);
911 GNUNET_assert (NULL != fh);
912 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size));
913 num_peers = file_size / 53;
914 buf = GNUNET_malloc (file_size);
915 size_read = GNUNET_DISK_file_read (fh, buf, file_size);
916 GNUNET_assert (size_read == file_size);
917 LOG (GNUNET_ERROR_TYPE_DEBUG,
918 "Restoring %" PRIu32 " peers from file `%s'\n",
919 num_peers,
920 filename_valid_peers);
921 for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
922 {
923 str_repr = GNUNET_strndup (iter_buf, 53);
924 peer = s2i_full (str_repr);
925 GNUNET_free (str_repr);
926 add_valid_peer (peer);
927 LOG (GNUNET_ERROR_TYPE_DEBUG,
928 "Restored valid peer %s from disk\n",
929 GNUNET_i2s_full (peer));
930 }
931 iter_buf = NULL;
932 GNUNET_free (buf);
933 LOG (GNUNET_ERROR_TYPE_DEBUG,
934 "num_peers: %" PRIu32 ", _size (valid_peers): %u\n",
935 num_peers,
936 GNUNET_CONTAINER_multipeermap_size (valid_peers));
937 if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers))
938 {
939 LOG (GNUNET_ERROR_TYPE_WARNING,
940 "Number of restored peers does not match file size. Have probably duplicates.\n");
941 }
942 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
943 LOG (GNUNET_ERROR_TYPE_DEBUG,
944 "Restored %u valid peers from disk\n",
945 GNUNET_CONTAINER_multipeermap_size (valid_peers));
946}
947
948
949/**
950 * @brief Initialise storage of peers
951 *
952 * @param fn_valid_peers filename of the file used to store valid peer ids
953 * @param cadet_h cadet handle
954 * @param disconnect_handler Disconnect handler
955 * @param c_handlers cadet handlers
956 * @param own_id own peer identity
957 */
958void
959Peers_initialise (char* fn_valid_peers,
960 struct GNUNET_CADET_Handle *cadet_h,
961 GNUNET_CADET_DisconnectEventHandler disconnect_handler,
962 const struct GNUNET_MQ_MessageHandler *c_handlers,
963 const struct GNUNET_PeerIdentity *own_id)
964{
965 filename_valid_peers = GNUNET_strdup (fn_valid_peers);
966 cadet_handle = cadet_h;
967 cleanup_destroyed_channel = disconnect_handler;
968 cadet_handlers = c_handlers;
969 own_identity = own_id;
970 peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
971 valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
972 restore_valid_peers ();
973}
974
975
976/**
977 * @brief Delete storage of peers that was created with #Peers_initialise ()
978 */
979void
980Peers_terminate ()
981{
982 if (GNUNET_SYSERR ==
983 GNUNET_CONTAINER_multipeermap_iterate (peer_map,
984 peermap_clear_iterator,
985 NULL))
986 {
987 LOG (GNUNET_ERROR_TYPE_WARNING,
988 "Iteration destroying peers was aborted.\n");
989 }
990 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
991 store_valid_peers ();
992 GNUNET_free (filename_valid_peers);
993 GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
994}
995
996
997/**
998 * Iterator over #valid_peers hash map entries.
999 *
1000 * @param cls closure - unused
1001 * @param peer current peer id
1002 * @param value value in the hash map - unused
1003 * @return #GNUNET_YES if we should continue to
1004 * iterate,
1005 * #GNUNET_NO if not.
1006 */
1007static int
1008valid_peer_iterator (void *cls,
1009 const struct GNUNET_PeerIdentity *peer,
1010 void *value)
1011{
1012 struct PeersIteratorCls *it_cls = cls;
1013
1014 return it_cls->iterator (it_cls->cls,
1015 peer);
1016}
1017
1018
1019/**
1020 * @brief Get all currently known, valid peer ids.
1021 *
1022 * @param it function to call on each peer id
1023 * @param it_cls extra argument to @a it
1024 * @return the number of key value pairs processed,
1025 * #GNUNET_SYSERR if it aborted iteration
1026 */
1027int
1028Peers_get_valid_peers (PeersIterator iterator,
1029 void *it_cls)
1030{
1031 struct PeersIteratorCls *cls;
1032 int ret;
1033
1034 cls = GNUNET_new (struct PeersIteratorCls);
1035 cls->iterator = iterator;
1036 cls->cls = it_cls;
1037 ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1038 valid_peer_iterator,
1039 cls);
1040 GNUNET_free (cls);
1041 return ret;
1042}
1043
1044
1045/**
1046 * @brief Add peer to known peers.
1047 *
1048 * This function is called on new peer_ids from 'external' sources
1049 * (client seed, cadet get_peers(), ...)
1050 *
1051 * @param peer the new #GNUNET_PeerIdentity
1052 *
1053 * @return #GNUNET_YES if peer was inserted
1054 * #GNUNET_NO otherwise (if peer was already known or
1055 * peer was #own_identity)
1056 */
1057int
1058Peers_insert_peer (const struct GNUNET_PeerIdentity *peer)
1059{
1060 if ( (GNUNET_YES == Peers_check_peer_known (peer)) ||
1061 (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) )
1062 {
1063 return GNUNET_NO; /* We already know this peer - nothing to do */
1064 }
1065 (void) create_peer_ctx (peer);
1066 return GNUNET_YES;
1067}
1068
1069
1070/**
1071 * @brief Try connecting to a peer to see whether it is online
1072 *
1073 * If not known yet, insert into known peers
1074 *
1075 * @param peer the peer whose liveliness is to be checked
1076 * @return #GNUNET_YES if peer had to be inserted
1077 * #GNUNET_NO otherwise (if peer was already known or
1078 * peer was #own_identity)
1079 */
1080int
1081Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer)
1082{
1083 struct PeerContext *peer_ctx;
1084 int ret;
1085
1086 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1087 {
1088 return GNUNET_NO;
1089 }
1090 ret = Peers_insert_peer (peer);
1091 peer_ctx = get_peer_ctx (peer);
1092 if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE))
1093 {
1094 check_peer_live (peer_ctx);
1095 }
1096 return ret;
1097}
1098
1099
1100/**
1101 * @brief Check if peer is removable.
1102 *
1103 * Check if
1104 * - a recv channel exists
1105 * - there are pending messages
1106 * - there is no pending pull reply
1107 *
1108 * @param peer the peer in question
1109 * @return #GNUNET_YES if peer is removable
1110 * #GNUNET_NO if peer is NOT removable
1111 * #GNUNET_SYSERR if peer is not known
1112 */
1113int
1114Peers_check_removable (const struct GNUNET_PeerIdentity *peer)
1115{
1116 struct PeerContext *peer_ctx;
1117
1118 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1119 {
1120 return GNUNET_SYSERR;
1121 }
1122
1123 peer_ctx = get_peer_ctx (peer);
1124 if ( (NULL != peer_ctx->recv_channel) ||
1125 (NULL != peer_ctx->pending_messages_head) ||
1126 (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) )
1127 {
1128 return GNUNET_NO;
1129 }
1130 return GNUNET_YES;
1131}
1132
1133
1134/**
1135 * @brief Remove peer
1136 *
1137 * @param peer the peer to clean
1138 * @return #GNUNET_YES if peer was removed
1139 * #GNUNET_NO otherwise
1140 */
1141int
1142Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
1143{
1144 struct PeerContext *peer_ctx;
1145
1146 if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
1147 {
1148 return GNUNET_NO;
1149 }
1150
1151 peer_ctx = get_peer_ctx (peer);
1152 set_peer_flag (peer_ctx, Peers_TO_DESTROY);
1153 LOG (GNUNET_ERROR_TYPE_DEBUG,
1154 "Going to remove peer %s\n",
1155 GNUNET_i2s (&peer_ctx->peer_id));
1156 Peers_unset_peer_flag (peer, Peers_ONLINE);
1157
1158 GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
1159 while (NULL != peer_ctx->pending_messages_head)
1160 {
1161 LOG (GNUNET_ERROR_TYPE_DEBUG,
1162 "Removing unsent %s\n",
1163 peer_ctx->pending_messages_head->type);
1164 /* Cancle pending message, too */
1165 remove_pending_message (peer_ctx->pending_messages_head, GNUNET_YES);
1166 }
1167 /* If we are still waiting for notification whether this peer is live
1168 * cancel the according task */
1169 if (NULL != peer_ctx->liveliness_check_pending)
1170 {
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1172 "Removing pending liveliness check for peer %s\n",
1173 GNUNET_i2s (&peer_ctx->peer_id));
1174 // TODO wait until cadet sets mq->cancel_impl
1175 //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
1176 GNUNET_free (peer_ctx->liveliness_check_pending);
1177 peer_ctx->liveliness_check_pending = NULL;
1178 }
1179 if (NULL != peer_ctx->send_channel)
1180 {
1181 LOG (GNUNET_ERROR_TYPE_DEBUG,
1182 "Destroying send channel\n");
1183 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1184 peer_ctx->send_channel = NULL;
1185 }
1186 if (NULL != peer_ctx->recv_channel)
1187 {
1188 LOG (GNUNET_ERROR_TYPE_DEBUG,
1189 "Destroying recv channel\n");
1190 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1191 peer_ctx->recv_channel = NULL;
1192 }
1193
1194 GNUNET_free (peer_ctx->send_channel_flags);
1195 GNUNET_free (peer_ctx->recv_channel_flags);
1196
1197 if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
1198 {
1199 LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
1200 }
1201 GNUNET_free (peer_ctx);
1202 return GNUNET_YES;
1203}
1204
1205
1206/**
1207 * @brief set flags on a given peer.
1208 *
1209 * @param peer the peer to set flags on
1210 * @param flags the flags
1211 */
1212void
1213Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1214{
1215 struct PeerContext *peer_ctx;
1216
1217 peer_ctx = get_peer_ctx (peer);
1218 set_peer_flag (peer_ctx, flags);
1219}
1220
1221
1222/**
1223 * @brief unset flags on a given peer.
1224 *
1225 * @param peer the peer to unset flags on
1226 * @param flags the flags
1227 */
1228void
1229Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1230{
1231 struct PeerContext *peer_ctx;
1232
1233 peer_ctx = get_peer_ctx (peer);
1234 unset_peer_flag (peer_ctx, flags);
1235}
1236
1237
1238/**
1239 * @brief Check whether flags on a peer are set.
1240 *
1241 * @param peer the peer to check the flag of
1242 * @param flags the flags to check
1243 *
1244 * @return #GNUNET_SYSERR if peer is not known
1245 * #GNUNET_YES if all given flags are set
1246 * #GNUNET_NO otherwise
1247 */
1248int
1249Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
1250{
1251 struct PeerContext *peer_ctx;
1252
1253 if (GNUNET_NO == Peers_check_peer_known (peer))
1254 {
1255 return GNUNET_SYSERR;
1256 }
1257 peer_ctx = get_peer_ctx (peer);
1258 return check_peer_flag_set (peer_ctx, flags);
1259}
1260
1261
1262/**
1263 * @brief set flags on a given channel.
1264 *
1265 * @param channel the channel to set flags on
1266 * @param flags the flags
1267 */
1268void
1269Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1270{
1271 set_channel_flag (channel_flags, flags);
1272}
1273
1274
1275/**
1276 * @brief unset flags on a given channel.
1277 *
1278 * @param channel the channel to unset flags on
1279 * @param flags the flags
1280 */
1281void
1282Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1283{
1284 unset_channel_flag (channel_flags, flags);
1285}
1286
1287
1288/**
1289 * @brief Check whether flags on a channel are set.
1290 *
1291 * @param channel the channel to check the flag of
1292 * @param flags the flags to check
1293 *
1294 * @return #GNUNET_YES if all given flags are set
1295 * #GNUNET_NO otherwise
1296 */
1297int
1298Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags)
1299{
1300 return check_channel_flag_set (channel_flags, flags);
1301}
1302
1303/**
1304 * @brief Get the flags for the channel in @a role for @a peer.
1305 *
1306 * @param peer Peer to get the channel flags for.
1307 * @param role Role of channel to get flags for
1308 *
1309 * @return The flags.
1310 */
1311uint32_t *
1312Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1313 enum Peers_ChannelRole role)
1314{
1315 const struct PeerContext *peer_ctx;
1316
1317 peer_ctx = get_peer_ctx (peer);
1318 if (Peers_CHANNEL_ROLE_SENDING == role)
1319 {
1320 return peer_ctx->send_channel_flags;
1321 }
1322 else if (Peers_CHANNEL_ROLE_RECEIVING == role)
1323 {
1324 return peer_ctx->recv_channel_flags;
1325 }
1326 else
1327 {
1328 GNUNET_assert (0);
1329 }
1330}
1331
1332/**
1333 * @brief Check whether we have information about the given peer.
1334 *
1335 * FIXME probably deprecated. Make this the new _online.
1336 *
1337 * @param peer peer in question
1338 *
1339 * @return #GNUNET_YES if peer is known
1340 * #GNUNET_NO if peer is not knwon
1341 */
1342int
1343Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
1344{
1345 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
1346}
1347
1348
1349/**
1350 * @brief Check whether @a peer is actually a peer.
1351 *
1352 * A valid peer is a peer that we know exists eg. we were connected to once.
1353 *
1354 * @param peer peer in question
1355 *
1356 * @return #GNUNET_YES if peer is valid
1357 * #GNUNET_NO if peer is not valid
1358 */
1359int
1360Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer)
1361{
1362 return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1363}
1364
1365
1366/**
1367 * @brief Indicate that we want to send to the other peer
1368 *
1369 * This establishes a sending channel
1370 *
1371 * @param peer the peer to establish channel to
1372 */
1373void
1374Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer)
1375{
1376 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1377 (void) get_channel (peer);
1378}
1379
1380
1381/**
1382 * @brief Check whether other peer has the intention to send/opened channel
1383 * towars us
1384 *
1385 * @param peer the peer in question
1386 *
1387 * @return #GNUNET_YES if peer has the intention to send
1388 * #GNUNET_NO otherwise
1389 */
1390int
1391Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer)
1392{
1393 const struct PeerContext *peer_ctx;
1394
1395 peer_ctx = get_peer_ctx (peer);
1396 if (NULL != peer_ctx->recv_channel)
1397 {
1398 return GNUNET_YES;
1399 }
1400 return GNUNET_NO;
1401}
1402
1403
1404/**
1405 * Handle the channel a peer opens to us.
1406 *
1407 * @param cls The closure
1408 * @param channel The channel the peer wants to establish
1409 * @param initiator The peer's peer ID
1410 *
1411 * @return initial channel context for the channel
1412 * (can be NULL -- that's not an error)
1413 */
1414void *
1415Peers_handle_inbound_channel (void *cls,
1416 struct GNUNET_CADET_Channel *channel,
1417 const struct GNUNET_PeerIdentity *initiator)
1418{
1419 struct PeerContext *peer_ctx;
1420
1421 LOG (GNUNET_ERROR_TYPE_DEBUG,
1422 "New channel was established to us (Peer %s).\n",
1423 GNUNET_i2s (initiator));
1424 GNUNET_assert (NULL != channel); /* according to cadet API */
1425 /* Make sure we 'know' about this peer */
1426 peer_ctx = create_or_get_peer_ctx (initiator);
1427 set_peer_live (peer_ctx);
1428 /* We only accept one incoming channel per peer */
1429 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
1430 {
1431 set_channel_flag (peer_ctx->recv_channel_flags,
1432 Peers_CHANNEL_ESTABLISHED_TWICE);
1433 GNUNET_CADET_channel_destroy (channel);
1434 /* return the channel context */
1435 return &peer_ctx->peer_id;
1436 }
1437 peer_ctx->recv_channel = channel;
1438 return &peer_ctx->peer_id;
1439}
1440
1441
1442/**
1443 * @brief Check whether a sending channel towards the given peer exists
1444 *
1445 * @param peer the peer to check for
1446 *
1447 * @return #GNUNET_YES if a sending channel towards that peer exists
1448 * #GNUNET_NO otherwise
1449 */
1450int
1451Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer)
1452{
1453 struct PeerContext *peer_ctx;
1454
1455 if (GNUNET_NO == Peers_check_peer_known (peer))
1456 { /* If no such peer exists, there is no channel */
1457 return GNUNET_NO;
1458 }
1459 peer_ctx = get_peer_ctx (peer);
1460 if (NULL == peer_ctx->send_channel)
1461 {
1462 return GNUNET_NO;
1463 }
1464 return GNUNET_YES;
1465}
1466
1467
1468/**
1469 * @brief check whether the given channel is the sending channel of the given
1470 * peer
1471 *
1472 * @param peer the peer in question
1473 * @param channel the channel to check for
1474 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
1475 * #Peers_CHANNEL_ROLE_RECEIVING
1476 *
1477 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
1478 * #GNUNET_NO otherwise
1479 */
1480int
1481Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
1482 const struct GNUNET_CADET_Channel *channel,
1483 enum Peers_ChannelRole role)
1484{
1485 const struct PeerContext *peer_ctx;
1486
1487 if (GNUNET_NO == Peers_check_peer_known (peer))
1488 {
1489 return GNUNET_NO;
1490 }
1491 peer_ctx = get_peer_ctx (peer);
1492 if ( (Peers_CHANNEL_ROLE_SENDING == role) &&
1493 (channel == peer_ctx->send_channel) )
1494 {
1495 return GNUNET_YES;
1496 }
1497 if ( (Peers_CHANNEL_ROLE_RECEIVING == role) &&
1498 (channel == peer_ctx->recv_channel) )
1499 {
1500 return GNUNET_YES;
1501 }
1502 return GNUNET_NO;
1503}
1504
1505
1506/**
1507 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
1508 * intention to another peer
1509 *
1510 * If there is also no channel to receive messages from that peer, remove it
1511 * from the peermap.
1512 * TODO really?
1513 *
1514 * @peer the peer identity of the peer whose sending channel to destroy
1515 * @return #GNUNET_YES if channel was destroyed
1516 * #GNUNET_NO otherwise
1517 */
1518int
1519Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1520{
1521 struct PeerContext *peer_ctx;
1522
1523 if (GNUNET_NO == Peers_check_peer_known (peer))
1524 {
1525 return GNUNET_NO;
1526 }
1527 peer_ctx = get_peer_ctx (peer);
1528 if (NULL != peer_ctx->send_channel)
1529 {
1530 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1531 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1532 peer_ctx->send_channel = NULL;
1533 (void) Peers_check_connected (peer);
1534 return GNUNET_YES;
1535 }
1536 return GNUNET_NO;
1537}
1538
1539/**
1540 * This is called when a channel is destroyed.
1541 *
1542 * @param cls The closure
1543 * @param channel The channel being closed
1544 * @param channel_ctx The context associated with this channel
1545 */
1546void
1547Peers_cleanup_destroyed_channel (void *cls,
1548 const struct GNUNET_CADET_Channel *channel)
1549{
1550 struct GNUNET_PeerIdentity *peer = cls;
1551 struct PeerContext *peer_ctx;
1552
1553 if (GNUNET_NO == Peers_check_peer_known (peer))
1554 {/* We don't want to implicitly create a context that we're about to kill */
1555 LOG (GNUNET_ERROR_TYPE_DEBUG,
1556 "channel (%s) without associated context was destroyed\n",
1557 GNUNET_i2s (peer));
1558 return;
1559 }
1560 peer_ctx = get_peer_ctx (peer);
1561
1562 /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
1563 * flag will be set. In this case simply make sure that the channels are
1564 * cleaned. */
1565 /* FIXME This distinction seems to be redundant */
1566 if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
1567 {/* We initiatad the destruction of this particular peer */
1568 if (channel == peer_ctx->send_channel)
1569 peer_ctx->send_channel = NULL;
1570 else if (channel == peer_ctx->recv_channel)
1571 peer_ctx->recv_channel = NULL;
1572
1573 if (NULL != peer_ctx->send_channel)
1574 {
1575 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1576 peer_ctx->send_channel = NULL;
1577 }
1578 if (NULL != peer_ctx->recv_channel)
1579 {
1580 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1581 peer_ctx->recv_channel = NULL;
1582 }
1583 /* Set the #Peers_ONLINE flag accordingly */
1584 (void) Peers_check_connected (peer);
1585 return;
1586 }
1587
1588 else
1589 { /* We did not initiate the destruction of this peer */
1590 if (channel == peer_ctx->send_channel)
1591 { /* Something (but us) killd the channel - clean up peer */
1592 LOG (GNUNET_ERROR_TYPE_DEBUG,
1593 "send channel (%s) was destroyed - cleaning up\n",
1594 GNUNET_i2s (peer));
1595 peer_ctx->send_channel = NULL;
1596 }
1597 else if (channel == peer_ctx->recv_channel)
1598 { /* Other peer doesn't want to send us messages anymore */
1599 LOG (GNUNET_ERROR_TYPE_DEBUG,
1600 "Peer %s destroyed recv channel - cleaning up channel\n",
1601 GNUNET_i2s (peer));
1602 peer_ctx->recv_channel = NULL;
1603 }
1604 else
1605 {
1606 LOG (GNUNET_ERROR_TYPE_WARNING,
1607 "unknown channel (%s) was destroyed\n",
1608 GNUNET_i2s (peer));
1609 }
1610 }
1611 (void) Peers_check_connected (peer);
1612}
1613
1614/**
1615 * @brief Send a message to another peer.
1616 *
1617 * Keeps track about pending messages so they can be properly removed when the
1618 * peer is destroyed.
1619 *
1620 * @param peer receeiver of the message
1621 * @param ev envelope of the message
1622 * @param type type of the message
1623 */
1624void
1625Peers_send_message (const struct GNUNET_PeerIdentity *peer,
1626 struct GNUNET_MQ_Envelope *ev,
1627 const char *type)
1628{
1629 struct PendingMessage *pending_msg;
1630 struct GNUNET_MQ_Handle *mq;
1631
1632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1633 "Sending message to %s of type %s\n",
1634 GNUNET_i2s (peer),
1635 type);
1636 pending_msg = insert_pending_message (peer, ev, type);
1637 mq = get_mq (peer);
1638 GNUNET_MQ_notify_sent (ev,
1639 mq_notify_sent_cb,
1640 pending_msg);
1641 GNUNET_MQ_send (mq, ev);
1642}
1643
1644/**
1645 * @brief Schedule a operation on given peer
1646 *
1647 * Avoids scheduling an operation twice.
1648 *
1649 * @param peer the peer we want to schedule the operation for once it gets live
1650 *
1651 * @return #GNUNET_YES if the operation was scheduled
1652 * #GNUNET_NO otherwise
1653 */
1654int
1655Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
1656 const PeerOp peer_op)
1657{
1658 struct PeerPendingOp pending_op;
1659 struct PeerContext *peer_ctx;
1660
1661 if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity))
1662 {
1663 return GNUNET_NO;
1664 }
1665 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1666
1667 //TODO if LIVE/ONLINE execute immediately
1668
1669 if (GNUNET_NO == check_operation_scheduled (peer, peer_op))
1670 {
1671 peer_ctx = get_peer_ctx (peer);
1672 pending_op.op = peer_op;
1673 pending_op.op_cls = NULL;
1674 GNUNET_array_append (peer_ctx->pending_ops,
1675 peer_ctx->num_pending_ops,
1676 pending_op);
1677 return GNUNET_YES;
1678 }
1679 return GNUNET_NO;
1680}
1681
1682/**
1683 * @brief Get the recv_channel of @a peer.
1684 * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
1685 * messages.
1686 *
1687 * @param peer The peer to get the recv_channel from.
1688 *
1689 * @return The recv_channel.
1690 */
1691struct GNUNET_CADET_Channel *
1692Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer)
1693{
1694 struct PeerContext *peer_ctx;
1695
1696 GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer));
1697 peer_ctx = get_peer_ctx (peer);
1698 return peer_ctx->recv_channel;
1699}
1700
1701/* 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
deleted file mode 100644
index 15970a7ce..000000000
--- a/src/rps/gnunet-service-rps_peers.h
+++ /dev/null
@@ -1,437 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file rps/gnunet-service-rps_peers.h
23 * @brief utilities for managing (information about) peers
24 * @author Julius Bünger
25 */
26#include "gnunet_util_lib.h"
27#include <inttypes.h>
28#include "gnunet_cadet_service.h"
29
30
31/**
32 * Different flags indicating the status of another peer.
33 */
34enum Peers_PeerFlags
35{
36 /**
37 * If we are waiting for a reply from that peer (sent a pull request).
38 */
39 Peers_PULL_REPLY_PENDING = 0x01,
40
41 /* IN_OTHER_GOSSIP_LIST = 0x02, unneeded? */
42 /* IN_OWN_SAMPLER_LIST = 0x04, unneeded? */
43 /* IN_OWN_GOSSIP_LIST = 0x08, unneeded? */
44
45 /**
46 * We set this bit when we know the peer is online.
47 */
48 Peers_ONLINE = 0x20,
49
50 /**
51 * We set this bit when we are going to destroy the channel to this peer.
52 * When cleanup_channel is called, we know that we wanted to destroy it.
53 * Otherwise the channel to the other peer was destroyed.
54 */
55 Peers_TO_DESTROY = 0x40,
56};
57
58/**
59 * Keep track of the status of a channel.
60 *
61 * This is needed in order to know what to do with a channel when it's
62 * destroyed.
63 */
64enum Peers_ChannelFlags
65{
66 /**
67 * We destroyed the channel because the other peer established a second one.
68 */
69 Peers_CHANNEL_ESTABLISHED_TWICE = 0x1,
70
71 /**
72 * The channel was removed because it was not needed any more. This should be
73 * the sending channel.
74 */
75 Peers_CHANNEL_CLEAN = 0x2,
76};
77
78/**
79 * @brief The role of a channel. Sending or receiving.
80 */
81enum Peers_ChannelRole
82{
83 /**
84 * Channel is used for sending
85 */
86 Peers_CHANNEL_ROLE_SENDING = 0x01,
87
88 /**
89 * Channel is used for receiving
90 */
91 Peers_CHANNEL_ROLE_RECEIVING = 0x02,
92};
93
94/**
95 * @brief Functions of this type can be used to be stored at a peer for later execution.
96 *
97 * @param cls closure
98 * @param peer peer to execute function on
99 */
100typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer);
101
102/**
103 * @brief Iterator over valid peers.
104 *
105 * @param cls closure
106 * @param peer current public peer id
107 * @return #GNUNET_YES if we should continue to
108 * iterate,
109 * #GNUNET_NO if not.
110 */
111typedef int
112(*PeersIterator) (void *cls,
113 const struct GNUNET_PeerIdentity *peer);
114
115/**
116 * @brief Initialise storage of peers
117 *
118 * @param fn_valid_peers filename of the file used to store valid peer ids
119 * @param cadet_h cadet handle
120 * @param disconnect_handler Disconnect handler
121 * @param c_handlers cadet handlers
122 * @param own_id own peer identity
123 */
124void
125Peers_initialise (char* fn_valid_peers,
126 struct GNUNET_CADET_Handle *cadet_h,
127 GNUNET_CADET_DisconnectEventHandler disconnect_handler,
128 const struct GNUNET_MQ_MessageHandler *c_handlers,
129 const struct GNUNET_PeerIdentity *own_id);
130
131/**
132 * @brief Delete storage of peers that was created with #Peers_initialise ()
133 */
134void
135Peers_terminate ();
136
137
138/**
139 * @brief Get all currently known, valid peer ids.
140 *
141 * @param it function to call on each peer id
142 * @param it_cls extra argument to @a it
143 * @return the number of key value pairs processed,
144 * #GNUNET_SYSERR if it aborted iteration
145 */
146int
147Peers_get_valid_peers (PeersIterator iterator,
148 void *it_cls);
149
150/**
151 * @brief Add peer to known peers.
152 *
153 * This function is called on new peer_ids from 'external' sources
154 * (client seed, cadet get_peers(), ...)
155 *
156 * @param peer the new #GNUNET_PeerIdentity
157 *
158 * @return #GNUNET_YES if peer was inserted
159 * #GNUNET_NO otherwise (if peer was already known or
160 * peer was #own_identity)
161 */
162int
163Peers_insert_peer (const struct GNUNET_PeerIdentity *peer);
164
165/**
166 * @brief Try connecting to a peer to see whether it is online
167 *
168 * If not known yet, insert into known peers
169 *
170 * @param peer the peer whose liveliness is to be checked
171 * @return #GNUNET_YES if peer had to be inserted
172 * #GNUNET_NO otherwise (if peer was already known or
173 * peer was #own_identity)
174 */
175int
176Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer);
177
178/**
179 * @brief Check if peer is removable.
180 *
181 * Check if
182 * - a recv channel exists
183 * - there are pending messages
184 * - there is no pending pull reply
185 *
186 * @param peer the peer in question
187 * @return #GNUNET_YES if peer is removable
188 * #GNUNET_NO if peer is NOT removable
189 * #GNUNET_SYSERR if peer is not known
190 */
191int
192Peers_check_removable (const struct GNUNET_PeerIdentity *peer);
193
194/**
195 * @brief Remove peer
196 *
197 * @param peer the peer to clean
198 * @return #GNUNET_YES if peer was removed
199 * #GNUNET_NO otherwise
200 */
201int
202Peers_remove_peer (const struct GNUNET_PeerIdentity *peer);
203
204/**
205 * @brief set flags on a given peer.
206 *
207 * @param peer the peer to set flags on
208 * @param flags the flags
209 */
210void
211Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
212
213/**
214 * @brief unset flags on a given peer.
215 *
216 * @param peer the peer to unset flags on
217 * @param flags the flags
218 */
219void
220Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
221
222/**
223 * @brief Check whether flags on a peer are set.
224 *
225 * @param peer the peer to check the flag of
226 * @param flags the flags to check
227 *
228 * @return #GNUNET_YES if all given flags are set
229 * ##GNUNET_NO otherwise
230 */
231int
232Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags);
233
234
235/**
236 * @brief set flags on a given channel.
237 *
238 * @param channel the channel to set flags on
239 * @param flags the flags
240 */
241void
242Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
243
244/**
245 * @brief unset flags on a given channel.
246 *
247 * @param channel the channel to unset flags on
248 * @param flags the flags
249 */
250void
251Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
252
253/**
254 * @brief Check whether flags on a channel are set.
255 *
256 * @param channel the channel to check the flag of
257 * @param flags the flags to check
258 *
259 * @return #GNUNET_YES if all given flags are set
260 * #GNUNET_NO otherwise
261 */
262int
263Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags);
264
265/**
266 * @brief Get the flags for the channel in @a role for @a peer.
267 *
268 * @param peer Peer to get the channel flags for.
269 * @param role Role of channel to get flags for
270 *
271 * @return The flags.
272 */
273uint32_t *
274Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
275 enum Peers_ChannelRole role);
276
277/**
278 * @brief Check whether we have information about the given peer.
279 *
280 * FIXME probably deprecated. Make this the new _online.
281 *
282 * @param peer peer in question
283 *
284 * @return #GNUNET_YES if peer is known
285 * #GNUNET_NO if peer is not knwon
286 */
287int
288Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer);
289
290/**
291 * @brief Check whether @a peer is actually a peer.
292 *
293 * A valid peer is a peer that we know exists eg. we were connected to once.
294 *
295 * @param peer peer in question
296 *
297 * @return #GNUNET_YES if peer is valid
298 * #GNUNET_NO if peer is not valid
299 */
300int
301Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer);
302
303/**
304 * @brief Indicate that we want to send to the other peer
305 *
306 * This establishes a sending channel
307 *
308 * @param peer the peer to establish channel to
309 */
310void
311Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer);
312
313/**
314 * @brief Check whether other peer has the intention to send/opened channel
315 * towars us
316 *
317 * @param peer the peer in question
318 *
319 * @return #GNUNET_YES if peer has the intention to send
320 * #GNUNET_NO otherwise
321 */
322int
323Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer);
324
325/**
326 * Handle the channel a peer opens to us.
327 *
328 * @param cls The closure
329 * @param channel The channel the peer wants to establish
330 * @param initiator The peer's peer ID
331 *
332 * @return initial channel context for the channel
333 * (can be NULL -- that's not an error)
334 */
335void *
336Peers_handle_inbound_channel (void *cls,
337 struct GNUNET_CADET_Channel *channel,
338 const struct GNUNET_PeerIdentity *initiator);
339
340/**
341 * @brief Check whether a sending channel towards the given peer exists
342 *
343 * @param peer the peer to check for
344 *
345 * @return #GNUNET_YES if a sending channel towards that peer exists
346 * #GNUNET_NO otherwise
347 */
348int
349Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer);
350
351/**
352 * @brief check whether the given channel is the sending channel of the given
353 * peer
354 *
355 * @param peer the peer in question
356 * @param channel the channel to check for
357 * @param role either #Peers_CHANNEL_ROLE_SENDING, or
358 * #Peers_CHANNEL_ROLE_RECEIVING
359 *
360 * @return #GNUNET_YES if the given chennel is the sending channel of the peer
361 * #GNUNET_NO otherwise
362 */
363int
364Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer,
365 const struct GNUNET_CADET_Channel *channel,
366 enum Peers_ChannelRole role);
367
368/**
369 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
370 * intention to another peer
371 *
372 * If there is also no channel to receive messages from that peer, remove it
373 * from the peermap.
374 *
375 * @peer the peer identity of the peer whose sending channel to destroy
376 * @return #GNUNET_YES if channel was destroyed
377 * #GNUNET_NO otherwise
378 */
379int
380Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer);
381
382/**
383 * This is called when a channel is destroyed.
384 *
385 * Removes peer completely from our knowledge if the send_channel was destroyed
386 * Otherwise simply delete the recv_channel
387 *
388 * @param cls The closure
389 * @param channel The channel being closed
390 * @param channel_ctx The context associated with this channel
391 */
392void
393Peers_cleanup_destroyed_channel (void *cls,
394 const struct GNUNET_CADET_Channel *channel);
395
396/**
397 * @brief Send a message to another peer.
398 *
399 * Keeps track about pending messages so they can be properly removed when the
400 * peer is destroyed.
401 *
402 * @param peer receeiver of the message
403 * @param ev envelope of the message
404 * @param type type of the message
405 */
406void
407Peers_send_message (const struct GNUNET_PeerIdentity *peer,
408 struct GNUNET_MQ_Envelope *ev,
409 const char *type);
410
411/**
412 * @brief Schedule a operation on given peer
413 *
414 * Avoids scheduling an operation twice.
415 *
416 * @param peer the peer we want to schedule the operation for once it gets live
417 *
418 * @return #GNUNET_YES if the operation was scheduled
419 * #GNUNET_NO otherwise
420 */
421int
422Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer,
423 const PeerOp peer_op);
424
425/**
426 * @brief Get the recv_channel of @a peer.
427 * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming
428 * messages.
429 *
430 * @param peer The peer to get the recv_channel from.
431 *
432 * @return The recv_channel.
433 */
434struct GNUNET_CADET_Channel *
435Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer);
436
437/* end of gnunet-service-rps_peers.h */
diff --git a/src/rps/rps.h b/src/rps/rps.h
index 3037e2190..f5cc2e8d1 100644
--- a/src/rps/rps.h
+++ b/src/rps/rps.h
@@ -175,4 +175,100 @@ struct GNUNET_RPS_CS_ActMaliciousMessage
175}; 175};
176#endif /* ENABLE_MALICIOUS */ 176#endif /* ENABLE_MALICIOUS */
177 177
178
179/***********************************************************************
180 * Defines from old gnunet-service-rps_peers.h
181***********************************************************************/
182
183/**
184 * Different flags indicating the status of another peer.
185 */
186enum Peers_PeerFlags
187{
188 /**
189 * If we are waiting for a reply from that peer (sent a pull request).
190 */
191 Peers_PULL_REPLY_PENDING = 0x01,
192
193 /* IN_OTHER_GOSSIP_LIST = 0x02, unneeded? */
194 /* IN_OWN_SAMPLER_LIST = 0x04, unneeded? */
195 /* IN_OWN_GOSSIP_LIST = 0x08, unneeded? */
196
197 /**
198 * We set this bit when we know the peer is online.
199 */
200 Peers_ONLINE = 0x20,
201
202 /**
203 * We set this bit when we are going to destroy the channel to this peer.
204 * When cleanup_channel is called, we know that we wanted to destroy it.
205 * Otherwise the channel to the other peer was destroyed.
206 */
207 Peers_TO_DESTROY = 0x40,
208};
209
210/**
211 * Keep track of the status of a channel.
212 *
213 * This is needed in order to know what to do with a channel when it's
214 * destroyed.
215 */
216enum Peers_ChannelFlags
217{
218 /**
219 * We destroyed the channel because the other peer established a second one.
220 */
221 Peers_CHANNEL_ESTABLISHED_TWICE = 0x1,
222
223 /**
224 * The channel was removed because it was not needed any more. This should be
225 * the sending channel.
226 */
227 Peers_CHANNEL_CLEAN = 0x2,
228
229 /**
230 * We destroyed the channel because the other peer established a second one.
231 */
232 Peers_CHANNEL_DESTROING = 0x4,
233};
234
235
236/**
237 * @brief The role of a channel. Sending or receiving.
238 */
239enum Peers_ChannelRole
240{
241 /**
242 * Channel is used for sending
243 */
244 Peers_CHANNEL_ROLE_SENDING = 0x01,
245
246 /**
247 * Channel is used for receiving
248 */
249 Peers_CHANNEL_ROLE_RECEIVING = 0x02,
250};
251
252/**
253 * @brief Functions of this type can be used to be stored at a peer for later execution.
254 *
255 * @param cls closure
256 * @param peer peer to execute function on
257 */
258typedef void (* PeerOp) (void *cls, const struct GNUNET_PeerIdentity *peer);
259
260/**
261 * @brief Iterator over valid peers.
262 *
263 * @param cls closure
264 * @param peer current public peer id
265 * @return #GNUNET_YES if we should continue to
266 * iterate,
267 * #GNUNET_NO if not.
268 */
269typedef int
270(*PeersIterator) (void *cls,
271 const struct GNUNET_PeerIdentity *peer);
272
273
178GNUNET_NETWORK_STRUCT_END 274GNUNET_NETWORK_STRUCT_END
diff --git a/src/rps/test_service_rps_peers.c b/src/rps/test_service_rps_peers.c
deleted file mode 100644
index 9cd677fef..000000000
--- a/src/rps/test_service_rps_peers.c
+++ /dev/null
@@ -1,137 +0,0 @@
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 * @file rps/test_service_rps_peers.c
22 * @brief testcase for gnunet-service-rps_peers.c
23 */
24#include <platform.h>
25#include "gnunet-service-rps_peers.h"
26
27#define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); Peers_terminate (); return 1; }
28#define CHECK(c) { if (! (c)) ABORT(); }
29
30#define FN_VALID_PEERS "DISABLE"
31
32/**
33 * @brief Dummy implementation of #PeerOp (Operation on peer)
34 *
35 * @param cls closure
36 * @param peer peer
37 */
38void peer_op (void *cls, const struct GNUNET_PeerIdentity *peer)
39{
40 GNUNET_assert (NULL != peer);
41}
42
43/**
44 * @brief Function that is called on a peer for later execution
45 *
46 * @param cls closure
47 * @param peer peer to execute function upon
48 */
49void
50peer_op (void *cls, const struct GNUNET_PeerIdentity *peer);
51
52static int
53check ()
54{
55 struct GNUNET_PeerIdentity k1;
56 struct GNUNET_PeerIdentity own_id;
57
58 memset (&k1, 0, sizeof (k1));
59 memset (&own_id, 1, sizeof (own_id));
60
61 /* Do nothing */
62 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
63 Peers_terminate ();
64
65
66 /* Create peer */
67 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
68 CHECK (GNUNET_YES == Peers_insert_peer (&k1));
69 Peers_terminate ();
70
71
72 /* Create peer */
73 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
74 CHECK (GNUNET_YES == Peers_insert_peer (&k1));
75 CHECK (GNUNET_YES == Peers_remove_peer (&k1));
76 Peers_terminate ();
77
78
79 /* Insertion and Removal */
80 Peers_initialise (FN_VALID_PEERS, NULL, NULL, NULL, &own_id);
81 CHECK (GNUNET_NO == Peers_check_peer_known (&k1));
82
83 CHECK (GNUNET_YES == Peers_insert_peer (&k1));
84 CHECK (GNUNET_NO == Peers_insert_peer (&k1));
85 CHECK (GNUNET_YES == Peers_check_peer_known (&k1));
86
87 CHECK (GNUNET_YES == Peers_remove_peer (&k1));
88 CHECK (GNUNET_NO == Peers_remove_peer (&k1));
89 CHECK (GNUNET_NO == Peers_check_peer_known (&k1));
90
91
92 /* Flags */
93 Peers_insert_peer (&k1);
94
95 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_PULL_REPLY_PENDING));
96 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_ONLINE));
97 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
98
99 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_ONLINE));
100
101 Peers_set_peer_flag (&k1, Peers_ONLINE);
102 CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_ONLINE));
103 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
104 CHECK (GNUNET_YES == Peers_check_peer_flag (&k1, Peers_ONLINE));
105 CHECK (GNUNET_NO == Peers_check_peer_flag (&k1, Peers_TO_DESTROY));
106
107 /* Check send intention */
108 CHECK (GNUNET_NO == Peers_check_peer_send_intention (&k1));
109
110 /* Check existence of sending channel */
111 CHECK (GNUNET_NO == Peers_check_sending_channel_exists (&k1));
112
113 /* Check role of channels */
114 CHECK (GNUNET_YES == Peers_check_channel_role (&k1,
115 NULL,
116 Peers_CHANNEL_ROLE_SENDING));
117 CHECK (GNUNET_YES == Peers_check_channel_role (&k1,
118 NULL,
119 Peers_CHANNEL_ROLE_RECEIVING));
120
121 CHECK (GNUNET_YES == Peers_schedule_operation (&k1, peer_op));
122
123 Peers_terminate ();
124 return 0;
125}
126
127
128int
129main (int argc, char *argv[])
130{
131 GNUNET_log_setup ("test_service_rps_peers",
132 "WARNING",
133 NULL);
134 return check ();
135}
136
137/* end of test_service_rps_peers.c */