diff options
author | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-01-02 16:48:03 +0100 |
---|---|---|
committer | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-01-02 16:48:03 +0100 |
commit | 7c1f035ed971e12882cd7a65c7d36883842945b1 (patch) | |
tree | 3828089ef8124270b976ac94902ba27210d275a3 /src/rps | |
parent | 92d8c8a77e242a61927acc0e22fcecea479e6c43 (diff) | |
parent | 61f532f18450e0d7c72f0c17f4a20b5854cf53bf (diff) | |
download | gnunet-7c1f035ed971e12882cd7a65c7d36883842945b1.tar.gz gnunet-7c1f035ed971e12882cd7a65c7d36883842945b1.zip |
-merge
Diffstat (limited to 'src/rps')
-rw-r--r-- | src/rps/.gitignore | 12 | ||||
-rw-r--r-- | src/rps/Makefile.am | 15 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps.c | 1798 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps_peers.c | 1694 | ||||
-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_rps.c | 86 | ||||
-rw-r--r-- | src/rps/test_rps.conf | 38 | ||||
-rw-r--r-- | src/rps/test_service_rps_peers.c | 137 |
9 files changed, 1990 insertions, 2323 deletions
diff --git a/src/rps/.gitignore b/src/rps/.gitignore index 0d460e62c..cb14f5b09 100644 --- a/src/rps/.gitignore +++ b/src/rps/.gitignore | |||
@@ -1,3 +1,15 @@ | |||
1 | gnunet-service-rps | 1 | gnunet-service-rps |
2 | gnunet-rps | 2 | gnunet-rps |
3 | gnunet-rps-profiler | 3 | gnunet-rps-profiler |
4 | test_rps_malicious_1 | ||
5 | test_rps_malicious_2 | ||
6 | test_rps_malicious_3 | ||
7 | test_rps_req_cancel | ||
8 | test_rps_seed_big | ||
9 | test_rps_seed_request | ||
10 | test_rps_single_req | ||
11 | test_service_rps_custommap | ||
12 | test_service_rps_sampler_elem | ||
13 | test_service_rps_view | ||
14 | test_rps_churn | ||
15 | test_service_rps_peers | ||
diff --git a/src/rps/Makefile.am b/src/rps/Makefile.am index e6c8cd929..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 \ |
@@ -81,7 +79,8 @@ check_PROGRAMS = \ | |||
81 | test_rps_seed_request \ | 79 | test_rps_seed_request \ |
82 | test_rps_single_req \ | 80 | test_rps_single_req \ |
83 | test_rps_req_cancel \ | 81 | test_rps_req_cancel \ |
84 | test_rps_seed_big | 82 | test_rps_seed_big \ |
83 | test_rps_churn | ||
85 | endif | 84 | endif |
86 | 85 | ||
87 | ld_rps_test_lib = \ | 86 | ld_rps_test_lib = \ |
@@ -105,13 +104,6 @@ test_service_rps_view_SOURCES = \ | |||
105 | test_service_rps_view.c | 104 | test_service_rps_view.c |
106 | test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la | 105 | test_service_rps_view_LDADD = $(top_builddir)/src/util/libgnunetutil.la |
107 | 106 | ||
108 | test_service_rps_peers_SOURCES = \ | ||
109 | gnunet-service-rps_peers.h gnunet-service-rps_peers.c \ | ||
110 | test_service_rps_peers.c | ||
111 | test_service_rps_peers_LDADD = \ | ||
112 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
113 | $(top_builddir)/src/cadet/libgnunetcadet.la | ||
114 | |||
115 | test_service_rps_custommap_SOURCES = \ | 107 | test_service_rps_custommap_SOURCES = \ |
116 | gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ | 108 | gnunet-service-rps_custommap.h gnunet-service-rps_custommap.c \ |
117 | test_service_rps_custommap.c | 109 | test_service_rps_custommap.c |
@@ -145,6 +137,9 @@ test_rps_req_cancel_LDADD = $(ld_rps_test_lib) | |||
145 | test_rps_seed_big_SOURCES = $(rps_test_src) | 137 | test_rps_seed_big_SOURCES = $(rps_test_src) |
146 | test_rps_seed_big_LDADD = $(ld_rps_test_lib) | 138 | test_rps_seed_big_LDADD = $(ld_rps_test_lib) |
147 | 139 | ||
140 | test_rps_churn_SOURCES = $(rps_test_src) | ||
141 | test_rps_churn_LDADD = $(ld_rps_test_lib) | ||
142 | |||
148 | gnunet_rps_profiler_SOURCES = $(rps_test_src) | 143 | gnunet_rps_profiler_SOURCES = $(rps_test_src) |
149 | gnunet_rps_profiler_LDADD = $(ld_rps_test_lib) | 144 | gnunet_rps_profiler_LDADD = $(ld_rps_test_lib) |
150 | 145 | ||
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index 0a4543b30..ec70075cf 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 | ***********************************************************************/ |
@@ -847,6 +2568,7 @@ cleanup_destroyed_channel (void *cls, | |||
847 | { | 2568 | { |
848 | struct GNUNET_PeerIdentity *peer = cls; | 2569 | struct GNUNET_PeerIdentity *peer = cls; |
849 | uint32_t *channel_flag; | 2570 | uint32_t *channel_flag; |
2571 | struct PeerContext *peer_ctx; | ||
850 | 2572 | ||
851 | if (GNUNET_NO == Peers_check_peer_known (peer)) | 2573 | if (GNUNET_NO == Peers_check_peer_known (peer)) |
852 | { /* We don't know a context to that peer */ | 2574 | { /* We don't know a context to that peer */ |
@@ -856,6 +2578,15 @@ cleanup_destroyed_channel (void *cls, | |||
856 | return; | 2578 | return; |
857 | } | 2579 | } |
858 | 2580 | ||
2581 | peer_ctx = get_peer_ctx (peer); | ||
2582 | if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_RECEIVING)) | ||
2583 | { | ||
2584 | set_channel_flag (peer_ctx->recv_channel_flags, Peers_CHANNEL_DESTROING); | ||
2585 | } else if (GNUNET_YES == Peers_check_channel_role (peer, channel, Peers_CHANNEL_ROLE_SENDING)) | ||
2586 | { | ||
2587 | set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_DESTROING); | ||
2588 | } | ||
2589 | |||
859 | if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY)) | 2590 | if (GNUNET_YES == Peers_check_peer_flag (peer, Peers_TO_DESTROY)) |
860 | { /* We are in the middle of removing that peer from our knowledge. In this | 2591 | { /* We are in the middle of removing that peer from our knowledge. In this |
861 | case simply make sure that the channels are cleaned. */ | 2592 | case simply make sure that the channels are cleaned. */ |
@@ -1121,7 +2852,6 @@ handle_client_request_cancel (void *cls, | |||
1121 | (rep_cls->id != ntohl (msg->id)) ) | 2852 | (rep_cls->id != ntohl (msg->id)) ) |
1122 | rep_cls = rep_cls->next; | 2853 | rep_cls = rep_cls->next; |
1123 | GNUNET_assert (rep_cls->id == ntohl (msg->id)); | 2854 | GNUNET_assert (rep_cls->id == ntohl (msg->id)); |
1124 | RPS_sampler_request_cancel (rep_cls->req_handle); | ||
1125 | destroy_reply_cls (rep_cls); | 2855 | destroy_reply_cls (rep_cls); |
1126 | GNUNET_SERVICE_client_continue (cli_ctx->client); | 2856 | GNUNET_SERVICE_client_continue (cli_ctx->client); |
1127 | } | 2857 | } |
@@ -1239,24 +2969,24 @@ handle_peer_push (void *cls, | |||
1239 | (3 == mal_type) ) | 2969 | (3 == mal_type) ) |
1240 | { /* Try to maximise representation */ | 2970 | { /* Try to maximise representation */ |
1241 | tmp_att_peer = GNUNET_new (struct AttackedPeer); | 2971 | tmp_att_peer = GNUNET_new (struct AttackedPeer); |
1242 | GNUNET_memcpy (&tmp_att_peer->peer_id, peer, sizeof (struct GNUNET_PeerIdentity)); | 2972 | tmp_att_peer->peer_id = *peer; |
1243 | if (NULL == att_peer_set) | 2973 | if (NULL == att_peer_set) |
1244 | att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO); | 2974 | att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO); |
1245 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set, | 2975 | if (GNUNET_NO == |
1246 | peer)) | 2976 | GNUNET_CONTAINER_multipeermap_contains (att_peer_set, |
2977 | peer)) | ||
1247 | { | 2978 | { |
1248 | GNUNET_CONTAINER_DLL_insert (att_peers_head, | 2979 | GNUNET_CONTAINER_DLL_insert (att_peers_head, |
1249 | att_peers_tail, | 2980 | att_peers_tail, |
1250 | tmp_att_peer); | 2981 | tmp_att_peer); |
1251 | add_peer_array_to_set (peer, 1, att_peer_set); | 2982 | add_peer_array_to_set (peer, 1, att_peer_set); |
1252 | } | 2983 | } |
1253 | GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); | ||
1254 | } | 2984 | } |
1255 | 2985 | ||
1256 | 2986 | ||
1257 | else if (2 == mal_type) | 2987 | else if (2 == mal_type) |
1258 | { /* We attack one single well-known peer - simply ignore */ | 2988 | { |
1259 | GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); | 2989 | /* We attack one single well-known peer - simply ignore */ |
1260 | } | 2990 | } |
1261 | #endif /* ENABLE_MALICIOUS */ | 2991 | #endif /* ENABLE_MALICIOUS */ |
1262 | 2992 | ||
@@ -1289,7 +3019,6 @@ handle_peer_pull_request (void *cls, | |||
1289 | || 3 == mal_type) | 3019 | || 3 == mal_type) |
1290 | { /* Try to maximise representation */ | 3020 | { /* Try to maximise representation */ |
1291 | send_pull_reply (peer, mal_peers, num_mal_peers); | 3021 | send_pull_reply (peer, mal_peers, num_mal_peers); |
1292 | GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); | ||
1293 | } | 3022 | } |
1294 | 3023 | ||
1295 | else if (2 == mal_type) | 3024 | else if (2 == mal_type) |
@@ -1298,7 +3027,6 @@ handle_peer_pull_request (void *cls, | |||
1298 | { | 3027 | { |
1299 | send_pull_reply (peer, mal_peers, num_mal_peers); | 3028 | send_pull_reply (peer, mal_peers, num_mal_peers); |
1300 | } | 3029 | } |
1301 | GNUNET_CADET_receive_done (Peers_get_recv_channel (peer)); | ||
1302 | } | 3030 | } |
1303 | #endif /* ENABLE_MALICIOUS */ | 3031 | #endif /* ENABLE_MALICIOUS */ |
1304 | 3032 | ||
@@ -1360,7 +3088,7 @@ static void | |||
1360 | handle_peer_pull_reply (void *cls, | 3088 | handle_peer_pull_reply (void *cls, |
1361 | const struct GNUNET_RPS_P2P_PullReplyMessage *msg) | 3089 | const struct GNUNET_RPS_P2P_PullReplyMessage *msg) |
1362 | { | 3090 | { |
1363 | struct GNUNET_PeerIdentity *peers; | 3091 | const struct GNUNET_PeerIdentity *peers; |
1364 | struct GNUNET_PeerIdentity *sender = cls; | 3092 | struct GNUNET_PeerIdentity *sender = cls; |
1365 | uint32_t i; | 3093 | uint32_t i; |
1366 | #ifdef ENABLE_MALICIOUS | 3094 | #ifdef ENABLE_MALICIOUS |
@@ -1373,12 +3101,11 @@ handle_peer_pull_reply (void *cls, | |||
1373 | // We shouldn't even receive pull replies as we're not sending | 3101 | // We shouldn't even receive pull replies as we're not sending |
1374 | if (2 == mal_type) | 3102 | if (2 == mal_type) |
1375 | { | 3103 | { |
1376 | GNUNET_CADET_receive_done (Peers_get_recv_channel (sender)); | ||
1377 | } | 3104 | } |
1378 | #endif /* ENABLE_MALICIOUS */ | 3105 | #endif /* ENABLE_MALICIOUS */ |
1379 | 3106 | ||
1380 | /* Do actual logic */ | 3107 | /* Do actual logic */ |
1381 | peers = (struct GNUNET_PeerIdentity *) &msg[1]; | 3108 | peers = (const struct GNUNET_PeerIdentity *) &msg[1]; |
1382 | 3109 | ||
1383 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 3110 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1384 | "PULL REPLY received, got following %u peers:\n", | 3111 | "PULL REPLY received, got following %u peers:\n", |
@@ -2132,7 +3859,6 @@ shutdown_task (void *cls) | |||
2132 | reply_cls); | 3859 | reply_cls); |
2133 | GNUNET_free (reply_cls); | 3860 | GNUNET_free (reply_cls); |
2134 | } | 3861 | } |
2135 | GNUNET_MQ_destroy (client_ctx->mq); | ||
2136 | GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx); | 3862 | GNUNET_CONTAINER_DLL_remove (cli_ctx_head, cli_ctx_tail, client_ctx); |
2137 | GNUNET_free (client_ctx); | 3863 | GNUNET_free (client_ctx); |
2138 | } | 3864 | } |
@@ -2150,6 +3876,7 @@ shutdown_task (void *cls) | |||
2150 | GNUNET_NSE_disconnect (nse); | 3876 | GNUNET_NSE_disconnect (nse); |
2151 | RPS_sampler_destroy (prot_sampler); | 3877 | RPS_sampler_destroy (prot_sampler); |
2152 | RPS_sampler_destroy (client_sampler); | 3878 | RPS_sampler_destroy (client_sampler); |
3879 | GNUNET_CADET_close_port (cadet_port); | ||
2153 | GNUNET_CADET_disconnect (cadet_handle); | 3880 | GNUNET_CADET_disconnect (cadet_handle); |
2154 | View_destroy (); | 3881 | View_destroy (); |
2155 | CustomPeerMap_destroy (push_map); | 3882 | CustomPeerMap_destroy (push_map); |
@@ -2240,26 +3967,6 @@ run (void *cls, | |||
2240 | const struct GNUNET_CONFIGURATION_Handle *c, | 3967 | const struct GNUNET_CONFIGURATION_Handle *c, |
2241 | struct GNUNET_SERVICE_Handle *service) | 3968 | struct GNUNET_SERVICE_Handle *service) |
2242 | { | 3969 | { |
2243 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = { | ||
2244 | GNUNET_MQ_hd_fixed_size (peer_check, | ||
2245 | GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE, | ||
2246 | struct GNUNET_MessageHeader, | ||
2247 | NULL), | ||
2248 | GNUNET_MQ_hd_fixed_size (peer_push, | ||
2249 | GNUNET_MESSAGE_TYPE_RPS_PP_PUSH, | ||
2250 | struct GNUNET_MessageHeader, | ||
2251 | NULL), | ||
2252 | GNUNET_MQ_hd_fixed_size (peer_pull_request, | ||
2253 | GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST, | ||
2254 | struct GNUNET_MessageHeader, | ||
2255 | NULL), | ||
2256 | GNUNET_MQ_hd_var_size (peer_pull_reply, | ||
2257 | GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY, | ||
2258 | struct GNUNET_RPS_P2P_PullReplyMessage, | ||
2259 | NULL), | ||
2260 | GNUNET_MQ_handler_end () | ||
2261 | }; | ||
2262 | |||
2263 | int size; | 3970 | int size; |
2264 | int out_size; | 3971 | int out_size; |
2265 | char* fn_valid_peers; | 3972 | char* fn_valid_peers; |
@@ -2349,6 +4056,27 @@ run (void *cls, | |||
2349 | 4056 | ||
2350 | 4057 | ||
2351 | /* Initialise cadet */ | 4058 | /* Initialise cadet */ |
4059 | /* There exists a copy-paste-clone in get_channel() */ | ||
4060 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = { | ||
4061 | GNUNET_MQ_hd_fixed_size (peer_check, | ||
4062 | GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE, | ||
4063 | struct GNUNET_MessageHeader, | ||
4064 | NULL), | ||
4065 | GNUNET_MQ_hd_fixed_size (peer_push, | ||
4066 | GNUNET_MESSAGE_TYPE_RPS_PP_PUSH, | ||
4067 | struct GNUNET_MessageHeader, | ||
4068 | NULL), | ||
4069 | GNUNET_MQ_hd_fixed_size (peer_pull_request, | ||
4070 | GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST, | ||
4071 | struct GNUNET_MessageHeader, | ||
4072 | NULL), | ||
4073 | GNUNET_MQ_hd_var_size (peer_pull_reply, | ||
4074 | GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY, | ||
4075 | struct GNUNET_RPS_P2P_PullReplyMessage, | ||
4076 | NULL), | ||
4077 | GNUNET_MQ_handler_end () | ||
4078 | }; | ||
4079 | |||
2352 | cadet_handle = GNUNET_CADET_connect (cfg); | 4080 | cadet_handle = GNUNET_CADET_connect (cfg); |
2353 | GNUNET_assert (NULL != cadet_handle); | 4081 | GNUNET_assert (NULL != cadet_handle); |
2354 | GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS, | 4082 | GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_RPS, |
@@ -2365,7 +4093,7 @@ run (void *cls, | |||
2365 | 4093 | ||
2366 | peerinfo_handle = GNUNET_PEERINFO_connect (cfg); | 4094 | peerinfo_handle = GNUNET_PEERINFO_connect (cfg); |
2367 | Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel, | 4095 | Peers_initialise (fn_valid_peers, cadet_handle, cleanup_destroyed_channel, |
2368 | cadet_handlers, &own_identity); | 4096 | &own_identity); |
2369 | GNUNET_free (fn_valid_peers); | 4097 | GNUNET_free (fn_valid_peers); |
2370 | 4098 | ||
2371 | /* Initialise sampler */ | 4099 | /* Initialise sampler */ |
diff --git a/src/rps/gnunet-service-rps_peers.c b/src/rps/gnunet-service-rps_peers.c deleted file mode 100644 index 58aa84ccf..000000000 --- a/src/rps/gnunet-service-rps_peers.c +++ /dev/null | |||
@@ -1,1694 +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 | */ | ||
657 | static void | ||
658 | remove_pending_message (struct PendingMessage *pending_msg) | ||
659 | { | ||
660 | struct PeerContext *peer_ctx; | ||
661 | |||
662 | peer_ctx = pending_msg->peer_ctx; | ||
663 | GNUNET_CONTAINER_DLL_remove (peer_ctx->pending_messages_head, | ||
664 | peer_ctx->pending_messages_tail, | ||
665 | pending_msg); | ||
666 | GNUNET_MQ_send_cancel (peer_ctx->pending_messages_head->ev); | ||
667 | GNUNET_free (pending_msg); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * @brief Check whether function of type #PeerOp was already scheduled | ||
673 | * | ||
674 | * The array with pending operations will probably never grow really big, so | ||
675 | * iterating over it should be ok. | ||
676 | * | ||
677 | * @param peer the peer to check | ||
678 | * @param peer_op the operation (#PeerOp) on the peer | ||
679 | * | ||
680 | * @return #GNUNET_YES if this operation is scheduled on that peer | ||
681 | * #GNUNET_NO otherwise | ||
682 | */ | ||
683 | static int | ||
684 | check_operation_scheduled (const struct GNUNET_PeerIdentity *peer, | ||
685 | const PeerOp peer_op) | ||
686 | { | ||
687 | const struct PeerContext *peer_ctx; | ||
688 | unsigned int i; | ||
689 | |||
690 | peer_ctx = get_peer_ctx (peer); | ||
691 | for (i = 0; i < peer_ctx->num_pending_ops; i++) | ||
692 | if (peer_op == peer_ctx->pending_ops[i].op) | ||
693 | return GNUNET_YES; | ||
694 | return GNUNET_NO; | ||
695 | } | ||
696 | |||
697 | |||
698 | /** | ||
699 | * Iterator over hash map entries. Deletes all contexts of peers. | ||
700 | * | ||
701 | * @param cls closure | ||
702 | * @param key current public key | ||
703 | * @param value value in the hash map | ||
704 | * @return #GNUNET_YES if we should continue to iterate, | ||
705 | * #GNUNET_NO if not. | ||
706 | */ | ||
707 | static int | ||
708 | peermap_clear_iterator (void *cls, | ||
709 | const struct GNUNET_PeerIdentity *key, | ||
710 | void *value) | ||
711 | { | ||
712 | Peers_remove_peer (key); | ||
713 | return GNUNET_YES; | ||
714 | } | ||
715 | |||
716 | |||
717 | /** | ||
718 | * @brief This is called once a message is sent. | ||
719 | * | ||
720 | * Removes the pending message | ||
721 | * | ||
722 | * @param cls type of the message that was sent | ||
723 | */ | ||
724 | static void | ||
725 | mq_notify_sent_cb (void *cls) | ||
726 | { | ||
727 | struct PendingMessage *pending_msg = (struct PendingMessage *) cls; | ||
728 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "%s was sent.\n", | ||
730 | pending_msg->type); | ||
731 | remove_pending_message (pending_msg); | ||
732 | } | ||
733 | |||
734 | |||
735 | /** | ||
736 | * @brief Iterator function for #store_valid_peers. | ||
737 | * | ||
738 | * Implements #GNUNET_CONTAINER_PeerMapIterator. | ||
739 | * Writes single peer to disk. | ||
740 | * | ||
741 | * @param cls the file handle to write to. | ||
742 | * @param peer current peer | ||
743 | * @param value unused | ||
744 | * | ||
745 | * @return #GNUNET_YES if we should continue to | ||
746 | * iterate, | ||
747 | * #GNUNET_NO if not. | ||
748 | */ | ||
749 | static int | ||
750 | store_peer_presistently_iterator (void *cls, | ||
751 | const struct GNUNET_PeerIdentity *peer, | ||
752 | void *value) | ||
753 | { | ||
754 | const struct GNUNET_DISK_FileHandle *fh = cls; | ||
755 | char peer_string[128]; | ||
756 | int size; | ||
757 | ssize_t ret; | ||
758 | |||
759 | if (NULL == peer) | ||
760 | { | ||
761 | return GNUNET_YES; | ||
762 | } | ||
763 | size = GNUNET_snprintf (peer_string, | ||
764 | sizeof (peer_string), | ||
765 | "%s\n", | ||
766 | GNUNET_i2s_full (peer)); | ||
767 | GNUNET_assert (53 == size); | ||
768 | ret = GNUNET_DISK_file_write (fh, | ||
769 | peer_string, | ||
770 | size); | ||
771 | GNUNET_assert (size == ret); | ||
772 | return GNUNET_YES; | ||
773 | } | ||
774 | |||
775 | |||
776 | /** | ||
777 | * @brief Store the peers currently in #valid_peers to disk. | ||
778 | */ | ||
779 | static void | ||
780 | store_valid_peers () | ||
781 | { | ||
782 | struct GNUNET_DISK_FileHandle *fh; | ||
783 | uint32_t number_written_peers; | ||
784 | int ret; | ||
785 | |||
786 | if (0 == strncmp ("DISABLE", filename_valid_peers, 7)) | ||
787 | { | ||
788 | return; | ||
789 | } | ||
790 | |||
791 | ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers); | ||
792 | if (GNUNET_SYSERR == ret) | ||
793 | { | ||
794 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
795 | "Not able to create directory for file `%s'\n", | ||
796 | filename_valid_peers); | ||
797 | GNUNET_break (0); | ||
798 | } | ||
799 | else if (GNUNET_NO == ret) | ||
800 | { | ||
801 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
802 | "Directory for file `%s' exists but is not writable for us\n", | ||
803 | filename_valid_peers); | ||
804 | GNUNET_break (0); | ||
805 | } | ||
806 | fh = GNUNET_DISK_file_open (filename_valid_peers, | ||
807 | GNUNET_DISK_OPEN_WRITE | | ||
808 | GNUNET_DISK_OPEN_CREATE, | ||
809 | GNUNET_DISK_PERM_USER_READ | | ||
810 | GNUNET_DISK_PERM_USER_WRITE); | ||
811 | if (NULL == fh) | ||
812 | { | ||
813 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
814 | "Not able to write valid peers to file `%s'\n", | ||
815 | filename_valid_peers); | ||
816 | return; | ||
817 | } | ||
818 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
819 | "Writing %u valid peers to disk\n", | ||
820 | GNUNET_CONTAINER_multipeermap_size (valid_peers)); | ||
821 | number_written_peers = | ||
822 | GNUNET_CONTAINER_multipeermap_iterate (valid_peers, | ||
823 | store_peer_presistently_iterator, | ||
824 | fh); | ||
825 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); | ||
826 | GNUNET_assert (number_written_peers == | ||
827 | GNUNET_CONTAINER_multipeermap_size (valid_peers)); | ||
828 | } | ||
829 | |||
830 | |||
831 | /** | ||
832 | * @brief Convert string representation of peer id to peer id. | ||
833 | * | ||
834 | * Counterpart to #GNUNET_i2s_full. | ||
835 | * | ||
836 | * @param string_repr The string representation of the peer id | ||
837 | * | ||
838 | * @return The peer id | ||
839 | */ | ||
840 | static const struct GNUNET_PeerIdentity * | ||
841 | s2i_full (const char *string_repr) | ||
842 | { | ||
843 | struct GNUNET_PeerIdentity *peer; | ||
844 | size_t len; | ||
845 | int ret; | ||
846 | |||
847 | peer = GNUNET_new (struct GNUNET_PeerIdentity); | ||
848 | len = strlen (string_repr); | ||
849 | if (52 > len) | ||
850 | { | ||
851 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
852 | "Not able to convert string representation of PeerID to PeerID\n" | ||
853 | "Sting representation: %s (len %u) - too short\n", | ||
854 | string_repr, | ||
855 | len); | ||
856 | GNUNET_break (0); | ||
857 | } | ||
858 | else if (52 < len) | ||
859 | { | ||
860 | len = 52; | ||
861 | } | ||
862 | ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr, | ||
863 | len, | ||
864 | &peer->public_key); | ||
865 | if (GNUNET_OK != ret) | ||
866 | { | ||
867 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
868 | "Not able to convert string representation of PeerID to PeerID\n" | ||
869 | "Sting representation: %s\n", | ||
870 | string_repr); | ||
871 | GNUNET_break (0); | ||
872 | } | ||
873 | return peer; | ||
874 | } | ||
875 | |||
876 | |||
877 | /** | ||
878 | * @brief Restore the peers on disk to #valid_peers. | ||
879 | */ | ||
880 | static void | ||
881 | restore_valid_peers () | ||
882 | { | ||
883 | off_t file_size; | ||
884 | uint32_t num_peers; | ||
885 | struct GNUNET_DISK_FileHandle *fh; | ||
886 | char *buf; | ||
887 | ssize_t size_read; | ||
888 | char *iter_buf; | ||
889 | char *str_repr; | ||
890 | const struct GNUNET_PeerIdentity *peer; | ||
891 | |||
892 | if (0 == strncmp ("DISABLE", filename_valid_peers, 7)) | ||
893 | { | ||
894 | return; | ||
895 | } | ||
896 | |||
897 | if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers)) | ||
898 | { | ||
899 | return; | ||
900 | } | ||
901 | fh = GNUNET_DISK_file_open (filename_valid_peers, | ||
902 | GNUNET_DISK_OPEN_READ, | ||
903 | GNUNET_DISK_PERM_NONE); | ||
904 | GNUNET_assert (NULL != fh); | ||
905 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size)); | ||
906 | num_peers = file_size / 53; | ||
907 | buf = GNUNET_malloc (file_size); | ||
908 | size_read = GNUNET_DISK_file_read (fh, buf, file_size); | ||
909 | GNUNET_assert (size_read == file_size); | ||
910 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
911 | "Restoring %" PRIu32 " peers from file `%s'\n", | ||
912 | num_peers, | ||
913 | filename_valid_peers); | ||
914 | for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53) | ||
915 | { | ||
916 | str_repr = GNUNET_strndup (iter_buf, 53); | ||
917 | peer = s2i_full (str_repr); | ||
918 | GNUNET_free (str_repr); | ||
919 | add_valid_peer (peer); | ||
920 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
921 | "Restored valid peer %s from disk\n", | ||
922 | GNUNET_i2s_full (peer)); | ||
923 | } | ||
924 | iter_buf = NULL; | ||
925 | GNUNET_free (buf); | ||
926 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
927 | "num_peers: %" PRIu32 ", _size (valid_peers): %u\n", | ||
928 | num_peers, | ||
929 | GNUNET_CONTAINER_multipeermap_size (valid_peers)); | ||
930 | if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers)) | ||
931 | { | ||
932 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
933 | "Number of restored peers does not match file size. Have probably duplicates.\n"); | ||
934 | } | ||
935 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); | ||
936 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
937 | "Restored %u valid peers from disk\n", | ||
938 | GNUNET_CONTAINER_multipeermap_size (valid_peers)); | ||
939 | } | ||
940 | |||
941 | |||
942 | /** | ||
943 | * @brief Initialise storage of peers | ||
944 | * | ||
945 | * @param fn_valid_peers filename of the file used to store valid peer ids | ||
946 | * @param cadet_h cadet handle | ||
947 | * @param disconnect_handler Disconnect handler | ||
948 | * @param c_handlers cadet handlers | ||
949 | * @param own_id own peer identity | ||
950 | */ | ||
951 | void | ||
952 | Peers_initialise (char* fn_valid_peers, | ||
953 | struct GNUNET_CADET_Handle *cadet_h, | ||
954 | GNUNET_CADET_DisconnectEventHandler disconnect_handler, | ||
955 | const struct GNUNET_MQ_MessageHandler *c_handlers, | ||
956 | const struct GNUNET_PeerIdentity *own_id) | ||
957 | { | ||
958 | filename_valid_peers = GNUNET_strdup (fn_valid_peers); | ||
959 | cadet_handle = cadet_h; | ||
960 | cleanup_destroyed_channel = disconnect_handler; | ||
961 | cadet_handlers = c_handlers; | ||
962 | own_identity = own_id; | ||
963 | peer_map = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); | ||
964 | valid_peers = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO); | ||
965 | restore_valid_peers (); | ||
966 | } | ||
967 | |||
968 | |||
969 | /** | ||
970 | * @brief Delete storage of peers that was created with #Peers_initialise () | ||
971 | */ | ||
972 | void | ||
973 | Peers_terminate () | ||
974 | { | ||
975 | if (GNUNET_SYSERR == | ||
976 | GNUNET_CONTAINER_multipeermap_iterate (peer_map, | ||
977 | peermap_clear_iterator, | ||
978 | NULL)) | ||
979 | { | ||
980 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
981 | "Iteration destroying peers was aborted.\n"); | ||
982 | } | ||
983 | GNUNET_CONTAINER_multipeermap_destroy (peer_map); | ||
984 | store_valid_peers (); | ||
985 | GNUNET_free (filename_valid_peers); | ||
986 | GNUNET_CONTAINER_multipeermap_destroy (valid_peers); | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Iterator over #valid_peers hash map entries. | ||
992 | * | ||
993 | * @param cls closure - unused | ||
994 | * @param peer current peer id | ||
995 | * @param value value in the hash map - unused | ||
996 | * @return #GNUNET_YES if we should continue to | ||
997 | * iterate, | ||
998 | * #GNUNET_NO if not. | ||
999 | */ | ||
1000 | static int | ||
1001 | valid_peer_iterator (void *cls, | ||
1002 | const struct GNUNET_PeerIdentity *peer, | ||
1003 | void *value) | ||
1004 | { | ||
1005 | struct PeersIteratorCls *it_cls = cls; | ||
1006 | |||
1007 | return it_cls->iterator (it_cls->cls, | ||
1008 | peer); | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | /** | ||
1013 | * @brief Get all currently known, valid peer ids. | ||
1014 | * | ||
1015 | * @param it function to call on each peer id | ||
1016 | * @param it_cls extra argument to @a it | ||
1017 | * @return the number of key value pairs processed, | ||
1018 | * #GNUNET_SYSERR if it aborted iteration | ||
1019 | */ | ||
1020 | int | ||
1021 | Peers_get_valid_peers (PeersIterator iterator, | ||
1022 | void *it_cls) | ||
1023 | { | ||
1024 | struct PeersIteratorCls *cls; | ||
1025 | int ret; | ||
1026 | |||
1027 | cls = GNUNET_new (struct PeersIteratorCls); | ||
1028 | cls->iterator = iterator; | ||
1029 | cls->cls = it_cls; | ||
1030 | ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers, | ||
1031 | valid_peer_iterator, | ||
1032 | cls); | ||
1033 | GNUNET_free (cls); | ||
1034 | return ret; | ||
1035 | } | ||
1036 | |||
1037 | |||
1038 | /** | ||
1039 | * @brief Add peer to known peers. | ||
1040 | * | ||
1041 | * This function is called on new peer_ids from 'external' sources | ||
1042 | * (client seed, cadet get_peers(), ...) | ||
1043 | * | ||
1044 | * @param peer the new #GNUNET_PeerIdentity | ||
1045 | * | ||
1046 | * @return #GNUNET_YES if peer was inserted | ||
1047 | * #GNUNET_NO otherwise (if peer was already known or | ||
1048 | * peer was #own_identity) | ||
1049 | */ | ||
1050 | int | ||
1051 | Peers_insert_peer (const struct GNUNET_PeerIdentity *peer) | ||
1052 | { | ||
1053 | if ( (GNUNET_YES == Peers_check_peer_known (peer)) || | ||
1054 | (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) ) | ||
1055 | { | ||
1056 | return GNUNET_NO; /* We already know this peer - nothing to do */ | ||
1057 | } | ||
1058 | (void) create_peer_ctx (peer); | ||
1059 | return GNUNET_YES; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | /** | ||
1064 | * @brief Try connecting to a peer to see whether it is online | ||
1065 | * | ||
1066 | * If not known yet, insert into known peers | ||
1067 | * | ||
1068 | * @param peer the peer whose liveliness is to be checked | ||
1069 | * @return #GNUNET_YES if peer had to be inserted | ||
1070 | * #GNUNET_NO otherwise (if peer was already known or | ||
1071 | * peer was #own_identity) | ||
1072 | */ | ||
1073 | int | ||
1074 | Peers_issue_peer_liveliness_check (const struct GNUNET_PeerIdentity *peer) | ||
1075 | { | ||
1076 | struct PeerContext *peer_ctx; | ||
1077 | int ret; | ||
1078 | |||
1079 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) | ||
1080 | { | ||
1081 | return GNUNET_NO; | ||
1082 | } | ||
1083 | ret = Peers_insert_peer (peer); | ||
1084 | peer_ctx = get_peer_ctx (peer); | ||
1085 | if (GNUNET_NO == Peers_check_peer_flag (peer, Peers_ONLINE)) | ||
1086 | { | ||
1087 | check_peer_live (peer_ctx); | ||
1088 | } | ||
1089 | return ret; | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * @brief Check if peer is removable. | ||
1095 | * | ||
1096 | * Check if | ||
1097 | * - a recv channel exists | ||
1098 | * - there are pending messages | ||
1099 | * - there is no pending pull reply | ||
1100 | * | ||
1101 | * @param peer the peer in question | ||
1102 | * @return #GNUNET_YES if peer is removable | ||
1103 | * #GNUNET_NO if peer is NOT removable | ||
1104 | * #GNUNET_SYSERR if peer is not known | ||
1105 | */ | ||
1106 | int | ||
1107 | Peers_check_removable (const struct GNUNET_PeerIdentity *peer) | ||
1108 | { | ||
1109 | struct PeerContext *peer_ctx; | ||
1110 | |||
1111 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) | ||
1112 | { | ||
1113 | return GNUNET_SYSERR; | ||
1114 | } | ||
1115 | |||
1116 | peer_ctx = get_peer_ctx (peer); | ||
1117 | if ( (NULL != peer_ctx->recv_channel) || | ||
1118 | (NULL != peer_ctx->pending_messages_head) || | ||
1119 | (GNUNET_NO == check_peer_flag_set (peer_ctx, Peers_PULL_REPLY_PENDING)) ) | ||
1120 | { | ||
1121 | return GNUNET_NO; | ||
1122 | } | ||
1123 | return GNUNET_YES; | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | /** | ||
1128 | * @brief Remove peer | ||
1129 | * | ||
1130 | * @param peer the peer to clean | ||
1131 | * @return #GNUNET_YES if peer was removed | ||
1132 | * #GNUNET_NO otherwise | ||
1133 | */ | ||
1134 | int | ||
1135 | Peers_remove_peer (const struct GNUNET_PeerIdentity *peer) | ||
1136 | { | ||
1137 | struct PeerContext *peer_ctx; | ||
1138 | |||
1139 | if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer)) | ||
1140 | { | ||
1141 | return GNUNET_NO; | ||
1142 | } | ||
1143 | |||
1144 | peer_ctx = get_peer_ctx (peer); | ||
1145 | set_peer_flag (peer_ctx, Peers_TO_DESTROY); | ||
1146 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1147 | "Going to remove peer %s\n", | ||
1148 | GNUNET_i2s (&peer_ctx->peer_id)); | ||
1149 | Peers_unset_peer_flag (peer, Peers_ONLINE); | ||
1150 | |||
1151 | GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0); | ||
1152 | while (NULL != peer_ctx->pending_messages_head) | ||
1153 | { | ||
1154 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1155 | "Removing unsent %s\n", | ||
1156 | peer_ctx->pending_messages_head->type); | ||
1157 | remove_pending_message (peer_ctx->pending_messages_head); | ||
1158 | } | ||
1159 | /* If we are still waiting for notification whether this peer is live | ||
1160 | * cancel the according task */ | ||
1161 | if (NULL != peer_ctx->liveliness_check_pending) | ||
1162 | { | ||
1163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1164 | "Removing pending liveliness check for peer %s\n", | ||
1165 | GNUNET_i2s (&peer_ctx->peer_id)); | ||
1166 | // TODO wait until cadet sets mq->cancel_impl | ||
1167 | //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev); | ||
1168 | GNUNET_free (peer_ctx->liveliness_check_pending); | ||
1169 | peer_ctx->liveliness_check_pending = NULL; | ||
1170 | } | ||
1171 | if (NULL != peer_ctx->send_channel) | ||
1172 | { | ||
1173 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1174 | "Destroying send channel\n"); | ||
1175 | GNUNET_CADET_channel_destroy (peer_ctx->send_channel); | ||
1176 | peer_ctx->send_channel = NULL; | ||
1177 | } | ||
1178 | if (NULL != peer_ctx->recv_channel) | ||
1179 | { | ||
1180 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1181 | "Destroying recv channel\n"); | ||
1182 | GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); | ||
1183 | peer_ctx->recv_channel = NULL; | ||
1184 | } | ||
1185 | if (NULL != peer_ctx->mq) | ||
1186 | { | ||
1187 | GNUNET_MQ_destroy (peer_ctx->mq); | ||
1188 | peer_ctx->mq = NULL; | ||
1189 | } | ||
1190 | |||
1191 | GNUNET_free (peer_ctx->send_channel_flags); | ||
1192 | GNUNET_free (peer_ctx->recv_channel_flags); | ||
1193 | |||
1194 | if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id)) | ||
1195 | { | ||
1196 | LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n"); | ||
1197 | } | ||
1198 | GNUNET_free (peer_ctx); | ||
1199 | return GNUNET_YES; | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | /** | ||
1204 | * @brief set flags on a given peer. | ||
1205 | * | ||
1206 | * @param peer the peer to set flags on | ||
1207 | * @param flags the flags | ||
1208 | */ | ||
1209 | void | ||
1210 | Peers_set_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags) | ||
1211 | { | ||
1212 | struct PeerContext *peer_ctx; | ||
1213 | |||
1214 | peer_ctx = get_peer_ctx (peer); | ||
1215 | set_peer_flag (peer_ctx, flags); | ||
1216 | } | ||
1217 | |||
1218 | |||
1219 | /** | ||
1220 | * @brief unset flags on a given peer. | ||
1221 | * | ||
1222 | * @param peer the peer to unset flags on | ||
1223 | * @param flags the flags | ||
1224 | */ | ||
1225 | void | ||
1226 | Peers_unset_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags) | ||
1227 | { | ||
1228 | struct PeerContext *peer_ctx; | ||
1229 | |||
1230 | peer_ctx = get_peer_ctx (peer); | ||
1231 | unset_peer_flag (peer_ctx, flags); | ||
1232 | } | ||
1233 | |||
1234 | |||
1235 | /** | ||
1236 | * @brief Check whether flags on a peer are set. | ||
1237 | * | ||
1238 | * @param peer the peer to check the flag of | ||
1239 | * @param flags the flags to check | ||
1240 | * | ||
1241 | * @return #GNUNET_SYSERR if peer is not known | ||
1242 | * #GNUNET_YES if all given flags are set | ||
1243 | * #GNUNET_NO otherwise | ||
1244 | */ | ||
1245 | int | ||
1246 | Peers_check_peer_flag (const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags) | ||
1247 | { | ||
1248 | struct PeerContext *peer_ctx; | ||
1249 | |||
1250 | if (GNUNET_NO == Peers_check_peer_known (peer)) | ||
1251 | { | ||
1252 | return GNUNET_SYSERR; | ||
1253 | } | ||
1254 | peer_ctx = get_peer_ctx (peer); | ||
1255 | return check_peer_flag_set (peer_ctx, flags); | ||
1256 | } | ||
1257 | |||
1258 | |||
1259 | /** | ||
1260 | * @brief set flags on a given channel. | ||
1261 | * | ||
1262 | * @param channel the channel to set flags on | ||
1263 | * @param flags the flags | ||
1264 | */ | ||
1265 | void | ||
1266 | Peers_set_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags) | ||
1267 | { | ||
1268 | set_channel_flag (channel_flags, flags); | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | /** | ||
1273 | * @brief unset flags on a given channel. | ||
1274 | * | ||
1275 | * @param channel the channel to unset flags on | ||
1276 | * @param flags the flags | ||
1277 | */ | ||
1278 | void | ||
1279 | Peers_unset_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags) | ||
1280 | { | ||
1281 | unset_channel_flag (channel_flags, flags); | ||
1282 | } | ||
1283 | |||
1284 | |||
1285 | /** | ||
1286 | * @brief Check whether flags on a channel are set. | ||
1287 | * | ||
1288 | * @param channel the channel to check the flag of | ||
1289 | * @param flags the flags to check | ||
1290 | * | ||
1291 | * @return #GNUNET_YES if all given flags are set | ||
1292 | * #GNUNET_NO otherwise | ||
1293 | */ | ||
1294 | int | ||
1295 | Peers_check_channel_flag (uint32_t *channel_flags, enum Peers_ChannelFlags flags) | ||
1296 | { | ||
1297 | return check_channel_flag_set (channel_flags, flags); | ||
1298 | } | ||
1299 | |||
1300 | /** | ||
1301 | * @brief Get the flags for the channel in @a role for @a peer. | ||
1302 | * | ||
1303 | * @param peer Peer to get the channel flags for. | ||
1304 | * @param role Role of channel to get flags for | ||
1305 | * | ||
1306 | * @return The flags. | ||
1307 | */ | ||
1308 | uint32_t * | ||
1309 | Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer, | ||
1310 | enum Peers_ChannelRole role) | ||
1311 | { | ||
1312 | const struct PeerContext *peer_ctx; | ||
1313 | |||
1314 | peer_ctx = get_peer_ctx (peer); | ||
1315 | if (Peers_CHANNEL_ROLE_SENDING == role) | ||
1316 | { | ||
1317 | return peer_ctx->send_channel_flags; | ||
1318 | } | ||
1319 | else if (Peers_CHANNEL_ROLE_RECEIVING == role) | ||
1320 | { | ||
1321 | return peer_ctx->recv_channel_flags; | ||
1322 | } | ||
1323 | else | ||
1324 | { | ||
1325 | GNUNET_assert (0); | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | /** | ||
1330 | * @brief Check whether we have information about the given peer. | ||
1331 | * | ||
1332 | * FIXME probably deprecated. Make this the new _online. | ||
1333 | * | ||
1334 | * @param peer peer in question | ||
1335 | * | ||
1336 | * @return #GNUNET_YES if peer is known | ||
1337 | * #GNUNET_NO if peer is not knwon | ||
1338 | */ | ||
1339 | int | ||
1340 | Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer) | ||
1341 | { | ||
1342 | return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer); | ||
1343 | } | ||
1344 | |||
1345 | |||
1346 | /** | ||
1347 | * @brief Check whether @a peer is actually a peer. | ||
1348 | * | ||
1349 | * A valid peer is a peer that we know exists eg. we were connected to once. | ||
1350 | * | ||
1351 | * @param peer peer in question | ||
1352 | * | ||
1353 | * @return #GNUNET_YES if peer is valid | ||
1354 | * #GNUNET_NO if peer is not valid | ||
1355 | */ | ||
1356 | int | ||
1357 | Peers_check_peer_valid (const struct GNUNET_PeerIdentity *peer) | ||
1358 | { | ||
1359 | return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer); | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | /** | ||
1364 | * @brief Indicate that we want to send to the other peer | ||
1365 | * | ||
1366 | * This establishes a sending channel | ||
1367 | * | ||
1368 | * @param peer the peer to establish channel to | ||
1369 | */ | ||
1370 | void | ||
1371 | Peers_indicate_sending_intention (const struct GNUNET_PeerIdentity *peer) | ||
1372 | { | ||
1373 | GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer)); | ||
1374 | (void) get_channel (peer); | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | /** | ||
1379 | * @brief Check whether other peer has the intention to send/opened channel | ||
1380 | * towars us | ||
1381 | * | ||
1382 | * @param peer the peer in question | ||
1383 | * | ||
1384 | * @return #GNUNET_YES if peer has the intention to send | ||
1385 | * #GNUNET_NO otherwise | ||
1386 | */ | ||
1387 | int | ||
1388 | Peers_check_peer_send_intention (const struct GNUNET_PeerIdentity *peer) | ||
1389 | { | ||
1390 | const struct PeerContext *peer_ctx; | ||
1391 | |||
1392 | peer_ctx = get_peer_ctx (peer); | ||
1393 | if (NULL != peer_ctx->recv_channel) | ||
1394 | { | ||
1395 | return GNUNET_YES; | ||
1396 | } | ||
1397 | return GNUNET_NO; | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /** | ||
1402 | * Handle the channel a peer opens to us. | ||
1403 | * | ||
1404 | * @param cls The closure | ||
1405 | * @param channel The channel the peer wants to establish | ||
1406 | * @param initiator The peer's peer ID | ||
1407 | * | ||
1408 | * @return initial channel context for the channel | ||
1409 | * (can be NULL -- that's not an error) | ||
1410 | */ | ||
1411 | void * | ||
1412 | Peers_handle_inbound_channel (void *cls, | ||
1413 | struct GNUNET_CADET_Channel *channel, | ||
1414 | const struct GNUNET_PeerIdentity *initiator) | ||
1415 | { | ||
1416 | struct PeerContext *peer_ctx; | ||
1417 | |||
1418 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1419 | "New channel was established to us (Peer %s).\n", | ||
1420 | GNUNET_i2s (initiator)); | ||
1421 | GNUNET_assert (NULL != channel); /* according to cadet API */ | ||
1422 | /* Make sure we 'know' about this peer */ | ||
1423 | peer_ctx = create_or_get_peer_ctx (initiator); | ||
1424 | set_peer_live (peer_ctx); | ||
1425 | /* We only accept one incoming channel per peer */ | ||
1426 | if (GNUNET_YES == Peers_check_peer_send_intention (initiator)) | ||
1427 | { | ||
1428 | set_channel_flag (peer_ctx->recv_channel_flags, | ||
1429 | Peers_CHANNEL_ESTABLISHED_TWICE); | ||
1430 | GNUNET_CADET_channel_destroy (channel); | ||
1431 | /* return the channel context */ | ||
1432 | return &peer_ctx->peer_id; | ||
1433 | } | ||
1434 | peer_ctx->recv_channel = channel; | ||
1435 | return &peer_ctx->peer_id; | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | /** | ||
1440 | * @brief Check whether a sending channel towards the given peer exists | ||
1441 | * | ||
1442 | * @param peer the peer to check for | ||
1443 | * | ||
1444 | * @return #GNUNET_YES if a sending channel towards that peer exists | ||
1445 | * #GNUNET_NO otherwise | ||
1446 | */ | ||
1447 | int | ||
1448 | Peers_check_sending_channel_exists (const struct GNUNET_PeerIdentity *peer) | ||
1449 | { | ||
1450 | struct PeerContext *peer_ctx; | ||
1451 | |||
1452 | if (GNUNET_NO == Peers_check_peer_known (peer)) | ||
1453 | { /* If no such peer exists, there is no channel */ | ||
1454 | return GNUNET_NO; | ||
1455 | } | ||
1456 | peer_ctx = get_peer_ctx (peer); | ||
1457 | if (NULL == peer_ctx->send_channel) | ||
1458 | { | ||
1459 | return GNUNET_NO; | ||
1460 | } | ||
1461 | return GNUNET_YES; | ||
1462 | } | ||
1463 | |||
1464 | |||
1465 | /** | ||
1466 | * @brief check whether the given channel is the sending channel of the given | ||
1467 | * peer | ||
1468 | * | ||
1469 | * @param peer the peer in question | ||
1470 | * @param channel the channel to check for | ||
1471 | * @param role either #Peers_CHANNEL_ROLE_SENDING, or | ||
1472 | * #Peers_CHANNEL_ROLE_RECEIVING | ||
1473 | * | ||
1474 | * @return #GNUNET_YES if the given chennel is the sending channel of the peer | ||
1475 | * #GNUNET_NO otherwise | ||
1476 | */ | ||
1477 | int | ||
1478 | Peers_check_channel_role (const struct GNUNET_PeerIdentity *peer, | ||
1479 | const struct GNUNET_CADET_Channel *channel, | ||
1480 | enum Peers_ChannelRole role) | ||
1481 | { | ||
1482 | const struct PeerContext *peer_ctx; | ||
1483 | |||
1484 | if (GNUNET_NO == Peers_check_peer_known (peer)) | ||
1485 | { | ||
1486 | return GNUNET_NO; | ||
1487 | } | ||
1488 | peer_ctx = get_peer_ctx (peer); | ||
1489 | if ( (Peers_CHANNEL_ROLE_SENDING == role) && | ||
1490 | (channel == peer_ctx->send_channel) ) | ||
1491 | { | ||
1492 | return GNUNET_YES; | ||
1493 | } | ||
1494 | if ( (Peers_CHANNEL_ROLE_RECEIVING == role) && | ||
1495 | (channel == peer_ctx->recv_channel) ) | ||
1496 | { | ||
1497 | return GNUNET_YES; | ||
1498 | } | ||
1499 | return GNUNET_NO; | ||
1500 | } | ||
1501 | |||
1502 | |||
1503 | /** | ||
1504 | * @brief Destroy the send channel of a peer e.g. stop indicating a sending | ||
1505 | * intention to another peer | ||
1506 | * | ||
1507 | * If there is also no channel to receive messages from that peer, remove it | ||
1508 | * from the peermap. | ||
1509 | * TODO really? | ||
1510 | * | ||
1511 | * @peer the peer identity of the peer whose sending channel to destroy | ||
1512 | * @return #GNUNET_YES if channel was destroyed | ||
1513 | * #GNUNET_NO otherwise | ||
1514 | */ | ||
1515 | int | ||
1516 | Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer) | ||
1517 | { | ||
1518 | struct PeerContext *peer_ctx; | ||
1519 | |||
1520 | if (GNUNET_NO == Peers_check_peer_known (peer)) | ||
1521 | { | ||
1522 | return GNUNET_NO; | ||
1523 | } | ||
1524 | peer_ctx = get_peer_ctx (peer); | ||
1525 | if (NULL != peer_ctx->send_channel) | ||
1526 | { | ||
1527 | set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN); | ||
1528 | GNUNET_CADET_channel_destroy (peer_ctx->send_channel); | ||
1529 | peer_ctx->send_channel = NULL; | ||
1530 | (void) Peers_check_connected (peer); | ||
1531 | return GNUNET_YES; | ||
1532 | } | ||
1533 | return GNUNET_NO; | ||
1534 | } | ||
1535 | |||
1536 | /** | ||
1537 | * This is called when a channel is destroyed. | ||
1538 | * | ||
1539 | * @param cls The closure | ||
1540 | * @param channel The channel being closed | ||
1541 | * @param channel_ctx The context associated with this channel | ||
1542 | */ | ||
1543 | void | ||
1544 | Peers_cleanup_destroyed_channel (void *cls, | ||
1545 | const struct GNUNET_CADET_Channel *channel) | ||
1546 | { | ||
1547 | struct GNUNET_PeerIdentity *peer = cls; | ||
1548 | struct PeerContext *peer_ctx; | ||
1549 | |||
1550 | if (GNUNET_NO == Peers_check_peer_known (peer)) | ||
1551 | {/* We don't want to implicitly create a context that we're about to kill */ | ||
1552 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1553 | "channel (%s) without associated context was destroyed\n", | ||
1554 | GNUNET_i2s (peer)); | ||
1555 | return; | ||
1556 | } | ||
1557 | peer_ctx = get_peer_ctx (peer); | ||
1558 | |||
1559 | /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY | ||
1560 | * flag will be set. In this case simply make sure that the channels are | ||
1561 | * cleaned. */ | ||
1562 | /* FIXME This distinction seems to be redundant */ | ||
1563 | if (Peers_check_peer_flag (peer, Peers_TO_DESTROY)) | ||
1564 | {/* We initiatad the destruction of this particular peer */ | ||
1565 | if (channel == peer_ctx->send_channel) | ||
1566 | peer_ctx->send_channel = NULL; | ||
1567 | else if (channel == peer_ctx->recv_channel) | ||
1568 | peer_ctx->recv_channel = NULL; | ||
1569 | |||
1570 | if (NULL != peer_ctx->send_channel) | ||
1571 | { | ||
1572 | GNUNET_CADET_channel_destroy (peer_ctx->send_channel); | ||
1573 | peer_ctx->send_channel = NULL; | ||
1574 | } | ||
1575 | if (NULL != peer_ctx->recv_channel) | ||
1576 | { | ||
1577 | GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); | ||
1578 | peer_ctx->recv_channel = NULL; | ||
1579 | } | ||
1580 | /* Set the #Peers_ONLINE flag accordingly */ | ||
1581 | (void) Peers_check_connected (peer); | ||
1582 | return; | ||
1583 | } | ||
1584 | |||
1585 | else | ||
1586 | { /* We did not initiate the destruction of this peer */ | ||
1587 | if (channel == peer_ctx->send_channel) | ||
1588 | { /* Something (but us) killd the channel - clean up peer */ | ||
1589 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1590 | "send channel (%s) was destroyed - cleaning up\n", | ||
1591 | GNUNET_i2s (peer)); | ||
1592 | peer_ctx->send_channel = NULL; | ||
1593 | } | ||
1594 | else if (channel == peer_ctx->recv_channel) | ||
1595 | { /* Other peer doesn't want to send us messages anymore */ | ||
1596 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1597 | "Peer %s destroyed recv channel - cleaning up channel\n", | ||
1598 | GNUNET_i2s (peer)); | ||
1599 | peer_ctx->recv_channel = NULL; | ||
1600 | } | ||
1601 | else | ||
1602 | { | ||
1603 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1604 | "unknown channel (%s) was destroyed\n", | ||
1605 | GNUNET_i2s (peer)); | ||
1606 | } | ||
1607 | } | ||
1608 | (void) Peers_check_connected (peer); | ||
1609 | } | ||
1610 | |||
1611 | /** | ||
1612 | * @brief Send a message to another peer. | ||
1613 | * | ||
1614 | * Keeps track about pending messages so they can be properly removed when the | ||
1615 | * peer is destroyed. | ||
1616 | * | ||
1617 | * @param peer receeiver of the message | ||
1618 | * @param ev envelope of the message | ||
1619 | * @param type type of the message | ||
1620 | */ | ||
1621 | void | ||
1622 | Peers_send_message (const struct GNUNET_PeerIdentity *peer, | ||
1623 | struct GNUNET_MQ_Envelope *ev, | ||
1624 | const char *type) | ||
1625 | { | ||
1626 | struct PendingMessage *pending_msg; | ||
1627 | struct GNUNET_MQ_Handle *mq; | ||
1628 | |||
1629 | pending_msg = insert_pending_message (peer, ev, type); | ||
1630 | mq = get_mq (peer); | ||
1631 | GNUNET_MQ_notify_sent (ev, | ||
1632 | mq_notify_sent_cb, | ||
1633 | pending_msg); | ||
1634 | GNUNET_MQ_send (mq, ev); | ||
1635 | } | ||
1636 | |||
1637 | /** | ||
1638 | * @brief Schedule a operation on given peer | ||
1639 | * | ||
1640 | * Avoids scheduling an operation twice. | ||
1641 | * | ||
1642 | * @param peer the peer we want to schedule the operation for once it gets live | ||
1643 | * | ||
1644 | * @return #GNUNET_YES if the operation was scheduled | ||
1645 | * #GNUNET_NO otherwise | ||
1646 | */ | ||
1647 | int | ||
1648 | Peers_schedule_operation (const struct GNUNET_PeerIdentity *peer, | ||
1649 | const PeerOp peer_op) | ||
1650 | { | ||
1651 | struct PeerPendingOp pending_op; | ||
1652 | struct PeerContext *peer_ctx; | ||
1653 | |||
1654 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (peer, own_identity)) | ||
1655 | { | ||
1656 | return GNUNET_NO; | ||
1657 | } | ||
1658 | GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer)); | ||
1659 | |||
1660 | //TODO if LIVE/ONLINE execute immediately | ||
1661 | |||
1662 | if (GNUNET_NO == check_operation_scheduled (peer, peer_op)) | ||
1663 | { | ||
1664 | peer_ctx = get_peer_ctx (peer); | ||
1665 | pending_op.op = peer_op; | ||
1666 | pending_op.op_cls = NULL; | ||
1667 | GNUNET_array_append (peer_ctx->pending_ops, | ||
1668 | peer_ctx->num_pending_ops, | ||
1669 | pending_op); | ||
1670 | return GNUNET_YES; | ||
1671 | } | ||
1672 | return GNUNET_NO; | ||
1673 | } | ||
1674 | |||
1675 | /** | ||
1676 | * @brief Get the recv_channel of @a peer. | ||
1677 | * Needed to correctly handle (call #GNUNET_CADET_receive_done()) incoming | ||
1678 | * messages. | ||
1679 | * | ||
1680 | * @param peer The peer to get the recv_channel from. | ||
1681 | * | ||
1682 | * @return The recv_channel. | ||
1683 | */ | ||
1684 | struct GNUNET_CADET_Channel * | ||
1685 | Peers_get_recv_channel (const struct GNUNET_PeerIdentity *peer) | ||
1686 | { | ||
1687 | struct PeerContext *peer_ctx; | ||
1688 | |||
1689 | GNUNET_assert (GNUNET_YES == Peers_check_peer_known (peer)); | ||
1690 | peer_ctx = get_peer_ctx (peer); | ||
1691 | return peer_ctx->recv_channel; | ||
1692 | } | ||
1693 | |||
1694 | /* 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_rps.c b/src/rps/test_rps.c index acd3a165d..0114a19fe 100644 --- a/src/rps/test_rps.c +++ b/src/rps/test_rps.c | |||
@@ -18,7 +18,7 @@ | |||
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file rps/test_rps_multipeer.c | 21 | * @file rps/test_rps.c |
22 | * @brief Testcase for the random peer sampling service. Starts | 22 | * @brief Testcase for the random peer sampling service. Starts |
23 | * a peergroup with a given number of peers, then waits to | 23 | * a peergroup with a given number of peers, then waits to |
24 | * receive size pushes/pulls from each peer. Expects to wait | 24 | * receive size pushes/pulls from each peer. Expects to wait |
@@ -344,6 +344,11 @@ struct SingleTestRun | |||
344 | * Number of Requests to make. | 344 | * Number of Requests to make. |
345 | */ | 345 | */ |
346 | uint32_t num_requests; | 346 | uint32_t num_requests; |
347 | |||
348 | /** | ||
349 | * Run with churn | ||
350 | */ | ||
351 | int have_churn; | ||
347 | } cur_test_run; | 352 | } cur_test_run; |
348 | 353 | ||
349 | /** | 354 | /** |
@@ -1023,6 +1028,33 @@ req_cancel_cb (struct RPSPeer *rps_peer) | |||
1023 | } | 1028 | } |
1024 | 1029 | ||
1025 | /*********************************** | 1030 | /*********************************** |
1031 | * CHURN | ||
1032 | ***********************************/ | ||
1033 | |||
1034 | static void | ||
1035 | churn (void *cls); | ||
1036 | |||
1037 | static void | ||
1038 | churn_test_cb (struct RPSPeer *rps_peer) | ||
1039 | { | ||
1040 | /* Start churn */ | ||
1041 | if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task) | ||
1042 | { | ||
1043 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1044 | "Starting churn task\n"); | ||
1045 | churn_task = GNUNET_SCHEDULER_add_delayed ( | ||
1046 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), | ||
1047 | churn, | ||
1048 | NULL); | ||
1049 | } else { | ||
1050 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1051 | "Not starting churn task\n"); | ||
1052 | } | ||
1053 | |||
1054 | schedule_missing_requests (rps_peer); | ||
1055 | } | ||
1056 | |||
1057 | /*********************************** | ||
1026 | * PROFILER | 1058 | * PROFILER |
1027 | ***********************************/ | 1059 | ***********************************/ |
1028 | 1060 | ||
@@ -1148,6 +1180,9 @@ churn (void *cls) | |||
1148 | double portion_go_online; | 1180 | double portion_go_online; |
1149 | double portion_go_offline; | 1181 | double portion_go_offline; |
1150 | 1182 | ||
1183 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1184 | "Churn function executing\n"); | ||
1185 | |||
1151 | /* Compute the probability for an online peer to go offline | 1186 | /* Compute the probability for an online peer to go offline |
1152 | * this round */ | 1187 | * this round */ |
1153 | portion_online = num_peers_online * 1.0 / num_peers; | 1188 | portion_online = num_peers_online * 1.0 / num_peers; |
@@ -1256,12 +1291,17 @@ static void | |||
1256 | profiler_cb (struct RPSPeer *rps_peer) | 1291 | profiler_cb (struct RPSPeer *rps_peer) |
1257 | { | 1292 | { |
1258 | /* Start churn */ | 1293 | /* Start churn */ |
1259 | if (NULL == churn_task) | 1294 | if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task) |
1260 | { | 1295 | { |
1296 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1297 | "Starting churn task\n"); | ||
1261 | churn_task = GNUNET_SCHEDULER_add_delayed ( | 1298 | churn_task = GNUNET_SCHEDULER_add_delayed ( |
1262 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), | 1299 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), |
1263 | churn, | 1300 | churn, |
1264 | NULL); | 1301 | NULL); |
1302 | } else { | ||
1303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1304 | "Not starting churn task\n"); | ||
1265 | } | 1305 | } |
1266 | 1306 | ||
1267 | /* Only request peer ids at one peer. | 1307 | /* Only request peer ids at one peer. |
@@ -1353,6 +1393,24 @@ run (void *cls, | |||
1353 | struct OpListEntry *entry; | 1393 | struct OpListEntry *entry; |
1354 | uint32_t num_mal_peers; | 1394 | uint32_t num_mal_peers; |
1355 | 1395 | ||
1396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RUN was called\n"); | ||
1397 | |||
1398 | /* Check whether we timed out */ | ||
1399 | if (n_peers != num_peers || | ||
1400 | NULL == peers || | ||
1401 | 0 == links_succeeded) | ||
1402 | { | ||
1403 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Going down due to args (eg. timeout)\n"); | ||
1404 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tn_peers: %u\n", n_peers); | ||
1405 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tnum_peers: %" PRIu32 "\n", num_peers); | ||
1406 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tpeers: %p\n", peers); | ||
1407 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tlinks_succeeded: %u\n", links_succeeded); | ||
1408 | GNUNET_SCHEDULER_shutdown (); | ||
1409 | return; | ||
1410 | } | ||
1411 | |||
1412 | |||
1413 | /* Initialize peers */ | ||
1356 | testbed_peers = peers; | 1414 | testbed_peers = peers; |
1357 | num_peers_online = 0; | 1415 | num_peers_online = 0; |
1358 | for (i = 0; i < num_peers; i++) | 1416 | for (i = 0; i < num_peers; i++) |
@@ -1412,6 +1470,7 @@ main (int argc, char *argv[]) | |||
1412 | cur_test_run.pre_test = NULL; | 1470 | cur_test_run.pre_test = NULL; |
1413 | cur_test_run.reply_handle = default_reply_handle; | 1471 | cur_test_run.reply_handle = default_reply_handle; |
1414 | cur_test_run.eval_cb = default_eval_cb; | 1472 | cur_test_run.eval_cb = default_eval_cb; |
1473 | cur_test_run.have_churn = GNUNET_YES; | ||
1415 | churn_task = NULL; | 1474 | churn_task = NULL; |
1416 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); | 1475 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); |
1417 | 1476 | ||
@@ -1446,6 +1505,7 @@ main (int argc, char *argv[]) | |||
1446 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n"); | 1505 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n"); |
1447 | cur_test_run.name = "test-rps-single-req"; | 1506 | cur_test_run.name = "test-rps-single-req"; |
1448 | cur_test_run.main_test = single_req_cb; | 1507 | cur_test_run.main_test = single_req_cb; |
1508 | cur_test_run.have_churn = GNUNET_NO; | ||
1449 | } | 1509 | } |
1450 | 1510 | ||
1451 | else if (strstr (argv[0], "_delayed_reqs") != NULL) | 1511 | else if (strstr (argv[0], "_delayed_reqs") != NULL) |
@@ -1453,6 +1513,7 @@ main (int argc, char *argv[]) | |||
1453 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n"); | 1513 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n"); |
1454 | cur_test_run.name = "test-rps-delayed-reqs"; | 1514 | cur_test_run.name = "test-rps-delayed-reqs"; |
1455 | cur_test_run.main_test = delay_req_cb; | 1515 | cur_test_run.main_test = delay_req_cb; |
1516 | cur_test_run.have_churn = GNUNET_NO; | ||
1456 | } | 1517 | } |
1457 | 1518 | ||
1458 | else if (strstr (argv[0], "_seed_big") != NULL) | 1519 | else if (strstr (argv[0], "_seed_big") != NULL) |
@@ -1462,6 +1523,7 @@ main (int argc, char *argv[]) | |||
1462 | cur_test_run.name = "test-rps-seed-big"; | 1523 | cur_test_run.name = "test-rps-seed-big"; |
1463 | cur_test_run.main_test = seed_big_cb; | 1524 | cur_test_run.main_test = seed_big_cb; |
1464 | cur_test_run.eval_cb = no_eval; | 1525 | cur_test_run.eval_cb = no_eval; |
1526 | cur_test_run.have_churn = GNUNET_NO; | ||
1465 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); | 1527 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); |
1466 | } | 1528 | } |
1467 | 1529 | ||
@@ -1470,6 +1532,7 @@ main (int argc, char *argv[]) | |||
1470 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n"); | 1532 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n"); |
1471 | cur_test_run.name = "test-rps-single-peer-seed"; | 1533 | cur_test_run.name = "test-rps-single-peer-seed"; |
1472 | cur_test_run.main_test = single_peer_seed_cb; | 1534 | cur_test_run.main_test = single_peer_seed_cb; |
1535 | cur_test_run.have_churn = GNUNET_NO; | ||
1473 | } | 1536 | } |
1474 | 1537 | ||
1475 | else if (strstr (argv[0], "_seed_request") != NULL) | 1538 | else if (strstr (argv[0], "_seed_request") != NULL) |
@@ -1477,6 +1540,7 @@ main (int argc, char *argv[]) | |||
1477 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n"); | 1540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n"); |
1478 | cur_test_run.name = "test-rps-seed-request"; | 1541 | cur_test_run.name = "test-rps-seed-request"; |
1479 | cur_test_run.main_test = seed_req_cb; | 1542 | cur_test_run.main_test = seed_req_cb; |
1543 | cur_test_run.have_churn = GNUNET_NO; | ||
1480 | } | 1544 | } |
1481 | 1545 | ||
1482 | else if (strstr (argv[0], "_seed") != NULL) | 1546 | else if (strstr (argv[0], "_seed") != NULL) |
@@ -1485,6 +1549,7 @@ main (int argc, char *argv[]) | |||
1485 | cur_test_run.name = "test-rps-seed"; | 1549 | cur_test_run.name = "test-rps-seed"; |
1486 | cur_test_run.main_test = seed_cb; | 1550 | cur_test_run.main_test = seed_cb; |
1487 | cur_test_run.eval_cb = no_eval; | 1551 | cur_test_run.eval_cb = no_eval; |
1552 | cur_test_run.have_churn = GNUNET_NO; | ||
1488 | } | 1553 | } |
1489 | 1554 | ||
1490 | else if (strstr (argv[0], "_req_cancel") != NULL) | 1555 | else if (strstr (argv[0], "_req_cancel") != NULL) |
@@ -1494,6 +1559,20 @@ main (int argc, char *argv[]) | |||
1494 | num_peers = 1; | 1559 | num_peers = 1; |
1495 | cur_test_run.main_test = req_cancel_cb; | 1560 | cur_test_run.main_test = req_cancel_cb; |
1496 | cur_test_run.eval_cb = no_eval; | 1561 | cur_test_run.eval_cb = no_eval; |
1562 | cur_test_run.have_churn = GNUNET_NO; | ||
1563 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); | ||
1564 | } | ||
1565 | |||
1566 | else if (strstr (argv[0], "_churn") != NULL) | ||
1567 | { | ||
1568 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test churn\n"); | ||
1569 | cur_test_run.name = "test-rps-churn"; | ||
1570 | num_peers = 5; | ||
1571 | cur_test_run.init_peer = default_init_peer; | ||
1572 | cur_test_run.main_test = churn_test_cb; | ||
1573 | cur_test_run.reply_handle = default_reply_handle; | ||
1574 | cur_test_run.eval_cb = default_eval_cb; | ||
1575 | cur_test_run.have_churn = GNUNET_YES; | ||
1497 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); | 1576 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); |
1498 | } | 1577 | } |
1499 | 1578 | ||
@@ -1510,6 +1589,7 @@ main (int argc, char *argv[]) | |||
1510 | cur_test_run.eval_cb = profiler_eval; | 1589 | cur_test_run.eval_cb = profiler_eval; |
1511 | cur_test_run.request_interval = 2; | 1590 | cur_test_run.request_interval = 2; |
1512 | cur_test_run.num_requests = 5; | 1591 | cur_test_run.num_requests = 5; |
1592 | cur_test_run.have_churn = GNUNET_YES; | ||
1513 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90); | 1593 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90); |
1514 | 1594 | ||
1515 | /* 'Clean' directory */ | 1595 | /* 'Clean' directory */ |
@@ -1542,4 +1622,4 @@ main (int argc, char *argv[]) | |||
1542 | return ret_value; | 1622 | return ret_value; |
1543 | } | 1623 | } |
1544 | 1624 | ||
1545 | /* end of test_rps_multipeer.c */ | 1625 | /* end of test_rps.c */ |
diff --git a/src/rps/test_rps.conf b/src/rps/test_rps.conf index 7da91ccf0..fce07c945 100644 --- a/src/rps/test_rps.conf +++ b/src/rps/test_rps.conf | |||
@@ -24,16 +24,16 @@ INITSIZE = 4 | |||
24 | [testbed] | 24 | [testbed] |
25 | HOSTNAME = localhost | 25 | HOSTNAME = localhost |
26 | 26 | ||
27 | OPERATION_TIMEOUT = 60 s | 27 | # OPERATION_TIMEOUT = 60 s |
28 | 28 | ||
29 | MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 1 | 29 | # MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 100 |
30 | #OVERLAY_TOPOLOGY = CLIQUE | 30 | OVERLAY_TOPOLOGY = CLIQUE |
31 | OVERLAY_TOPOLOGY = SMALL_WORLD | 31 | #OVERLAY_TOPOLOGY = SMALL_WORLD |
32 | #SCALE_FREE_TOPOLOGY_CAP = | 32 | #SCALE_FREE_TOPOLOGY_CAP = |
33 | 33 | ||
34 | OVERLAY_RANDOM_LINKS = 25 | 34 | # OVERLAY_RANDOM_LINKS = 25 |
35 | 35 | ||
36 | SETUP_TIMEOUT = 2 m | 36 | # SETUP_TIMEOUT = 2 m |
37 | 37 | ||
38 | [nse] | 38 | [nse] |
39 | WORKBITS = 0 | 39 | WORKBITS = 0 |
@@ -46,7 +46,27 @@ USE_LOCALADDR = YES | |||
46 | RETURN_LOCAL_ADDRESSES = YES | 46 | RETURN_LOCAL_ADDRESSES = YES |
47 | 47 | ||
48 | [transport] | 48 | [transport] |
49 | PLUGINS = unix | 49 | PLUGINS = udp |
50 | |||
51 | [ats] | ||
52 | # Network specific inbound/outbound quotas | ||
53 | UNSPECIFIED_QUOTA_IN = unlimited | ||
54 | UNSPECIFIED_QUOTA_OUT = unlimited | ||
55 | # LOOPBACK | ||
56 | LOOPBACK_QUOTA_IN = unlimited | ||
57 | LOOPBACK_QUOTA_OUT = unlimited | ||
58 | # LAN | ||
59 | LAN_QUOTA_IN = unlimited | ||
60 | LAN_QUOTA_OUT = unlimited | ||
61 | #WAN | ||
62 | WAN_QUOTA_OUT = unlimited | ||
63 | WAN_QUOTA_IN = unlimited | ||
64 | # WLAN | ||
65 | WLAN_QUOTA_IN = unlimited | ||
66 | WLAN_QUOTA_OUT = unlimited | ||
67 | # BLUETOOTH | ||
68 | BLUETOOTH_QUOTA_IN = unlimited | ||
69 | BLUETOOTH_QUOTA_OUT = unlimited | ||
50 | 70 | ||
51 | [dht] | 71 | [dht] |
52 | DISABLE_TRY_CONNECT = YES | 72 | DISABLE_TRY_CONNECT = YES |
@@ -69,6 +89,10 @@ NO_IO = YES | |||
69 | FORCESTART = NO | 89 | FORCESTART = NO |
70 | AUTOSTART = NO | 90 | AUTOSTART = NO |
71 | 91 | ||
92 | [zonemaster] | ||
93 | FORCESTART = NO | ||
94 | AUTOSTART = NO | ||
95 | |||
72 | [namecache] | 96 | [namecache] |
73 | FORCESTART = NO | 97 | FORCESTART = NO |
74 | AUTOSTART = NO | 98 | AUTOSTART = NO |
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 */ | ||