aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet_peer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cadet/gnunet-service-cadet_peer.c')
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c1609
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 */
74struct 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 */
111struct 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 */
241const char *
242GCP_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 */
278double
279GCP_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 */
329static void
330destroy_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 */
395static void
396consider_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 */
462static void
463consider_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 */
472static void
473drop_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 */
490static void
491consider_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 */
538void
539GCP_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 */
602static int
603should_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 */
620static void
621mqm_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 */
629static void
630mqm_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 */
703static void
704send_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 */
725static void
726mqm_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 */
744void
745GCP_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 */
780static int
781destroy_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 */
802void
803GCP_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 */
819void
820GCP_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 */
842void
843GCP_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 */
902void
903GCP_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 */
938static void
939path_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 */
979struct GNUNET_CONTAINER_HeapNode *
980GCP_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 */
1053void
1054GCP_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 */
1073void
1074GCP_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 */
1101void
1102GCP_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 */
1130struct CadetPeer *
1131GCP_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 */
1166const struct GNUNET_PeerIdentity *
1167GCP_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 */
1179void
1180GCP_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 */
1195unsigned int
1196GCP_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 */
1210unsigned int
1211GCP_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 */
1262unsigned int
1263GCP_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 */
1300unsigned int
1301GCP_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 */
1338struct CadetTunnel *
1339GCP_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 */
1359static void
1360hello_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 */
1375void
1376GCP_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 */
1419void
1420GCP_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 */
1439int
1440GCP_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 */
1454struct GCP_MessageQueueManager *
1455GCP_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 */
1485void
1486GCP_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 */
1531void
1532GCP_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 */
1563int
1564GCP_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 */
1586int
1587GCP_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 */