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