-remove debug message
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet_peer.c
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       (0 == 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 positiv: path off of peer above average (bad path for peer),
308      path_delta negativ: 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_non_null (cp->path_heads);
349   GNUNET_free_non_null (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_non_null (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 destory! */
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 desireable, 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        "Detatching 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 stucture 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  * 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.
1557  *
1558  * @param peer The peer we received a new time value from.
1559  * @param monotime Time value we check against the last time value we received from a peer.
1560  * @return GNUNET_YES if monotime is newer than the last received time value, GNUNET_NO if monotime is not newer.
1561  */
1562 int
1563 GCP_check_and_update_monotime (struct CadetPeer *peer,
1564                                struct GNUNET_TIME_AbsoluteNBO monotime)
1565 {
1566
1567   struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime);
1568
1569   if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us))
1570   {
1571     peer->last_connection_create = mt;
1572     return GNUNET_YES;
1573   }
1574   return GNUNET_NO;
1575 }
1576
1577 /**
1578  * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
1579  *
1580  * @param peer The peer that signed the monotime value.
1581  * @param msg The GNUNET_CADET_ConnectionCreateMessage with the monotime value.
1582  * @return GNUNET_OK if the signature is good, GNUNET_SYSERR if not.
1583  */
1584 int
1585 GCP_check_monotime_sig (struct CadetPeer *peer,
1586                         const struct GNUNET_CADET_ConnectionCreateMessage *msg)
1587 {
1588   struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
1589                                           GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
1590                                         .purpose.size = htonl (sizeof(cp)),
1591                                         .monotonic_time = msg->monotime};
1592
1593   if (GNUNET_OK !=
1594       GNUNET_CRYPTO_eddsa_verify (
1595         GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR,
1596         &cp,
1597         &msg->monotime_sig,
1598         &peer->pid.public_key))
1599   {
1600     GNUNET_break_op (0);
1601     return GNUNET_SYSERR;
1602   }
1603   return GNUNET_OK;
1604 }
1605
1606
1607 /* end of gnunet-service-cadet-new_peer.c */