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