diff options
author | Julius Bünger <buenger@mytum.de> | 2017-12-29 15:37:48 +0100 |
---|---|---|
committer | Julius Bünger <buenger@mytum.de> | 2017-12-29 15:37:48 +0100 |
commit | f2b64da6fd07c3a20c8f202fa8920f9f2e96e51e (patch) | |
tree | 2d774cf2c02dc6b3d49e3fdcbe7eabc41512744f /src | |
parent | c6f178907d4f1ef53a53ed85e12521d07ba4d08e (diff) | |
download | gnunet-f2b64da6fd07c3a20c8f202fa8920f9f2e96e51e.tar.gz gnunet-f2b64da6fd07c3a20c8f202fa8920f9f2e96e51e.zip |
refactor rps code
Diffstat (limited to 'src')
-rw-r--r-- | src/rps/.gitignore | 1 | ||||
-rw-r--r-- | src/rps/Makefile.am | 9 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps.c | 1723 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_peers.c | 1701 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_peers.h | 437 | ||||
-rw-r--r-- | src/rps/rps.h | 96 | ||||
-rw-r--r-- | src/rps/test_service_rps_peers.c | 137 |
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 | |||
9 | test_rps_seed_request | 9 | test_rps_seed_request |
10 | test_rps_single_req | 10 | test_rps_single_req |
11 | test_service_rps_custommap | 11 | test_service_rps_custommap |
12 | test_service_rps_peers | ||
13 | test_service_rps_sampler_elem | 12 | test_service_rps_sampler_elem |
14 | test_service_rps_view | 13 | test_service_rps_view |
15 | test_rps_churn | 14 | test_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 | |||
49 | gnunet_service_rps_SOURCES = \ | 49 | gnunet_service_rps_SOURCES = \ |
50 | gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \ | 50 | gnunet-service-rps_sampler_elem.h gnunet-service-rps_sampler_elem.c \ |
51 | gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \ | 51 | gnunet-service-rps_sampler.h gnunet-service-rps_sampler.c \ |
52 | gnunet-service-rps_peers.h gnunet-service-rps_peers.c \ | ||
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 | |||
73 | check_PROGRAMS = \ | 72 | check_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 |
107 | test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la | 105 | test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la |
108 | 106 | ||
109 | test_service_rps_peers_SOURCES = \ | ||
110 | gnunet-service-rps_peers.h gnunet-service-rps_peers.c \ | ||
111 | test_service_rps_peers.c | ||
112 | test_service_rps_peers_LDADD = \ | ||
113 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
114 | $(top_builddir)/src/cadet/libgnunetcadet.la | ||
115 | |||
116 | test_service_rps_custommap_SOURCES = \ | 107 | test_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; | |||
66 | static struct GNUNET_PeerIdentity own_identity; | 65 | static 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 | */ | ||
113 | struct 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 | */ | ||
132 | struct 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 | */ | ||
164 | struct 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 | */ | ||
244 | struct 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 | */ | ||
260 | static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers; | ||
261 | |||
262 | /** | ||
263 | * @brief Maximum number of valid peers to keep. | ||
264 | * TODO read from config | ||
265 | */ | ||
266 | static uint32_t num_valid_peers_max = UINT32_MAX; | ||
267 | |||
268 | /** | ||
269 | * @brief Filename of the file that stores the valid peers persistently. | ||
270 | */ | ||
271 | static char *filename_valid_peers; | ||
272 | |||
273 | /** | ||
274 | * Set of all peers to keep track of them. | ||
275 | */ | ||
276 | static struct GNUNET_CONTAINER_MultiPeerMap *peer_map; | ||
277 | |||
278 | /** | ||
279 | * Cadet handle. | ||
280 | */ | ||
281 | static 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 | */ | ||
292 | static struct PeerContext * | ||
293 | get_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 | |||
305 | int | ||
306 | Peers_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 | */ | ||
315 | static struct PeerContext * | ||
316 | create_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 | */ | ||
341 | static struct PeerContext * | ||
342 | create_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 | |||
351 | void | ||
352 | Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags); | ||
353 | |||
354 | void | ||
355 | Peers_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 | */ | ||
367 | int | ||
368 | Peers_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 | */ | ||
395 | struct 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 | */ | ||
426 | static int | ||
427 | get_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 | */ | ||
449 | static const struct GNUNET_PeerIdentity * | ||
450 | get_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 | */ | ||
478 | static int | ||
479 | add_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 | */ | ||
505 | static void | ||
506 | set_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 | |||
539 | static void | ||
540 | cleanup_destroyed_channel (void *cls, | ||
541 | const struct GNUNET_CADET_Channel *channel); | ||
542 | |||
543 | /* Declaration of handlers */ | ||
544 | static void | ||
545 | handle_peer_check (void *cls, | ||
546 | const struct GNUNET_MessageHeader *msg); | ||
547 | |||
548 | static void | ||
549 | handle_peer_push (void *cls, | ||
550 | const struct GNUNET_MessageHeader *msg); | ||
551 | |||
552 | static void | ||
553 | handle_peer_pull_request (void *cls, | ||
554 | const struct GNUNET_MessageHeader *msg); | ||
555 | |||
556 | static int | ||
557 | check_peer_pull_reply (void *cls, | ||
558 | const struct GNUNET_RPS_P2P_PullReplyMessage *msg); | ||
559 | |||
560 | static void | ||
561 | handle_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 | */ | ||
573 | struct GNUNET_CADET_Channel * | ||
574 | get_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 | */ | ||
633 | static struct GNUNET_MQ_Handle * | ||
634 | get_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 | */ | ||
655 | static void | ||
656 | mq_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 | */ | ||
676 | static void | ||
677 | check_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 | */ | ||
706 | static struct PendingMessage * | ||
707 | insert_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 | */ | ||
732 | static void | ||
733 | remove_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 | */ | ||
763 | static int | ||
764 | check_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 | |||
777 | int | ||
778 | Peers_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 | */ | ||
789 | static int | ||
790 | peermap_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 | */ | ||
806 | static void | ||
807 | mq_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 | */ | ||
832 | static int | ||
833 | store_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 | */ | ||
862 | static void | ||
863 | store_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 | */ | ||
923 | static const struct GNUNET_PeerIdentity * | ||
924 | s2i_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 | */ | ||
963 | static void | ||
964 | restore_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 | */ | ||
1033 | void | ||
1034 | Peers_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 | */ | ||
1051 | void | ||
1052 | Peers_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 | */ | ||
1079 | static int | ||
1080 | valid_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 | */ | ||
1099 | int | ||
1100 | Peers_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 | */ | ||
1129 | int | ||
1130 | Peers_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 | |||
1141 | int | ||
1142 | Peers_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 | */ | ||
1154 | int | ||
1155 | Peers_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 | */ | ||
1187 | int | ||
1188 | Peers_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 | |||
1207 | uint32_t * | ||
1208 | Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer, | ||
1209 | enum Peers_ChannelRole role); | ||
1210 | |||
1211 | int | ||
1212 | Peers_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 | */ | ||
1221 | int | ||
1222 | Peers_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 | */ | ||
1297 | void | ||
1298 | Peers_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 | */ | ||
1313 | void | ||
1314 | Peers_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 | */ | ||
1333 | int | ||
1334 | Peers_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 | */ | ||
1353 | void | ||
1354 | Peers_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 | */ | ||
1366 | void | ||
1367 | Peers_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 | */ | ||
1382 | int | ||
1383 | Peers_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 | */ | ||
1396 | uint32_t * | ||
1397 | Peers_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 | */ | ||
1427 | int | ||
1428 | Peers_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 | */ | ||
1444 | int | ||
1445 | Peers_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 | */ | ||
1458 | void | ||
1459 | Peers_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 | */ | ||
1475 | int | ||
1476 | Peers_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 | */ | ||
1499 | void * | ||
1500 | Peers_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 | */ | ||
1535 | int | ||
1536 | Peers_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 | */ | ||
1565 | int | ||
1566 | Peers_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 | */ | ||
1603 | int | ||
1604 | Peers_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 | */ | ||
1631 | void | ||
1632 | Peers_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 | */ | ||
1709 | void | ||
1710 | Peers_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 | */ | ||
1739 | int | ||
1740 | Peers_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 | */ | ||
1776 | struct GNUNET_CADET_Channel * | ||
1777 | Peers_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 | */ | ||
79 | struct 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 | */ | ||
98 | struct 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 | */ | ||
130 | struct 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 | */ | ||
210 | struct 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 | */ | ||
226 | static struct GNUNET_CONTAINER_MultiPeerMap *valid_peers; | ||
227 | |||
228 | /** | ||
229 | * @brief Maximum number of valid peers to keep. | ||
230 | * TODO read from config | ||
231 | */ | ||
232 | static uint32_t num_valid_peers_max = UINT32_MAX; | ||
233 | |||
234 | /** | ||
235 | * @brief Filename of the file that stores the valid peers persistently. | ||
236 | */ | ||
237 | static char *filename_valid_peers; | ||
238 | |||
239 | /** | ||
240 | * Set of all peers to keep track of them. | ||
241 | */ | ||
242 | static struct GNUNET_CONTAINER_MultiPeerMap *peer_map; | ||
243 | |||
244 | /** | ||
245 | * Own #GNUNET_PeerIdentity. | ||
246 | */ | ||
247 | static const struct GNUNET_PeerIdentity *own_identity; | ||
248 | |||
249 | /** | ||
250 | * Cadet handle. | ||
251 | */ | ||
252 | static struct GNUNET_CADET_Handle *cadet_handle; | ||
253 | |||
254 | /** | ||
255 | * @brief Disconnect handler | ||
256 | */ | ||
257 | static GNUNET_CADET_DisconnectEventHandler cleanup_destroyed_channel; | ||
258 | |||
259 | /** | ||
260 | * @brief cadet handlers | ||
261 | */ | ||
262 | static 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 | */ | ||
273 | static struct PeerContext * | ||
274 | get_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 | */ | ||
294 | static struct PeerContext * | ||
295 | create_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 | */ | ||
320 | static struct PeerContext * | ||
321 | create_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 | */ | ||
341 | int | ||
342 | Peers_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 | */ | ||
369 | struct 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 | */ | ||
400 | static int | ||
401 | get_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 | */ | ||
423 | static const struct GNUNET_PeerIdentity * | ||
424 | get_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 | */ | ||
452 | static int | ||
453 | add_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 | */ | ||
479 | static void | ||
480 | set_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 | */ | ||
520 | struct GNUNET_CADET_Channel * | ||
521 | get_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 | */ | ||
559 | static struct GNUNET_MQ_Handle * | ||
560 | get_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 | */ | ||
581 | static void | ||
582 | mq_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 | */ | ||
602 | static void | ||
603 | check_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 | */ | ||
632 | static struct PendingMessage * | ||
633 | insert_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 | */ | ||
658 | static void | ||
659 | remove_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 | */ | ||
689 | static int | ||
690 | check_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 | */ | ||
713 | static int | ||
714 | peermap_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 | */ | ||
730 | static void | ||
731 | mq_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 | */ | ||
756 | static int | ||
757 | store_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 | */ | ||
786 | static void | ||
787 | store_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 | */ | ||
847 | static const struct GNUNET_PeerIdentity * | ||
848 | s2i_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 | */ | ||
887 | static void | ||
888 | restore_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 | */ | ||
958 | void | ||
959 | Peers_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 | */ | ||
979 | void | ||
980 | Peers_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 | */ | ||
1007 | static int | ||
1008 | valid_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 | */ | ||
1027 | int | ||
1028 | Peers_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 | */ | ||
1057 | int | ||
1058 | Peers_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 | */ | ||
1080 | int | ||
1081 | Peers_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 | */ | ||
1113 | int | ||
1114 | Peers_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 | */ | ||
1141 | int | ||
1142 | Peers_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 | */ | ||
1212 | void | ||
1213 | Peers_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 | */ | ||
1228 | void | ||
1229 | Peers_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 | */ | ||
1248 | int | ||
1249 | Peers_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 | */ | ||
1268 | void | ||
1269 | Peers_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 | */ | ||
1281 | void | ||
1282 | Peers_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 | */ | ||
1297 | int | ||
1298 | Peers_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 | */ | ||
1311 | uint32_t * | ||
1312 | Peers_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 | */ | ||
1342 | int | ||
1343 | Peers_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 | */ | ||
1359 | int | ||
1360 | Peers_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 | */ | ||
1373 | void | ||
1374 | Peers_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 | */ | ||
1390 | int | ||
1391 | Peers_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 | */ | ||
1414 | void * | ||
1415 | Peers_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 | */ | ||
1450 | int | ||
1451 | Peers_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 | */ | ||
1480 | int | ||
1481 | Peers_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 | */ | ||
1518 | int | ||
1519 | Peers_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 | */ | ||
1546 | void | ||
1547 | Peers_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 | */ | ||
1624 | void | ||
1625 | Peers_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 | */ | ||
1654 | int | ||
1655 | Peers_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 | */ | ||
1691 | struct GNUNET_CADET_Channel * | ||
1692 | Peers_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 | */ | ||
34 | enum Peers_PeerFlags | ||
35 | { | ||
36 | /** | ||
37 | * If we are waiting for a reply from that peer (sent a pull request). | ||
38 | */ | ||
39 | Peers_PULL_REPLY_PENDING = 0x01, | ||
40 | |||
41 | /* IN_OTHER_GOSSIP_LIST = 0x02, unneeded? */ | ||
42 | /* IN_OWN_SAMPLER_LIST = 0x04, unneeded? */ | ||
43 | /* IN_OWN_GOSSIP_LIST = 0x08, unneeded? */ | ||
44 | |||
45 | /** | ||
46 | * We set this bit when we 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 | */ | ||
64 | enum 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 | */ | ||
81 | enum 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 | */ | ||
100 | typedef 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 | */ | ||
111 | typedef 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 | */ | ||
124 | void | ||
125 | Peers_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 | */ | ||
134 | void | ||
135 | Peers_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 | */ | ||
146 | int | ||
147 | Peers_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 | */ | ||
162 | int | ||
163 | Peers_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 | */ | ||
175 | int | ||
176 | Peers_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 | */ | ||
191 | int | ||
192 | Peers_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 | */ | ||
201 | int | ||
202 | Peers_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 | */ | ||
210 | void | ||
211 | Peers_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 | */ | ||
219 | void | ||
220 | Peers_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 | */ | ||
231 | int | ||
232 | Peers_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 | */ | ||
241 | void | ||
242 | Peers_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 | */ | ||
250 | void | ||
251 | Peers_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 | */ | ||
262 | int | ||
263 | Peers_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 | */ | ||
273 | uint32_t * | ||
274 | Peers_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 | */ | ||
287 | int | ||
288 | Peers_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 | */ | ||
300 | int | ||
301 | Peers_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 | */ | ||
310 | void | ||
311 | Peers_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 | */ | ||
322 | int | ||
323 | Peers_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 | */ | ||
335 | void * | ||
336 | Peers_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 | */ | ||
348 | int | ||
349 | Peers_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 | */ | ||
363 | int | ||
364 | Peers_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 | */ | ||
379 | int | ||
380 | Peers_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 | */ | ||
392 | void | ||
393 | Peers_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 | */ | ||
406 | void | ||
407 | Peers_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 | */ | ||
421 | int | ||
422 | Peers_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 | */ | ||
434 | struct GNUNET_CADET_Channel * | ||
435 | Peers_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 | */ | ||
186 | enum 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 | */ | ||
216 | enum 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 | */ | ||
239 | enum 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 | */ | ||
258 | typedef 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 | */ | ||
269 | typedef int | ||
270 | (*PeersIterator) (void *cls, | ||
271 | const struct GNUNET_PeerIdentity *peer); | ||
272 | |||
273 | |||
178 | GNUNET_NETWORK_STRUCT_END | 274 | GNUNET_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 | */ | ||
38 | void 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 | */ | ||
49 | void | ||
50 | peer_op (void *cls, const struct GNUNET_PeerIdentity *peer); | ||
51 | |||
52 | static int | ||
53 | check () | ||
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 | |||
128 | int | ||
129 | main (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 */ | ||