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