diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_peer.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_peer.c | 1609 |
1 files changed, 0 insertions, 1609 deletions
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c deleted file mode 100644 index 2437a3e1b..000000000 --- a/src/cadet/gnunet-service-cadet_peer.c +++ /dev/null | |||
@@ -1,1609 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_peer.c | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * TODO: | ||
28 | * - optimize stopping/restarting DHT search to situations | ||
29 | * where we actually need it (i.e. not if we have a direct connection, | ||
30 | * or if we already have plenty of good short ones, or maybe even | ||
31 | * to take a break if we have some connections and have searched a lot (?)) | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet_time_lib.h" | ||
35 | #include "gnunet_util_lib.h" | ||
36 | #include "gnunet_hello_lib.h" | ||
37 | #include "gnunet_signatures.h" | ||
38 | #include "gnunet_transport_service.h" | ||
39 | #include "gnunet_ats_service.h" | ||
40 | #include "gnunet_core_service.h" | ||
41 | #include "gnunet_statistics_service.h" | ||
42 | #include "gnunet-service-cadet_peer.h" | ||
43 | #include "gnunet-service-cadet.h" | ||
44 | #include "gnunet-service-cadet_connection.h" | ||
45 | #include "gnunet-service-cadet_dht.h" | ||
46 | #include "gnunet-service-cadet_paths.h" | ||
47 | #include "gnunet-service-cadet_tunnels.h" | ||
48 | |||
49 | |||
50 | #define LOG(level, ...) GNUNET_log_from (level, "cadet-per", __VA_ARGS__) | ||
51 | |||
52 | |||
53 | /** | ||
54 | * How long do we wait until tearing down an idle peer? | ||
55 | */ | ||
56 | #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
57 | GNUNET_TIME_UNIT_MINUTES, 5) | ||
58 | |||
59 | /** | ||
60 | * How long do we keep paths around if we no longer care about the peer? | ||
61 | */ | ||
62 | #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply ( \ | ||
63 | GNUNET_TIME_UNIT_MINUTES, 2) | ||
64 | |||
65 | /** | ||
66 | * Queue size when we start dropping OOO messages. | ||
67 | */ | ||
68 | #define MAX_OOO_QUEUE_SIZE 100 | ||
69 | |||
70 | /** | ||
71 | * Data structure used to track whom we have to notify about changes | ||
72 | * to our message queue. | ||
73 | */ | ||
74 | struct GCP_MessageQueueManager | ||
75 | { | ||
76 | /** | ||
77 | * Kept in a DLL. | ||
78 | */ | ||
79 | struct GCP_MessageQueueManager *next; | ||
80 | |||
81 | /** | ||
82 | * Kept in a DLL. | ||
83 | */ | ||
84 | struct GCP_MessageQueueManager *prev; | ||
85 | |||
86 | /** | ||
87 | * Function to call with updated message queue object. | ||
88 | */ | ||
89 | GCP_MessageQueueNotificationCallback cb; | ||
90 | |||
91 | /** | ||
92 | * Closure for @e cb. | ||
93 | */ | ||
94 | void *cb_cls; | ||
95 | |||
96 | /** | ||
97 | * The peer this is for. | ||
98 | */ | ||
99 | struct CadetPeer *cp; | ||
100 | |||
101 | /** | ||
102 | * Envelope this manager would like to transmit once it is its turn. | ||
103 | */ | ||
104 | struct GNUNET_MQ_Envelope *env; | ||
105 | }; | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Struct containing all information regarding a given peer | ||
110 | */ | ||
111 | struct CadetPeer | ||
112 | { | ||
113 | /** | ||
114 | * ID of the peer | ||
115 | */ | ||
116 | struct GNUNET_PeerIdentity pid; | ||
117 | |||
118 | /** | ||
119 | * Last time we heard from this peer (currently not used!) | ||
120 | */ | ||
121 | struct GNUNET_TIME_Absolute last_connection_create; | ||
122 | |||
123 | /** | ||
124 | * Array of DLLs of paths traversing the peer, organized by the | ||
125 | * offset of the peer on the larger path. | ||
126 | */ | ||
127 | struct CadetPeerPathEntry **path_heads; | ||
128 | |||
129 | /** | ||
130 | * Array of DLL of paths traversing the peer, organized by the | ||
131 | * offset of the peer on the larger path. | ||
132 | */ | ||
133 | struct CadetPeerPathEntry **path_tails; | ||
134 | |||
135 | /** | ||
136 | * Notifications to call when @e core_mq changes. | ||
137 | */ | ||
138 | struct GCP_MessageQueueManager *mqm_head; | ||
139 | |||
140 | /** | ||
141 | * Notifications to call when @e core_mq changes. | ||
142 | */ | ||
143 | struct GCP_MessageQueueManager *mqm_tail; | ||
144 | |||
145 | /** | ||
146 | * Pointer to first "ready" entry in @e mqm_head. | ||
147 | */ | ||
148 | struct GCP_MessageQueueManager *mqm_ready_ptr; | ||
149 | |||
150 | /** | ||
151 | * MIN-heap of paths owned by this peer (they also end at this | ||
152 | * peer). Ordered by desirability. | ||
153 | */ | ||
154 | struct GNUNET_CONTAINER_Heap *path_heap; | ||
155 | |||
156 | /** | ||
157 | * Handle to stop the DHT search for paths to this peer | ||
158 | */ | ||
159 | struct GCD_search_handle *search_h; | ||
160 | |||
161 | /** | ||
162 | * Task to clean up @e path_heap asynchronously. | ||
163 | */ | ||
164 | struct GNUNET_SCHEDULER_Task *heap_cleanup_task; | ||
165 | |||
166 | /** | ||
167 | * Task to destroy this entry. | ||
168 | */ | ||
169 | struct GNUNET_SCHEDULER_Task *destroy_task; | ||
170 | |||
171 | /** | ||
172 | * Tunnel to this peer, if any. | ||
173 | */ | ||
174 | struct CadetTunnel *t; | ||
175 | |||
176 | /** | ||
177 | * Connections that go through this peer; indexed by tid. | ||
178 | */ | ||
179 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
180 | |||
181 | /** | ||
182 | * Handle for core transmissions. | ||
183 | */ | ||
184 | struct GNUNET_MQ_Handle *core_mq; | ||
185 | |||
186 | /** | ||
187 | * Hello message of the peer. | ||
188 | */ | ||
189 | struct GNUNET_HELLO_Message *hello; | ||
190 | |||
191 | /** | ||
192 | * Handle to us offering the HELLO to the transport. | ||
193 | */ | ||
194 | struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer; | ||
195 | |||
196 | /** | ||
197 | * Handle to our ATS request asking ATS to suggest an address | ||
198 | * to TRANSPORT for this peer (to establish a direct link). | ||
199 | */ | ||
200 | struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion; | ||
201 | |||
202 | /** | ||
203 | * How many messages are in the queue to this peer. | ||
204 | */ | ||
205 | unsigned int queue_n; | ||
206 | |||
207 | /** | ||
208 | * How many paths do we have to this peer (in all @e path_heads DLLs combined). | ||
209 | */ | ||
210 | unsigned int num_paths; | ||
211 | |||
212 | /** | ||
213 | * Sum over all of the offsets of all of the paths in the @a path_heads DLLs. | ||
214 | * Used to speed-up @GCP_get_desirability_of_path() calculation. | ||
215 | */ | ||
216 | unsigned int off_sum; | ||
217 | |||
218 | /** | ||
219 | * Number of message queue managers of this peer that have a message in waiting. | ||
220 | * | ||
221 | * Used to quickly see if we need to bother scanning the @e msm_head DLL. | ||
222 | * TODO: could be replaced by another DLL that would then allow us to avoid | ||
223 | * the O(n)-scan of the DLL for ready entries! | ||
224 | */ | ||
225 | unsigned int mqm_ready_counter; | ||
226 | |||
227 | /** | ||
228 | * Current length of the @e path_heads and @path_tails arrays. | ||
229 | * The arrays should be grown as needed. | ||
230 | */ | ||
231 | unsigned int path_dll_length; | ||
232 | }; | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Get the static string for a peer ID. | ||
237 | * | ||
238 | * @param cp Peer. | ||
239 | * @return Static string for it's ID. | ||
240 | */ | ||
241 | const char * | ||
242 | GCP_2s (const struct CadetPeer *cp) | ||
243 | { | ||
244 | static char buf[5]; | ||
245 | char *ret; | ||
246 | |||
247 | if ((NULL == cp) || | ||
248 | (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key))) | ||
249 | return "NULL"; | ||
250 | |||
251 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key); | ||
252 | if (NULL == ret) | ||
253 | return "NULL"; | ||
254 | |||
255 | GNUNET_strlcpy (buf, | ||
256 | ret, | ||
257 | sizeof(buf)); | ||
258 | GNUNET_free (ret); | ||
259 | return buf; | ||
260 | } | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Calculate how desirable a path is for @a cp if @a cp | ||
265 | * is at offset @a off. | ||
266 | * | ||
267 | * The 'desirability_table.c' program can be used to compute a list of | ||
268 | * sample outputs for different scenarios. Basically, we score paths | ||
269 | * lower if there are many alternatives, and higher if they are | ||
270 | * shorter than average, and very high if they are much shorter than | ||
271 | * average and without many alternatives. | ||
272 | * | ||
273 | * @param cp a peer reachable via a path | ||
274 | * @param off offset of @a cp in the path | ||
275 | * @return score how useful a path is to reach @a cp, | ||
276 | * positive scores mean path is more desirable | ||
277 | */ | ||
278 | double | ||
279 | GCP_get_desirability_of_path (struct CadetPeer *cp, | ||
280 | unsigned int off) | ||
281 | { | ||
282 | unsigned int num_alts = cp->num_paths; | ||
283 | unsigned int off_sum; | ||
284 | double avg_sum; | ||
285 | double path_delta; | ||
286 | double weight_alts; | ||
287 | |||
288 | GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */ | ||
289 | GNUNET_assert (0 != cp->path_dll_length); | ||
290 | |||
291 | /* We maintain 'off_sum' in 'peer' and thereby | ||
292 | avoid the SLOW recalculation each time. Kept here | ||
293 | just to document what is going on. */ | ||
294 | #if SLOW | ||
295 | off_sum = 0; | ||
296 | for (unsigned int j = 0; j < cp->path_dll_length; j++) | ||
297 | for (struct CadetPeerPathEntry *pe = cp->path_heads[j]; | ||
298 | NULL != pe; | ||
299 | pe = pe->next) | ||
300 | off_sum += j; | ||
301 | GNUNET_assert (off_sum == cp->off_sum); | ||
302 | #else | ||
303 | off_sum = cp->off_sum; | ||
304 | #endif | ||
305 | avg_sum = off_sum * 1.0 / cp->path_dll_length; | ||
306 | path_delta = off - avg_sum; | ||
307 | /* path_delta positive: path off of peer above average (bad path for peer), | ||
308 | path_delta negative: path off of peer below average (good path for peer) */ | ||
309 | if (path_delta <= -1.0) | ||
310 | weight_alts = -num_alts / path_delta; /* discount alternative paths */ | ||
311 | else if (path_delta >= 1.0) | ||
312 | weight_alts = num_alts * path_delta; /* overcount alternative paths */ | ||
313 | else | ||
314 | weight_alts = num_alts; /* count alternative paths normally */ | ||
315 | |||
316 | |||
317 | /* off+1: long paths are generally harder to find and thus count | ||
318 | a bit more as they get longer. However, above-average paths | ||
319 | still need to count less, hence the squaring of that factor. */ | ||
320 | return (off + 1.0) / (weight_alts * weight_alts); | ||
321 | } | ||
322 | |||
323 | |||
324 | /** | ||
325 | * This peer is no longer be needed, clean it up now. | ||
326 | * | ||
327 | * @param cls peer to clean up | ||
328 | */ | ||
329 | static void | ||
330 | destroy_peer (void *cls) | ||
331 | { | ||
332 | struct CadetPeer *cp = cls; | ||
333 | |||
334 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
335 | "Destroying state about peer %s\n", | ||
336 | GCP_2s (cp)); | ||
337 | cp->destroy_task = NULL; | ||
338 | GNUNET_assert (NULL == cp->t); | ||
339 | GNUNET_assert (NULL == cp->core_mq); | ||
340 | GNUNET_assert (0 == cp->num_paths); | ||
341 | for (unsigned int i = 0; i < cp->path_dll_length; i++) | ||
342 | GNUNET_assert (NULL == cp->path_heads[i]); | ||
343 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)); | ||
344 | GNUNET_assert (GNUNET_YES == | ||
345 | GNUNET_CONTAINER_multipeermap_remove (peers, | ||
346 | &cp->pid, | ||
347 | cp)); | ||
348 | GNUNET_free (cp->path_heads); | ||
349 | GNUNET_free (cp->path_tails); | ||
350 | cp->path_dll_length = 0; | ||
351 | if (NULL != cp->search_h) | ||
352 | { | ||
353 | GCD_search_stop (cp->search_h); | ||
354 | cp->search_h = NULL; | ||
355 | } | ||
356 | /* FIXME: clean up search_delayedXXX! */ | ||
357 | |||
358 | if (NULL != cp->hello_offer) | ||
359 | { | ||
360 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
361 | cp->hello_offer = NULL; | ||
362 | } | ||
363 | if (NULL != cp->connectivity_suggestion) | ||
364 | { | ||
365 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
366 | cp->connectivity_suggestion = NULL; | ||
367 | } | ||
368 | GNUNET_CONTAINER_multishortmap_destroy (cp->connections); | ||
369 | if (NULL != cp->path_heap) | ||
370 | { | ||
371 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
372 | cp->path_heap = NULL; | ||
373 | } | ||
374 | if (NULL != cp->heap_cleanup_task) | ||
375 | { | ||
376 | GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task); | ||
377 | cp->heap_cleanup_task = NULL; | ||
378 | } | ||
379 | GNUNET_free (cp->hello); | ||
380 | /* Peer should not be freed if paths exist; if there are no paths, | ||
381 | there ought to be no connections, and without connections, no | ||
382 | notifications. Thus we can assert that mqm_head is empty at this | ||
383 | point. */ | ||
384 | GNUNET_assert (NULL == cp->mqm_head); | ||
385 | GNUNET_assert (NULL == cp->mqm_ready_ptr); | ||
386 | GNUNET_free (cp); | ||
387 | } | ||
388 | |||
389 | |||
390 | /** | ||
391 | * This peer is now on more "active" duty, activate processes related to it. | ||
392 | * | ||
393 | * @param cp the more-active peer | ||
394 | */ | ||
395 | static void | ||
396 | consider_peer_activate (struct CadetPeer *cp) | ||
397 | { | ||
398 | uint32_t strength; | ||
399 | |||
400 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
401 | "Updating peer %s activation state (%u connections)%s%s\n", | ||
402 | GCP_2s (cp), | ||
403 | GNUNET_CONTAINER_multishortmap_size (cp->connections), | ||
404 | (NULL == cp->t) ? "" : " with tunnel", | ||
405 | (NULL == cp->core_mq) ? "" : " with CORE link"); | ||
406 | if (NULL != cp->destroy_task) | ||
407 | { | ||
408 | /* It's active, do not destroy! */ | ||
409 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
410 | cp->destroy_task = NULL; | ||
411 | } | ||
412 | if ((0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
413 | (NULL == cp->t)) | ||
414 | { | ||
415 | /* We're just on a path or directly connected; don't bother too much */ | ||
416 | if (NULL != cp->connectivity_suggestion) | ||
417 | { | ||
418 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
419 | cp->connectivity_suggestion = NULL; | ||
420 | } | ||
421 | if (NULL != cp->search_h) | ||
422 | { | ||
423 | GCD_search_stop (cp->search_h); | ||
424 | cp->search_h = NULL; | ||
425 | } | ||
426 | return; | ||
427 | } | ||
428 | if (NULL == cp->core_mq) | ||
429 | { | ||
430 | /* Lacks direct connection, try to create one by querying the DHT */ | ||
431 | if ((NULL == cp->search_h) && | ||
432 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths)) | ||
433 | cp->search_h | ||
434 | = GCD_search (&cp->pid); | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | /* Have direct connection, stop DHT search if active */ | ||
439 | if (NULL != cp->search_h) | ||
440 | { | ||
441 | GCD_search_stop (cp->search_h); | ||
442 | cp->search_h = NULL; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /* If we have a tunnel, our urge for connections is much bigger */ | ||
447 | strength = (NULL != cp->t) ? 32 : 1; | ||
448 | if (NULL != cp->connectivity_suggestion) | ||
449 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
450 | cp->connectivity_suggestion | ||
451 | = GNUNET_ATS_connectivity_suggest (ats_ch, | ||
452 | &cp->pid, | ||
453 | strength); | ||
454 | } | ||
455 | |||
456 | |||
457 | /** | ||
458 | * This peer may no longer be needed, consider cleaning it up. | ||
459 | * | ||
460 | * @param cp peer to clean up | ||
461 | */ | ||
462 | static void | ||
463 | consider_peer_destroy (struct CadetPeer *cp); | ||
464 | |||
465 | |||
466 | /** | ||
467 | * We really no longere care about a peer, stop hogging memory with paths to it. | ||
468 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
469 | * | ||
470 | * @param cls a `struct CadetPeer`. | ||
471 | */ | ||
472 | static void | ||
473 | drop_paths (void *cls) | ||
474 | { | ||
475 | struct CadetPeer *cp = cls; | ||
476 | struct CadetPeerPath *path; | ||
477 | |||
478 | cp->destroy_task = NULL; | ||
479 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
480 | GCPP_release (path); | ||
481 | consider_peer_destroy (cp); | ||
482 | } | ||
483 | |||
484 | |||
485 | /** | ||
486 | * This peer may no longer be needed, consider cleaning it up. | ||
487 | * | ||
488 | * @param cp peer to clean up | ||
489 | */ | ||
490 | static void | ||
491 | consider_peer_destroy (struct CadetPeer *cp) | ||
492 | { | ||
493 | struct GNUNET_TIME_Relative exp; | ||
494 | |||
495 | if (NULL != cp->destroy_task) | ||
496 | { | ||
497 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
498 | cp->destroy_task = NULL; | ||
499 | } | ||
500 | if (NULL != cp->t) | ||
501 | return; /* still relevant! */ | ||
502 | if (NULL != cp->core_mq) | ||
503 | return; /* still relevant! */ | ||
504 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) | ||
505 | return; /* still relevant! */ | ||
506 | if ((NULL != cp->path_heap) && | ||
507 | (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap))) | ||
508 | { | ||
509 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, | ||
510 | &drop_paths, | ||
511 | cp); | ||
512 | return; | ||
513 | } | ||
514 | if (0 != cp->num_paths) | ||
515 | return; /* still relevant! */ | ||
516 | if (NULL != cp->hello) | ||
517 | { | ||
518 | /* relevant only until HELLO expires */ | ||
519 | exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration ( | ||
520 | cp->hello)); | ||
521 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, | ||
522 | &destroy_peer, | ||
523 | cp); | ||
524 | return; | ||
525 | } | ||
526 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, | ||
527 | &destroy_peer, | ||
528 | cp); | ||
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
534 | * | ||
535 | * @param cp peer to modify | ||
536 | * @param mq message queue to set (can be NULL) | ||
537 | */ | ||
538 | void | ||
539 | GCP_set_mq (struct CadetPeer *cp, | ||
540 | struct GNUNET_MQ_Handle *mq) | ||
541 | { | ||
542 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
543 | "Message queue for peer %s is now %p\n", | ||
544 | GCP_2s (cp), | ||
545 | mq); | ||
546 | cp->core_mq = mq; | ||
547 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next; | ||
548 | NULL != mqm; | ||
549 | mqm = next) | ||
550 | { | ||
551 | /* Save next pointer in case mqm gets freed by the callback */ | ||
552 | next = mqm->next; | ||
553 | if (NULL == mq) | ||
554 | { | ||
555 | if (NULL != mqm->env) | ||
556 | { | ||
557 | GNUNET_MQ_discard (mqm->env); | ||
558 | mqm->env = NULL; | ||
559 | mqm->cb (mqm->cb_cls, | ||
560 | GNUNET_SYSERR); | ||
561 | } | ||
562 | else | ||
563 | { | ||
564 | mqm->cb (mqm->cb_cls, | ||
565 | GNUNET_NO); | ||
566 | } | ||
567 | } | ||
568 | else | ||
569 | { | ||
570 | GNUNET_assert (NULL == mqm->env); | ||
571 | mqm->cb (mqm->cb_cls, | ||
572 | GNUNET_YES); | ||
573 | } | ||
574 | } | ||
575 | if ((NULL != mq) || | ||
576 | (NULL != cp->t)) | ||
577 | consider_peer_activate (cp); | ||
578 | else | ||
579 | consider_peer_destroy (cp); | ||
580 | |||
581 | if ((NULL != mq) && | ||
582 | (NULL != cp->t)) | ||
583 | { | ||
584 | /* have a new, direct path to the target, notify tunnel */ | ||
585 | struct CadetPeerPath *path; | ||
586 | |||
587 | path = GCPP_get_path_from_route (1, | ||
588 | &cp->pid); | ||
589 | GCT_consider_path (cp->t, | ||
590 | path, | ||
591 | 0); | ||
592 | } | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * Debug function should NEVER return true in production code, useful to | ||
598 | * simulate losses for testcases. | ||
599 | * | ||
600 | * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. | ||
601 | */ | ||
602 | static int | ||
603 | should_I_drop (void) | ||
604 | { | ||
605 | if (0 == drop_percent) | ||
606 | return GNUNET_NO; | ||
607 | if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
608 | 101) < drop_percent) | ||
609 | return GNUNET_YES; | ||
610 | return GNUNET_NO; | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * Function called when CORE took one of the messages from | ||
616 | * a message queue manager and transmitted it. | ||
617 | * | ||
618 | * @param cls the `struct CadetPeeer` where we made progress | ||
619 | */ | ||
620 | static void | ||
621 | mqm_send_done (void *cls); | ||
622 | |||
623 | |||
624 | /** | ||
625 | * Transmit current envelope from this @a mqm. | ||
626 | * | ||
627 | * @param mqm mqm to transmit message for now | ||
628 | */ | ||
629 | static void | ||
630 | mqm_execute (struct GCP_MessageQueueManager *mqm) | ||
631 | { | ||
632 | struct CadetPeer *cp = mqm->cp; | ||
633 | |||
634 | /* Move ready pointer to the next entry that might be ready. */ | ||
635 | if ((mqm == cp->mqm_ready_ptr) && | ||
636 | (NULL != mqm->next)) | ||
637 | cp->mqm_ready_ptr = mqm->next; | ||
638 | /* Move entry to the end of the DLL, to be fair. */ | ||
639 | if (mqm != cp->mqm_tail) | ||
640 | { | ||
641 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
642 | cp->mqm_tail, | ||
643 | mqm); | ||
644 | GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head, | ||
645 | cp->mqm_tail, | ||
646 | mqm); | ||
647 | } | ||
648 | cp->mqm_ready_counter--; | ||
649 | if (GNUNET_YES == should_I_drop ()) | ||
650 | { | ||
651 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
652 | "DROPPING message to peer %s from MQM %p\n", | ||
653 | GCP_2s (cp), | ||
654 | mqm); | ||
655 | GNUNET_MQ_discard (mqm->env); | ||
656 | mqm->env = NULL; | ||
657 | mqm_send_done (cp); | ||
658 | } | ||
659 | else | ||
660 | { | ||
661 | { | ||
662 | const struct GNUNET_MessageHeader *mh; | ||
663 | |||
664 | mh = GNUNET_MQ_env_get_msg (mqm->env); | ||
665 | switch (ntohs (mh->type)) | ||
666 | { | ||
667 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
668 | { | ||
669 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg | ||
670 | = (const struct GNUNET_CADET_TunnelKeyExchangeMessage *) mh; | ||
671 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
672 | "P2P forwarding KX with ephemeral %s to %s on CID %s\n", | ||
673 | GNUNET_e2s (&msg->ephemeral_key), | ||
674 | GCP_2s (cp), | ||
675 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
676 | } | ||
677 | break; | ||
678 | |||
679 | default: | ||
680 | break; | ||
681 | } | ||
682 | } | ||
683 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
684 | "Sending to peer %s from MQM %p\n", | ||
685 | GCP_2s (cp), | ||
686 | mqm); | ||
687 | GNUNET_MQ_send (cp->core_mq, | ||
688 | mqm->env); | ||
689 | mqm->env = NULL; | ||
690 | } | ||
691 | mqm->cb (mqm->cb_cls, | ||
692 | GNUNET_YES); | ||
693 | } | ||
694 | |||
695 | |||
696 | /** | ||
697 | * Find the next ready message in the queue (starting | ||
698 | * the search from the `cp->mqm_ready_ptr`) and if possible | ||
699 | * execute the transmission. | ||
700 | * | ||
701 | * @param cp peer to try to send the next ready message to | ||
702 | */ | ||
703 | static void | ||
704 | send_next_ready (struct CadetPeer *cp) | ||
705 | { | ||
706 | struct GCP_MessageQueueManager *mqm; | ||
707 | |||
708 | if (0 == cp->mqm_ready_counter) | ||
709 | return; | ||
710 | while ((NULL != (mqm = cp->mqm_ready_ptr)) && | ||
711 | (NULL == mqm->env)) | ||
712 | cp->mqm_ready_ptr = mqm->next; | ||
713 | if (NULL == mqm) | ||
714 | return; /* nothing to do */ | ||
715 | mqm_execute (mqm); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * Function called when CORE took one of the messages from | ||
721 | * a message queue manager and transmitted it. | ||
722 | * | ||
723 | * @param cls the `struct CadetPeeer` where we made progress | ||
724 | */ | ||
725 | static void | ||
726 | mqm_send_done (void *cls) | ||
727 | { | ||
728 | struct CadetPeer *cp = cls; | ||
729 | |||
730 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
731 | "Sending to peer %s completed\n", | ||
732 | GCP_2s (cp)); | ||
733 | send_next_ready (cp); | ||
734 | } | ||
735 | |||
736 | |||
737 | /** | ||
738 | * Send the message in @a env to @a cp. | ||
739 | * | ||
740 | * @param mqm the message queue manager to use for transmission | ||
741 | * @param env envelope with the message to send; must NOT | ||
742 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
743 | */ | ||
744 | void | ||
745 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
746 | struct GNUNET_MQ_Envelope *env) | ||
747 | { | ||
748 | struct CadetPeer *cp = mqm->cp; | ||
749 | |||
750 | GNUNET_assert (NULL != env); | ||
751 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
752 | "Queueing message to peer %s in MQM %p\n", | ||
753 | GCP_2s (cp), | ||
754 | mqm); | ||
755 | GNUNET_assert (NULL != cp->core_mq); | ||
756 | GNUNET_assert (NULL == mqm->env); | ||
757 | GNUNET_MQ_notify_sent (env, | ||
758 | &mqm_send_done, | ||
759 | cp); | ||
760 | mqm->env = env; | ||
761 | cp->mqm_ready_counter++; | ||
762 | if (mqm != cp->mqm_ready_ptr) | ||
763 | cp->mqm_ready_ptr = cp->mqm_head; | ||
764 | if (1 == cp->mqm_ready_counter) | ||
765 | cp->mqm_ready_ptr = mqm; | ||
766 | if (0 != GNUNET_MQ_get_length (cp->core_mq)) | ||
767 | return; | ||
768 | send_next_ready (cp); | ||
769 | } | ||
770 | |||
771 | |||
772 | /** | ||
773 | * Function called to destroy a peer now. | ||
774 | * | ||
775 | * @param cls NULL | ||
776 | * @param pid identity of the peer (unused) | ||
777 | * @param value the `struct CadetPeer` to clean up | ||
778 | * @return #GNUNET_OK (continue to iterate) | ||
779 | */ | ||
780 | static int | ||
781 | destroy_iterator_cb (void *cls, | ||
782 | const struct GNUNET_PeerIdentity *pid, | ||
783 | void *value) | ||
784 | { | ||
785 | struct CadetPeer *cp = value; | ||
786 | |||
787 | if (NULL != cp->destroy_task) | ||
788 | { | ||
789 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
790 | cp->destroy_task = NULL; | ||
791 | } | ||
792 | destroy_peer (cp); | ||
793 | return GNUNET_OK; | ||
794 | } | ||
795 | |||
796 | |||
797 | /** | ||
798 | * Clean up all entries about all peers. | ||
799 | * Must only be called after all tunnels, CORE-connections and | ||
800 | * connections are down. | ||
801 | */ | ||
802 | void | ||
803 | GCP_destroy_all_peers () | ||
804 | { | ||
805 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
806 | "Destroying all peers now\n"); | ||
807 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
808 | &destroy_iterator_cb, | ||
809 | NULL); | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Drop all paths owned by this peer, and do not | ||
815 | * allow new ones to be added: We are shutting down. | ||
816 | * | ||
817 | * @param cp peer to drop paths to | ||
818 | */ | ||
819 | void | ||
820 | GCP_drop_owned_paths (struct CadetPeer *cp) | ||
821 | { | ||
822 | struct CadetPeerPath *path; | ||
823 | |||
824 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
825 | "Destroying all paths to %s\n", | ||
826 | GCP_2s (cp)); | ||
827 | while (NULL != (path = | ||
828 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
829 | GCPP_release (path); | ||
830 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
831 | cp->path_heap = NULL; | ||
832 | } | ||
833 | |||
834 | |||
835 | /** | ||
836 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
837 | * | ||
838 | * @param cp peer to modify | ||
839 | * @param entry an entry on a path | ||
840 | * @param off offset of this peer on the path | ||
841 | */ | ||
842 | void | ||
843 | GCP_path_entry_add (struct CadetPeer *cp, | ||
844 | struct CadetPeerPathEntry *entry, | ||
845 | unsigned int off) | ||
846 | { | ||
847 | GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path, | ||
848 | off)); | ||
849 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
850 | "Discovered that peer %s is on path %s at offset %u\n", | ||
851 | GCP_2s (cp), | ||
852 | GCPP_2s (entry->path), | ||
853 | off); | ||
854 | if (off >= cp->path_dll_length) | ||
855 | { | ||
856 | unsigned int len = cp->path_dll_length; | ||
857 | |||
858 | GNUNET_array_grow (cp->path_heads, | ||
859 | len, | ||
860 | off + 4); | ||
861 | GNUNET_array_grow (cp->path_tails, | ||
862 | cp->path_dll_length, | ||
863 | off + 4); | ||
864 | } | ||
865 | GNUNET_CONTAINER_DLL_insert (cp->path_heads[off], | ||
866 | cp->path_tails[off], | ||
867 | entry); | ||
868 | cp->off_sum += off; | ||
869 | cp->num_paths++; | ||
870 | |||
871 | /* If we have a tunnel to this peer, tell the tunnel that there is a | ||
872 | new path available. */ | ||
873 | if (NULL != cp->t) | ||
874 | GCT_consider_path (cp->t, | ||
875 | entry->path, | ||
876 | off); | ||
877 | |||
878 | if ((NULL != cp->search_h) && | ||
879 | (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths)) | ||
880 | { | ||
881 | /* Now I have enough paths, stop search */ | ||
882 | GCD_search_stop (cp->search_h); | ||
883 | cp->search_h = NULL; | ||
884 | } | ||
885 | if (NULL != cp->destroy_task) | ||
886 | { | ||
887 | /* paths changed, this resets the destroy timeout counter | ||
888 | and aborts a destroy task that may no longer be valid | ||
889 | to have (as we now have more paths via this peer). */ | ||
890 | consider_peer_destroy (cp); | ||
891 | } | ||
892 | } | ||
893 | |||
894 | |||
895 | /** | ||
896 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
897 | * | ||
898 | * @param cp peer to modify | ||
899 | * @param entry an entry on a path | ||
900 | * @param off offset of this peer on the path | ||
901 | */ | ||
902 | void | ||
903 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
904 | struct CadetPeerPathEntry *entry, | ||
905 | unsigned int off) | ||
906 | { | ||
907 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
908 | "Removing knowledge about peer %s beging on path %s at offset %u\n", | ||
909 | GCP_2s (cp), | ||
910 | GCPP_2s (entry->path), | ||
911 | off); | ||
912 | GNUNET_CONTAINER_DLL_remove (cp->path_heads[off], | ||
913 | cp->path_tails[off], | ||
914 | entry); | ||
915 | GNUNET_assert (0 < cp->num_paths); | ||
916 | cp->off_sum -= off; | ||
917 | cp->num_paths--; | ||
918 | if ((NULL == cp->core_mq) && | ||
919 | (NULL != cp->t) && | ||
920 | (NULL == cp->search_h) && | ||
921 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths)) | ||
922 | cp->search_h | ||
923 | = GCD_search (&cp->pid); | ||
924 | if (NULL == cp->destroy_task) | ||
925 | { | ||
926 | /* paths changed, we might now be ready for destruction, check again */ | ||
927 | consider_peer_destroy (cp); | ||
928 | } | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Prune down the number of paths to this peer, we seem to | ||
934 | * have way too many. | ||
935 | * | ||
936 | * @param cls the `struct CadetPeer` to maintain the path heap for | ||
937 | */ | ||
938 | static void | ||
939 | path_heap_cleanup (void *cls) | ||
940 | { | ||
941 | struct CadetPeer *cp = cls; | ||
942 | struct CadetPeerPath *root; | ||
943 | |||
944 | cp->heap_cleanup_task = NULL; | ||
945 | while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
946 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | ||
947 | { | ||
948 | /* Now we have way too many, drop least desirable UNLESS it is in use! | ||
949 | (Note that this intentionally keeps highly desirable, but currently | ||
950 | unused paths around in the hope that we might be able to switch, even | ||
951 | if the number of paths exceeds the threshold.) */ | ||
952 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
953 | GNUNET_assert (NULL != root); | ||
954 | if (NULL != | ||
955 | GCPP_get_connection (root, | ||
956 | cp, | ||
957 | GCPP_get_length (root) - 1)) | ||
958 | break; /* can't fix */ | ||
959 | /* Got plenty of paths to this destination, and this is a low-quality | ||
960 | one that we don't care about. Allow it to die. */ | ||
961 | GNUNET_assert (root == | ||
962 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
963 | GCPP_release (root); | ||
964 | } | ||
965 | } | ||
966 | |||
967 | |||
968 | /** | ||
969 | * Try adding a @a path to this @a peer. If the peer already | ||
970 | * has plenty of paths, return NULL. | ||
971 | * | ||
972 | * @param cp peer to which the @a path leads to | ||
973 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
974 | * @param off offset of @a cp in @a path | ||
975 | * @param force force attaching the path | ||
976 | * @return NULL if this peer does not care to become a new owner, | ||
977 | * otherwise the node in the peer's path heap for the @a path. | ||
978 | */ | ||
979 | struct GNUNET_CONTAINER_HeapNode * | ||
980 | GCP_attach_path (struct CadetPeer *cp, | ||
981 | struct CadetPeerPath *path, | ||
982 | unsigned int off, | ||
983 | int force) | ||
984 | { | ||
985 | GNUNET_CONTAINER_HeapCostType desirability; | ||
986 | struct CadetPeerPath *root; | ||
987 | GNUNET_CONTAINER_HeapCostType root_desirability; | ||
988 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
989 | |||
990 | GNUNET_assert (off == GCPP_get_length (path) - 1); | ||
991 | GNUNET_assert (cp == GCPP_get_peer_at_offset (path, | ||
992 | off)); | ||
993 | if (NULL == cp->path_heap) | ||
994 | { | ||
995 | /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */ | ||
996 | GNUNET_assert (GNUNET_NO == force); | ||
997 | return NULL; | ||
998 | } | ||
999 | desirability = GCPP_get_desirability (path); | ||
1000 | if (GNUNET_NO == force) | ||
1001 | { | ||
1002 | /* FIXME: desirability is not yet initialized; tricky! */ | ||
1003 | if (GNUNET_NO == | ||
1004 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, | ||
1005 | (void **) &root, | ||
1006 | &root_desirability)) | ||
1007 | { | ||
1008 | root = NULL; | ||
1009 | root_desirability = 0; | ||
1010 | } | ||
1011 | |||
1012 | if ((DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) && | ||
1013 | (desirability < root_desirability)) | ||
1014 | { | ||
1015 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1016 | "Decided to not attach path %s to peer %s due to undesirability\n", | ||
1017 | GCPP_2s (path), | ||
1018 | GCP_2s (cp)); | ||
1019 | return NULL; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1024 | "Attaching path %s to peer %s (%s)\n", | ||
1025 | GCPP_2s (path), | ||
1026 | GCP_2s (cp), | ||
1027 | (GNUNET_NO == force) ? "desirable" : "forced"); | ||
1028 | |||
1029 | /* Yes, we'd like to add this path, add to our heap */ | ||
1030 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, | ||
1031 | path, | ||
1032 | desirability); | ||
1033 | |||
1034 | /* Consider maybe dropping other paths because of the new one */ | ||
1035 | if ((GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
1036 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
1037 | (NULL != cp->heap_cleanup_task)) | ||
1038 | cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup, | ||
1039 | cp); | ||
1040 | return hn; | ||
1041 | } | ||
1042 | |||
1043 | |||
1044 | /** | ||
1045 | * This peer can no longer own @a path as the path | ||
1046 | * has been extended and a peer further down the line | ||
1047 | * is now the new owner. | ||
1048 | * | ||
1049 | * @param cp old owner of the @a path | ||
1050 | * @param path path where the ownership is lost | ||
1051 | * @param hn note in @a cp's path heap that must be deleted | ||
1052 | */ | ||
1053 | void | ||
1054 | GCP_detach_path (struct CadetPeer *cp, | ||
1055 | struct CadetPeerPath *path, | ||
1056 | struct GNUNET_CONTAINER_HeapNode *hn) | ||
1057 | { | ||
1058 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1059 | "Detaching path %s from peer %s\n", | ||
1060 | GCPP_2s (path), | ||
1061 | GCP_2s (cp)); | ||
1062 | GNUNET_assert (path == | ||
1063 | GNUNET_CONTAINER_heap_remove_node (hn)); | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | /** | ||
1068 | * Add a @a connection to this @a cp. | ||
1069 | * | ||
1070 | * @param cp peer via which the @a connection goes | ||
1071 | * @param cc the connection to add | ||
1072 | */ | ||
1073 | void | ||
1074 | GCP_add_connection (struct CadetPeer *cp, | ||
1075 | struct CadetConnection *cc) | ||
1076 | { | ||
1077 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1078 | "Adding %s to peer %s\n", | ||
1079 | GCC_2s (cc), | ||
1080 | GCP_2s (cp)); | ||
1081 | GNUNET_assert (GNUNET_OK == | ||
1082 | GNUNET_CONTAINER_multishortmap_put (cp->connections, | ||
1083 | &GCC_get_id ( | ||
1084 | cc)->connection_of_tunnel, | ||
1085 | cc, | ||
1086 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1087 | if (NULL != cp->destroy_task) | ||
1088 | { | ||
1089 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
1090 | cp->destroy_task = NULL; | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | /** | ||
1096 | * Remove a @a connection that went via this @a cp. | ||
1097 | * | ||
1098 | * @param cp peer via which the @a connection went | ||
1099 | * @param cc the connection to remove | ||
1100 | */ | ||
1101 | void | ||
1102 | GCP_remove_connection (struct CadetPeer *cp, | ||
1103 | struct CadetConnection *cc) | ||
1104 | { | ||
1105 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1106 | "Removing connection %s from peer %s\n", | ||
1107 | GCC_2s (cc), | ||
1108 | GCP_2s (cp)); | ||
1109 | GNUNET_assert (GNUNET_YES == | ||
1110 | GNUNET_CONTAINER_multishortmap_remove (cp->connections, | ||
1111 | &GCC_get_id ( | ||
1112 | cc)-> | ||
1113 | connection_of_tunnel, | ||
1114 | cc)); | ||
1115 | consider_peer_destroy (cp); | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | /** | ||
1120 | * Retrieve the CadetPeer structure associated with the | ||
1121 | * peer. Optionally create one and insert it in the appropriate | ||
1122 | * structures if the peer is not known yet. | ||
1123 | * | ||
1124 | * @param peer_id Full identity of the peer. | ||
1125 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
1126 | * #GNUNET_NO to return NULL if peer is unknown. | ||
1127 | * @return Existing or newly created peer structure. | ||
1128 | * NULL if unknown and not requested @a create | ||
1129 | */ | ||
1130 | struct CadetPeer * | ||
1131 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
1132 | int create) | ||
1133 | { | ||
1134 | struct CadetPeer *cp; | ||
1135 | |||
1136 | cp = GNUNET_CONTAINER_multipeermap_get (peers, | ||
1137 | peer_id); | ||
1138 | if (NULL != cp) | ||
1139 | return cp; | ||
1140 | if (GNUNET_NO == create) | ||
1141 | return NULL; | ||
1142 | cp = GNUNET_new (struct CadetPeer); | ||
1143 | cp->pid = *peer_id; | ||
1144 | cp->connections = GNUNET_CONTAINER_multishortmap_create (32, | ||
1145 | GNUNET_YES); | ||
1146 | cp->path_heap = GNUNET_CONTAINER_heap_create ( | ||
1147 | GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1148 | GNUNET_assert (GNUNET_YES == | ||
1149 | GNUNET_CONTAINER_multipeermap_put (peers, | ||
1150 | &cp->pid, | ||
1151 | cp, | ||
1152 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1153 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1154 | "Creating peer %s\n", | ||
1155 | GCP_2s (cp)); | ||
1156 | return cp; | ||
1157 | } | ||
1158 | |||
1159 | |||
1160 | /** | ||
1161 | * Obtain the peer identity for a `struct CadetPeer`. | ||
1162 | * | ||
1163 | * @param cp our peer handle | ||
1164 | * @return the peer identity | ||
1165 | */ | ||
1166 | const struct GNUNET_PeerIdentity * | ||
1167 | GCP_get_id (struct CadetPeer *cp) | ||
1168 | { | ||
1169 | return &cp->pid; | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | /** | ||
1174 | * Iterate over all known peers. | ||
1175 | * | ||
1176 | * @param iter Iterator. | ||
1177 | * @param cls Closure for @c iter. | ||
1178 | */ | ||
1179 | void | ||
1180 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
1181 | void *cls) | ||
1182 | { | ||
1183 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
1184 | iter, | ||
1185 | cls); | ||
1186 | } | ||
1187 | |||
1188 | |||
1189 | /** | ||
1190 | * Count the number of known paths toward the peer. | ||
1191 | * | ||
1192 | * @param cp Peer to get path info. | ||
1193 | * @return Number of known paths. | ||
1194 | */ | ||
1195 | unsigned int | ||
1196 | GCP_count_paths (const struct CadetPeer *cp) | ||
1197 | { | ||
1198 | return cp->num_paths; | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Iterate over the paths to a peer. | ||
1204 | * | ||
1205 | * @param cp Peer to get path info. | ||
1206 | * @param callback Function to call for every path. | ||
1207 | * @param callback_cls Closure for @a callback. | ||
1208 | * @return Number of iterated paths. | ||
1209 | */ | ||
1210 | unsigned int | ||
1211 | GCP_iterate_paths (struct CadetPeer *cp, | ||
1212 | GCP_PathIterator callback, | ||
1213 | void *callback_cls) | ||
1214 | { | ||
1215 | unsigned int ret = 0; | ||
1216 | |||
1217 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1218 | "Iterating over paths to peer %s%s\n", | ||
1219 | GCP_2s (cp), | ||
1220 | (NULL == cp->core_mq) ? "" : " including direct link"); | ||
1221 | if (NULL != cp->core_mq) | ||
1222 | { | ||
1223 | /* FIXME: this branch seems to duplicate the | ||
1224 | i=0 case below (direct link). Leave out!??? -CG */ | ||
1225 | struct CadetPeerPath *path; | ||
1226 | |||
1227 | path = GCPP_get_path_from_route (1, | ||
1228 | &cp->pid); | ||
1229 | ret++; | ||
1230 | if (GNUNET_NO == | ||
1231 | callback (callback_cls, | ||
1232 | path, | ||
1233 | 0)) | ||
1234 | return ret; | ||
1235 | } | ||
1236 | for (unsigned int i = 0; i < cp->path_dll_length; i++) | ||
1237 | { | ||
1238 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1239 | NULL != pe; | ||
1240 | pe = pe->next) | ||
1241 | { | ||
1242 | ret++; | ||
1243 | if (GNUNET_NO == | ||
1244 | callback (callback_cls, | ||
1245 | pe->path, | ||
1246 | i)) | ||
1247 | return ret; | ||
1248 | } | ||
1249 | } | ||
1250 | return ret; | ||
1251 | } | ||
1252 | |||
1253 | |||
1254 | /** | ||
1255 | * Iterate over the paths to a peer without direct link. | ||
1256 | * | ||
1257 | * @param cp Peer to get path info. | ||
1258 | * @param callback Function to call for every path. | ||
1259 | * @param callback_cls Closure for @a callback. | ||
1260 | * @return Number of iterated paths. | ||
1261 | */ | ||
1262 | unsigned int | ||
1263 | GCP_iterate_indirect_paths (struct CadetPeer *cp, | ||
1264 | GCP_PathIterator callback, | ||
1265 | void *callback_cls) | ||
1266 | { | ||
1267 | unsigned int ret = 0; | ||
1268 | |||
1269 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1270 | "Iterating over paths to peer %s without direct link\n", | ||
1271 | GCP_2s (cp)); | ||
1272 | for (unsigned int i = 1; i < cp->path_dll_length; i++) | ||
1273 | { | ||
1274 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1275 | NULL != pe; | ||
1276 | pe = pe->next) | ||
1277 | { | ||
1278 | ret++; | ||
1279 | if (GNUNET_NO == | ||
1280 | callback (callback_cls, | ||
1281 | pe->path, | ||
1282 | i)) | ||
1283 | return ret; | ||
1284 | } | ||
1285 | } | ||
1286 | return ret; | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | /** | ||
1291 | * Iterate over the paths to @a cp where | ||
1292 | * @a cp is at distance @a dist from us. | ||
1293 | * | ||
1294 | * @param cp Peer to get path info. | ||
1295 | * @param dist desired distance of @a cp to us on the path | ||
1296 | * @param callback Function to call for every path. | ||
1297 | * @param callback_cls Closure for @a callback. | ||
1298 | * @return Number of iterated paths. | ||
1299 | */ | ||
1300 | unsigned int | ||
1301 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
1302 | unsigned int dist, | ||
1303 | GCP_PathIterator callback, | ||
1304 | void *callback_cls) | ||
1305 | { | ||
1306 | unsigned int ret = 0; | ||
1307 | |||
1308 | if (dist >= cp->path_dll_length) | ||
1309 | { | ||
1310 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1311 | "Asked to look for paths at distance %u, but maximum for me is < %u\n", | ||
1312 | dist, | ||
1313 | cp->path_dll_length); | ||
1314 | return 0; | ||
1315 | } | ||
1316 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; | ||
1317 | NULL != pe; | ||
1318 | pe = pe->next) | ||
1319 | { | ||
1320 | if (GNUNET_NO == | ||
1321 | callback (callback_cls, | ||
1322 | pe->path, | ||
1323 | dist)) | ||
1324 | return ret; | ||
1325 | ret++; | ||
1326 | } | ||
1327 | return ret; | ||
1328 | } | ||
1329 | |||
1330 | |||
1331 | /** | ||
1332 | * Get the tunnel towards a peer. | ||
1333 | * | ||
1334 | * @param cp Peer to get from. | ||
1335 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
1336 | * @return Tunnel towards peer. | ||
1337 | */ | ||
1338 | struct CadetTunnel * | ||
1339 | GCP_get_tunnel (struct CadetPeer *cp, | ||
1340 | int create) | ||
1341 | { | ||
1342 | if (NULL == cp) | ||
1343 | return NULL; | ||
1344 | if ((NULL != cp->t) || | ||
1345 | (GNUNET_NO == create)) | ||
1346 | return cp->t; | ||
1347 | cp->t = GCT_create_tunnel (cp); | ||
1348 | consider_peer_activate (cp); | ||
1349 | return cp->t; | ||
1350 | } | ||
1351 | |||
1352 | |||
1353 | /** | ||
1354 | * Hello offer was passed to the transport service. Mark it | ||
1355 | * as done. | ||
1356 | * | ||
1357 | * @param cls the `struct CadetPeer` where the offer completed | ||
1358 | */ | ||
1359 | static void | ||
1360 | hello_offer_done (void *cls) | ||
1361 | { | ||
1362 | struct CadetPeer *cp = cls; | ||
1363 | |||
1364 | cp->hello_offer = NULL; | ||
1365 | } | ||
1366 | |||
1367 | |||
1368 | /** | ||
1369 | * We got a HELLO for a @a peer, remember it, and possibly | ||
1370 | * trigger adequate actions (like trying to connect). | ||
1371 | * | ||
1372 | * @param cp the peer we got a HELLO for | ||
1373 | * @param hello the HELLO to remember | ||
1374 | */ | ||
1375 | void | ||
1376 | GCP_set_hello (struct CadetPeer *cp, | ||
1377 | const struct GNUNET_HELLO_Message *hello) | ||
1378 | { | ||
1379 | struct GNUNET_HELLO_Message *mrg; | ||
1380 | |||
1381 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1382 | "Got %u byte HELLO for peer %s\n", | ||
1383 | (unsigned int) GNUNET_HELLO_size (hello), | ||
1384 | GCP_2s (cp)); | ||
1385 | if (NULL != cp->hello_offer) | ||
1386 | { | ||
1387 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
1388 | cp->hello_offer = NULL; | ||
1389 | } | ||
1390 | if (NULL != cp->hello) | ||
1391 | { | ||
1392 | mrg = GNUNET_HELLO_merge (hello, | ||
1393 | cp->hello); | ||
1394 | GNUNET_free (cp->hello); | ||
1395 | cp->hello = mrg; | ||
1396 | } | ||
1397 | else | ||
1398 | { | ||
1399 | cp->hello = GNUNET_memdup (hello, | ||
1400 | GNUNET_HELLO_size (hello)); | ||
1401 | } | ||
1402 | cp->hello_offer | ||
1403 | = GNUNET_TRANSPORT_offer_hello (cfg, | ||
1404 | GNUNET_HELLO_get_header (cp->hello), | ||
1405 | &hello_offer_done, | ||
1406 | cp); | ||
1407 | /* New HELLO means cp's destruction time may change... */ | ||
1408 | consider_peer_destroy (cp); | ||
1409 | } | ||
1410 | |||
1411 | |||
1412 | /** | ||
1413 | * The tunnel to the given peer no longer exists, remove it from our | ||
1414 | * data structures, and possibly clean up the peer itself. | ||
1415 | * | ||
1416 | * @param cp the peer affected | ||
1417 | * @param t the dead tunnel | ||
1418 | */ | ||
1419 | void | ||
1420 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
1421 | struct CadetTunnel *t) | ||
1422 | { | ||
1423 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1424 | "Dropping tunnel %s to peer %s\n", | ||
1425 | GCT_2s (t), | ||
1426 | GCP_2s (cp)); | ||
1427 | GNUNET_assert (cp->t == t); | ||
1428 | cp->t = NULL; | ||
1429 | consider_peer_destroy (cp); | ||
1430 | } | ||
1431 | |||
1432 | |||
1433 | /** | ||
1434 | * Test if @a cp has a core-level connection | ||
1435 | * | ||
1436 | * @param cp peer to test | ||
1437 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
1438 | */ | ||
1439 | int | ||
1440 | GCP_has_core_connection (struct CadetPeer *cp) | ||
1441 | { | ||
1442 | return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO; | ||
1443 | } | ||
1444 | |||
1445 | |||
1446 | /** | ||
1447 | * Start message queue change notifications. | ||
1448 | * | ||
1449 | * @param cp peer to notify for | ||
1450 | * @param cb function to call if mq becomes available or unavailable | ||
1451 | * @param cb_cls closure for @a cb | ||
1452 | * @return handle to cancel request | ||
1453 | */ | ||
1454 | struct GCP_MessageQueueManager * | ||
1455 | GCP_request_mq (struct CadetPeer *cp, | ||
1456 | GCP_MessageQueueNotificationCallback cb, | ||
1457 | void *cb_cls) | ||
1458 | { | ||
1459 | struct GCP_MessageQueueManager *mqm; | ||
1460 | |||
1461 | mqm = GNUNET_new (struct GCP_MessageQueueManager); | ||
1462 | mqm->cb = cb; | ||
1463 | mqm->cb_cls = cb_cls; | ||
1464 | mqm->cp = cp; | ||
1465 | GNUNET_CONTAINER_DLL_insert (cp->mqm_head, | ||
1466 | cp->mqm_tail, | ||
1467 | mqm); | ||
1468 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1469 | "Creating MQM %p for peer %s\n", | ||
1470 | mqm, | ||
1471 | GCP_2s (cp)); | ||
1472 | if (NULL != cp->core_mq) | ||
1473 | cb (cb_cls, | ||
1474 | GNUNET_YES); | ||
1475 | return mqm; | ||
1476 | } | ||
1477 | |||
1478 | |||
1479 | /** | ||
1480 | * Stops message queue change notifications. | ||
1481 | * | ||
1482 | * @param mqm handle matching request to cancel | ||
1483 | * @param last_env final message to transmit, or NULL | ||
1484 | */ | ||
1485 | void | ||
1486 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
1487 | struct GNUNET_MQ_Envelope *last_env) | ||
1488 | { | ||
1489 | struct CadetPeer *cp = mqm->cp; | ||
1490 | |||
1491 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1492 | "Destroying MQM %p for peer %s%s\n", | ||
1493 | mqm, | ||
1494 | GCP_2s (cp), | ||
1495 | (NULL == last_env) ? "" : " with last ditch transmission"); | ||
1496 | if (NULL != mqm->env) | ||
1497 | GNUNET_MQ_discard (mqm->env); | ||
1498 | if (NULL != last_env) | ||
1499 | { | ||
1500 | if (NULL != cp->core_mq) | ||
1501 | { | ||
1502 | GNUNET_MQ_notify_sent (last_env, | ||
1503 | &mqm_send_done, | ||
1504 | cp); | ||
1505 | GNUNET_MQ_send (cp->core_mq, | ||
1506 | last_env); | ||
1507 | } | ||
1508 | else | ||
1509 | { | ||
1510 | GNUNET_MQ_discard (last_env); | ||
1511 | } | ||
1512 | } | ||
1513 | if (cp->mqm_ready_ptr == mqm) | ||
1514 | cp->mqm_ready_ptr = mqm->next; | ||
1515 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
1516 | cp->mqm_tail, | ||
1517 | mqm); | ||
1518 | GNUNET_free (mqm); | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | /** | ||
1523 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
1524 | * This function should only be used to send error messages outside | ||
1525 | * of flow and congestion control, similar to ICMP. Note that | ||
1526 | * the envelope may be silently discarded as well. | ||
1527 | * | ||
1528 | * @param cp peer to send the message to | ||
1529 | * @param env envelope with the message to send | ||
1530 | */ | ||
1531 | void | ||
1532 | GCP_send_ooo (struct CadetPeer *cp, | ||
1533 | struct GNUNET_MQ_Envelope *env) | ||
1534 | { | ||
1535 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1536 | "Sending message to %s out of management\n", | ||
1537 | GCP_2s (cp)); | ||
1538 | if (NULL == cp->core_mq) | ||
1539 | { | ||
1540 | GNUNET_MQ_discard (env); | ||
1541 | return; | ||
1542 | } | ||
1543 | if (GNUNET_MQ_get_length (cp->core_mq) > MAX_OOO_QUEUE_SIZE) | ||
1544 | { | ||
1545 | GNUNET_MQ_discard (env); | ||
1546 | return; | ||
1547 | } | ||
1548 | GNUNET_MQ_notify_sent (env, | ||
1549 | &mqm_send_done, | ||
1550 | cp); | ||
1551 | GNUNET_MQ_send (cp->core_mq, | ||
1552 | env); | ||
1553 | } | ||
1554 | |||
1555 | |||
1556 | /** | ||
1557 | * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer. | ||
1558 | * | ||
1559 | * @param peer The peer we received a new time value from. | ||
1560 | * @param monotime Time value we check against the last time value we received from a peer. | ||
1561 | * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer. | ||
1562 | */ | ||
1563 | int | ||
1564 | GCP_check_and_update_monotime (struct CadetPeer *peer, | ||
1565 | struct GNUNET_TIME_AbsoluteNBO monotime) | ||
1566 | { | ||
1567 | |||
1568 | struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime); | ||
1569 | |||
1570 | if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us)) | ||
1571 | { | ||
1572 | peer->last_connection_create = mt; | ||
1573 | return GNUNET_YES; | ||
1574 | } | ||
1575 | return GNUNET_NO; | ||
1576 | } | ||
1577 | |||
1578 | |||
1579 | /** | ||
1580 | * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage. | ||
1581 | * | ||
1582 | * @param peer The peer that signed the monotime value. | ||
1583 | * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value. | ||
1584 | * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not. | ||
1585 | */ | ||
1586 | int | ||
1587 | GCP_check_monotime_sig (struct CadetPeer *peer, | ||
1588 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
1589 | { | ||
1590 | struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl ( | ||
1591 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR), | ||
1592 | .purpose.size = htonl (sizeof(cp)), | ||
1593 | .monotonic_time = msg->monotime}; | ||
1594 | |||
1595 | if (GNUNET_OK != | ||
1596 | GNUNET_CRYPTO_eddsa_verify ( | ||
1597 | GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR, | ||
1598 | &cp, | ||
1599 | &msg->monotime_sig, | ||
1600 | &peer->pid.public_key)) | ||
1601 | { | ||
1602 | GNUNET_break_op (0); | ||
1603 | return GNUNET_SYSERR; | ||
1604 | } | ||
1605 | return GNUNET_OK; | ||
1606 | } | ||
1607 | |||
1608 | |||
1609 | /* end of gnunet-service-cadet-new_peer.c */ | ||