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