- refactor and improve path creation
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_peer.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21
22 #include "platform.h"
23 #include "gnunet_util_lib.h"
24
25 #include "gnunet_core_service.h"
26 #include "gnunet_statistics_service.h"
27
28 #include "mesh_protocol.h"
29
30 #include "gnunet-service-mesh_peer.h"
31 #include "gnunet-service-mesh_dht.h"
32 #include "gnunet-service-mesh_connection.h"
33 #include "gnunet-service-mesh_tunnel.h"
34 #include "mesh_path.h"
35
36 #define LOG(level, ...) GNUNET_log_from (level,"mesh-p2p",__VA_ARGS__)
37
38 /******************************************************************************/
39 /********************************   STRUCTS  **********************************/
40 /******************************************************************************/
41
42 /**
43  * Struct containing info about a queued transmission to this peer
44  */
45 struct MeshPeerQueue
46 {
47     /**
48       * DLL next
49       */
50   struct MeshPeerQueue *next;
51
52     /**
53       * DLL previous
54       */
55   struct MeshPeerQueue *prev;
56
57     /**
58      * Peer this transmission is directed to.
59      */
60   struct MeshPeer *peer;
61
62     /**
63      * Connection this message belongs to.
64      */
65   struct MeshConnection *c;
66
67     /**
68      * Is FWD in c?
69      */
70   int fwd;
71
72     /**
73      * Pointer to info stucture used as cls.
74      */
75   void *cls;
76
77     /**
78      * Type of message
79      */
80   uint16_t type;
81
82     /**
83      * Size of the message
84      */
85   size_t size;
86
87     /**
88      * Set when this message starts waiting for CORE.
89      */
90   struct GNUNET_TIME_Absolute start_waiting;
91
92     /**
93      * Function to call on sending.
94      */
95   GMP_sent callback;
96
97     /**
98      * Closure for callback.
99      */
100   void *callback_cls;
101 };
102
103 /**
104  * Struct containing all information regarding a given peer
105  */
106 struct MeshPeer
107 {
108     /**
109      * ID of the peer
110      */
111   GNUNET_PEER_Id id;
112
113     /**
114      * Last time we heard from this peer
115      */
116   struct GNUNET_TIME_Absolute last_contact;
117
118     /**
119      * Paths to reach the peer, ordered by ascending hop count
120      */
121   struct MeshPeerPath *path_head;
122
123     /**
124      * Paths to reach the peer, ordered by ascending hop count
125      */
126   struct MeshPeerPath *path_tail;
127
128     /**
129      * Handle to stop the DHT search for paths to this peer
130      */
131   struct GMD_search_handle *search_h;
132
133     /**
134      * Tunnel to this peer, if any.
135      */
136   struct MeshTunnel3 *tunnel;
137
138     /**
139      * Connections that go through this peer, indexed by tid;
140      */
141   struct GNUNET_CONTAINER_MultiHashMap *connections;
142
143     /**
144      * Handle for queued transmissions
145      */
146   struct GNUNET_CORE_TransmitHandle *core_transmit;
147
148   /**
149    * Transmission queue to core DLL head
150    */
151   struct MeshPeerQueue *queue_head;
152
153   /**
154    * Transmission queue to core DLL tail
155    */
156   struct MeshPeerQueue *queue_tail;
157
158   /**
159    * How many messages are in the queue to this peer.
160    */
161   unsigned int queue_n;
162 };
163
164
165 /******************************************************************************/
166 /*******************************   GLOBALS  ***********************************/
167 /******************************************************************************/
168
169 /**
170  * Global handle to the statistics service.
171  */
172 extern struct GNUNET_STATISTICS_Handle *stats;
173
174 /**
175  * Local peer own ID (full value).
176  */
177 extern struct GNUNET_PeerIdentity my_full_id;
178
179 /**
180  * Local peer own ID (short)
181  */
182 extern GNUNET_PEER_Id myid;
183
184 /**
185  * Peers known, indexed by PeerIdentity (MeshPeer).
186  */
187 static struct GNUNET_CONTAINER_MultiPeerMap *peers;
188
189 /**
190  * How many peers do we want to remember?
191  */
192 static unsigned long long max_peers;
193
194 /**
195  * Percentage of messages that will be dropped (for test purposes only).
196  */
197 static unsigned long long drop_percent;
198
199 /**
200  * Handle to communicate with core.
201  */
202 static struct GNUNET_CORE_Handle *core_handle;
203
204
205 /******************************************************************************/
206 /***************************** CORE CALLBACKS *********************************/
207 /******************************************************************************/
208
209
210 /**
211  * Iterator to notify all connections of a broken link. Mark connections
212  * to destroy after all traffic has been sent.
213  *
214  * @param cls Closure (peer disconnected).
215  * @param key Current key code (peer id).
216  * @param value Value in the hash map (connection).
217  *
218  * @return #GNUNET_YES to continue to iterate.
219  */
220 static int
221 notify_broken (void *cls,
222                const struct GNUNET_HashCode *key,
223                void *value)
224 {
225   struct MeshPeer *peer = cls;
226   struct MeshConnection *c = value;
227
228   LOG (GNUNET_ERROR_TYPE_DEBUG, "  notifying %s due to %s\n",
229        GMC_2s (c), GMP_2s (peer));
230   GMC_notify_broken (c, peer);
231
232   return GNUNET_YES;
233 }
234
235
236 /**
237  * Method called whenever a given peer connects.
238  *
239  * @param cls closure
240  * @param peer peer identity this notification is about
241  */
242 static void
243 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
244 {
245   struct MeshPeer *mp;
246   struct MeshPeerPath *path;
247
248   LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer connected\n");
249   LOG (GNUNET_ERROR_TYPE_DEBUG, "     %s\n", GNUNET_i2s (&my_full_id));
250   mp = GMP_get (peer);
251   if (myid == mp->id)
252   {
253     LOG (GNUNET_ERROR_TYPE_DEBUG, "     (self)\n");
254     path = path_new (1);
255   }
256   else
257   {
258     LOG (GNUNET_ERROR_TYPE_DEBUG, "     %s\n", GNUNET_i2s (peer));
259     path = path_new (2);
260     path->peers[1] = mp->id;
261     GNUNET_PEER_change_rc (mp->id, 1);
262     GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
263   }
264   path->peers[0] = myid;
265   GNUNET_PEER_change_rc (myid, 1);
266   GMP_add_path (mp, path, GNUNET_YES);
267
268   mp->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
269   return;
270 }
271
272
273 /**
274  * Method called whenever a peer disconnects.
275  *
276  * @param cls closure
277  * @param peer peer identity this notification is about
278  */
279 static void
280 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
281 {
282   struct MeshPeer *p;
283
284   LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer disconnected\n");
285   p = GNUNET_CONTAINER_multipeermap_get (peers, peer);
286   if (NULL == p)
287   {
288     GNUNET_break (0);
289     return;
290   }
291   if (myid == p->id)
292     LOG (GNUNET_ERROR_TYPE_DEBUG, "     (self: %s)\n", GMP_2s (p));
293   else
294     LOG (GNUNET_ERROR_TYPE_DEBUG, "     %s\n", GMP_2s (p));
295
296
297   GNUNET_CONTAINER_multihashmap_iterate (p->connections, &notify_broken, p);
298   GNUNET_CONTAINER_multihashmap_destroy (p->connections);
299   p->connections = NULL;
300   if (NULL != p->core_transmit)
301     {
302       GNUNET_CORE_notify_transmit_ready_cancel (p->core_transmit);
303       p->core_transmit = NULL;
304     }
305   GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
306
307   return;
308 }
309
310
311 /**
312  * Functions to handle messages from core
313  */
314 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
315   {&GMC_handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
316     0},
317   {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
318     sizeof (struct GNUNET_MESH_ConnectionACK)},
319   {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
320     sizeof (struct GNUNET_MESH_ConnectionBroken)},
321   {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
322     sizeof (struct GNUNET_MESH_ConnectionDestroy)},
323   {&GMC_handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE,
324     sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
325   {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
326     sizeof (struct GNUNET_MESH_ACK)},
327   {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
328     sizeof (struct GNUNET_MESH_Poll)},
329   {&GMC_handle_encrypted, GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED, 0},
330   {&GMC_handle_kx, GNUNET_MESSAGE_TYPE_MESH_KX, 0},
331   {NULL, 0, 0}
332 };
333
334
335 /**
336  * To be called on core init/fail.
337  *
338  * @param cls Closure (config)
339  * @param identity the public identity of this peer
340  */
341 static void
342 core_init (void *cls,
343            const struct GNUNET_PeerIdentity *identity)
344 {
345   const struct GNUNET_CONFIGURATION_Handle *c = cls;
346   static int i = 0;
347
348   LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
349   if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
350   {
351     LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
352     LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity));
353     LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
354     GNUNET_CORE_disconnect (core_handle);
355     core_handle = GNUNET_CORE_connect (c, /* Main configuration */
356                                        NULL,      /* Closure passed to MESH functions */
357                                        &core_init,        /* Call core_init once connected */
358                                        &core_connect,     /* Handle connects */
359                                        &core_disconnect,  /* remove peers on disconnects */
360                                        NULL,      /* Don't notify about all incoming messages */
361                                        GNUNET_NO, /* For header only in notification */
362                                        NULL,      /* Don't notify about all outbound messages */
363                                        GNUNET_NO, /* For header-only out notification */
364                                        core_handlers);    /* Register these handlers */
365     if (10 < i++)
366       GNUNET_abort();
367   }
368   GML_start ();
369   return;
370 }
371
372 /**
373   * Core callback to write a pre-constructed data packet to core buffer
374   *
375   * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
376   * @param size Number of bytes available in buf.
377   * @param buf Where the to write the message.
378   *
379   * @return number of bytes written to buf
380   */
381 static size_t
382 send_core_data_raw (void *cls, size_t size, void *buf)
383 {
384   struct GNUNET_MessageHeader *msg = cls;
385   size_t total_size;
386
387   GNUNET_assert (NULL != msg);
388   total_size = ntohs (msg->size);
389
390   if (total_size > size)
391   {
392     GNUNET_break (0);
393     return 0;
394   }
395   memcpy (buf, msg, total_size);
396   GNUNET_free (cls);
397   return total_size;
398 }
399
400
401 /**
402  * Function to send a create connection message to a peer.
403  *
404  * @param c Connection to create.
405  * @param size number of bytes available in buf
406  * @param buf where the callee should write the message
407  * @return number of bytes written to buf
408  */
409 static size_t
410 send_core_connection_create (struct MeshConnection *c, size_t size, void *buf)
411 {
412   struct GNUNET_MESH_ConnectionCreate *msg;
413   struct GNUNET_PeerIdentity *peer_ptr;
414   const struct MeshPeerPath *p = GMC_get_path (c);
415   size_t size_needed;
416   int i;
417
418   if (NULL == p)
419     return 0;
420
421   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
422   size_needed =
423       sizeof (struct GNUNET_MESH_ConnectionCreate) +
424       p->length * sizeof (struct GNUNET_PeerIdentity);
425
426   if (size < size_needed || NULL == buf)
427   {
428     GNUNET_break (0);
429     return 0;
430   }
431   msg = (struct GNUNET_MESH_ConnectionCreate *) buf;
432   msg->header.size = htons (size_needed);
433   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE);
434   msg->cid = *GMC_get_id (c);
435
436   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
437   for (i = 0; i < p->length; i++)
438   {
439     GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
440   }
441
442   LOG (GNUNET_ERROR_TYPE_DEBUG,
443        "CONNECTION CREATE (%u bytes long) sent!\n",
444        size_needed);
445   return size_needed;
446 }
447
448
449 /**
450  * Creates a path ack message in buf and frees all unused resources.
451  *
452  * @param c Connection to send an ACK on.
453  * @param size number of bytes available in buf
454  * @param buf where the callee should write the message
455  *
456  * @return number of bytes written to buf
457  */
458 static size_t
459 send_core_connection_ack (struct MeshConnection *c, size_t size, void *buf)
460 {
461   struct GNUNET_MESH_ConnectionACK *msg = buf;
462
463   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
464   if (sizeof (struct GNUNET_MESH_ConnectionACK) > size)
465   {
466     GNUNET_break (0);
467     return 0;
468   }
469   msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK));
470   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK);
471   msg->cid = *GMC_get_id (c);
472   msg->reserved = 0;
473
474   /* TODO add signature */
475
476   LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
477   return sizeof (struct GNUNET_MESH_ConnectionACK);
478 }
479
480
481 /******************************************************************************/
482 /********************************   STATIC  ***********************************/
483 /******************************************************************************/
484
485 /**
486  * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
487  *
488  * @param cls closure
489  * @param key current key code
490  * @param value value in the hash map
491  * @return #GNUNET_YES if we should continue to iterate,
492  *         #GNUNET_NO if not.
493  */
494 static int
495 shutdown_tunnel (void *cls,
496                  const struct GNUNET_PeerIdentity *key,
497                  void *value)
498 {
499   struct MeshPeer *p = value;
500   struct MeshTunnel3 *t = p->tunnel;
501
502   if (NULL != t)
503     GMT_destroy (t);
504   return GNUNET_YES;
505 }
506
507
508
509 /**
510  * Destroy the peer_info and free any allocated resources linked to it
511  *
512  * @param peer The peer_info to destroy.
513  *
514  * @return GNUNET_OK on success
515  */
516 static int
517 peer_destroy (struct MeshPeer *peer)
518 {
519   struct GNUNET_PeerIdentity id;
520   struct MeshPeerPath *p;
521   struct MeshPeerPath *nextp;
522
523   GNUNET_PEER_resolve (peer->id, &id);
524   GNUNET_PEER_change_rc (peer->id, -1);
525
526   LOG (GNUNET_ERROR_TYPE_WARNING, "destroying peer %s\n", GNUNET_i2s (&id));
527
528   if (GNUNET_YES !=
529     GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
530   {
531     GNUNET_break (0);
532     LOG (GNUNET_ERROR_TYPE_WARNING, " not in peermap!!\n");
533   }
534   if (NULL != peer->search_h)
535   {
536     GMD_search_stop (peer->search_h);
537   }
538   p = peer->path_head;
539   while (NULL != p)
540   {
541     nextp = p->next;
542     GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
543     path_destroy (p);
544     p = nextp;
545   }
546   GMT_destroy_empty (peer->tunnel);
547   GNUNET_free (peer);
548   return GNUNET_OK;
549 }
550
551
552 /**
553  * Returns if peer is used (has a tunnel or is neighbor).
554  *
555  * @param peer Peer to check.
556  *
557  * @return #GNUNET_YES if peer is in use.
558  */
559 static int
560 peer_is_used (struct MeshPeer *peer)
561 {
562   struct MeshPeerPath *p;
563
564   if (NULL != peer->tunnel)
565     return GNUNET_YES;
566
567   for (p = peer->path_head; NULL != p; p = p->next)
568   {
569     if (p->length < 3)
570       return GNUNET_YES;
571   }
572     return GNUNET_NO;
573 }
574
575
576 /**
577  * Iterator over all the peers to get the oldest timestamp.
578  *
579  * @param cls Closure (unsued).
580  * @param key ID of the peer.
581  * @param value Peer_Info of the peer.
582  */
583 static int
584 peer_get_oldest (void *cls,
585                  const struct GNUNET_PeerIdentity *key,
586                  void *value)
587 {
588   struct MeshPeer *p = value;
589   struct GNUNET_TIME_Absolute *abs = cls;
590
591   /* Don't count active peers */
592   if (GNUNET_YES == peer_is_used (p))
593     return GNUNET_YES;
594
595   if (abs->abs_value_us < p->last_contact.abs_value_us)
596     abs->abs_value_us = p->last_contact.abs_value_us;
597
598   return GNUNET_YES;
599 }
600
601
602 /**
603  * Iterator over all the peers to remove the oldest entry.
604  *
605  * @param cls Closure (unsued).
606  * @param key ID of the peer.
607  * @param value Peer_Info of the peer.
608  */
609 static int
610 peer_timeout (void *cls,
611               const struct GNUNET_PeerIdentity *key,
612               void *value)
613 {
614   struct MeshPeer *p = value;
615   struct GNUNET_TIME_Absolute *abs = cls;
616
617   LOG (GNUNET_ERROR_TYPE_WARNING,
618        "peer %s timeout\n", GNUNET_i2s (key));
619
620   if (p->last_contact.abs_value_us == abs->abs_value_us &&
621       GNUNET_NO == peer_is_used (p))
622   {
623     peer_destroy (p);
624     return GNUNET_NO;
625   }
626     return GNUNET_YES;
627 }
628
629
630 /**
631  * Delete oldest unused peer.
632  */
633 static void
634 peer_delete_oldest (void)
635 {
636   struct GNUNET_TIME_Absolute abs;
637
638   abs = GNUNET_TIME_UNIT_FOREVER_ABS;
639
640   GNUNET_CONTAINER_multipeermap_iterate (peers,
641                                          &peer_get_oldest,
642                                          &abs);
643   GNUNET_CONTAINER_multipeermap_iterate (peers,
644                                          &peer_timeout,
645                                          &abs);
646 }
647
648
649 /**
650  * Choose the best (yet unused) path towards a peer,
651  * considering the tunnel properties.
652  *
653  * @param peer The destination peer.
654  *
655  * @return Best current known path towards the peer, if any.
656  */
657 static struct MeshPeerPath *
658 peer_get_best_path (const struct MeshPeer *peer)
659 {
660   struct MeshPeerPath *best_p;
661   struct MeshPeerPath *p;
662   unsigned int best_cost;
663   unsigned int cost;
664
665   best_cost = UINT_MAX;
666   best_p = NULL;
667   for (p = peer->path_head; NULL != p; p = p->next)
668   {
669     if (GNUNET_YES == GMT_is_path_used (peer->tunnel, p))
670       continue; /* If path is already in use, skip it. */
671
672     if ((cost = GMT_get_path_cost (peer->tunnel, p)) < best_cost)
673     {
674       best_cost = cost;
675       best_p = p;
676     }
677   }
678   return best_p;
679 }
680
681
682 static int
683 queue_is_sendable (struct MeshPeerQueue *q)
684 {
685   /* Is PID-independent? */
686   switch (q->type)
687   {
688     case GNUNET_MESSAGE_TYPE_MESH_ACK:
689     case GNUNET_MESSAGE_TYPE_MESH_POLL:
690       return GNUNET_YES;
691   }
692
693   if (GMC_is_sendable (q->c, q->fwd))
694     return GNUNET_YES;
695
696   return GNUNET_NO;
697 }
698
699
700 /**
701  * Get first sendable message.
702  *
703  * @param peer The destination peer.
704  *
705  * @return Best current known path towards the peer, if any.
706  */
707 static struct MeshPeerQueue *
708 peer_get_first_message (const struct MeshPeer *peer)
709 {
710   struct MeshPeerQueue *q;
711
712   for (q = peer->queue_head; NULL != q; q = q->next)
713   {
714     if (queue_is_sendable (q))
715       return q;
716   }
717
718   return NULL;
719 }
720
721
722 /**
723  * Function to process paths received for a new peer addition. The recorded
724  * paths form the initial tunnel, which can be optimized later.
725  * Called on each result obtained for the DHT search.
726  *
727  * @param cls closure
728  * @param path
729  */
730 static void
731 search_handler (void *cls, const struct MeshPeerPath *path)
732 {
733   struct MeshPeer *peer = cls;
734   unsigned int connection_count;
735
736   GMP_add_path_to_all (path, GNUNET_NO);
737
738   /* Count connections */
739   connection_count = GMT_count_connections (peer->tunnel);
740
741   /* If we already have 3 (or more (?!)) connections, it's enough */
742   if (3 <= connection_count)
743     return;
744
745   if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel))
746   {
747     LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
748     GMP_connect (peer);
749   }
750   return;
751 }
752
753
754 /**
755  * Core callback to write a queued packet to core buffer
756  *
757  * @param cls Closure (peer info).
758  * @param size Number of bytes available in buf.
759  * @param buf Where the to write the message.
760  *
761  * @return number of bytes written to buf
762  */
763 static size_t
764 queue_send (void *cls, size_t size, void *buf)
765 {
766   struct MeshPeer *peer = cls;
767   struct MeshConnection *c;
768   struct MeshPeerQueue *queue;
769   const struct GNUNET_PeerIdentity *dst_id;
770   size_t data_size;
771
772   peer->core_transmit = NULL;
773   LOG (GNUNET_ERROR_TYPE_DEBUG, "* Queue send towards %s (max %u)\n",
774        GMP_2s (peer), size);
775
776   if (NULL == buf || 0 == size)
777   {
778     LOG (GNUNET_ERROR_TYPE_DEBUG, "* Buffer size 0.\n");
779     return 0;
780   }
781
782   /* Initialize */
783   queue = peer_get_first_message (peer);
784   if (NULL == queue)
785   {
786     GNUNET_assert (0); /* Core tmt_rdy should've been canceled FIXME */
787     return 0;
788   }
789   c = queue->c;
790
791   dst_id = GNUNET_PEER_resolve2 (peer->id);
792   LOG (GNUNET_ERROR_TYPE_DEBUG, "*   on connection %s\n", GMC_2s (c));
793   /* Check if buffer size is enough for the message */
794   if (queue->size > size)
795   {
796       LOG (GNUNET_ERROR_TYPE_DEBUG, "*   not enough room, reissue\n");
797       peer->core_transmit =
798           GNUNET_CORE_notify_transmit_ready (core_handle,
799                                              GNUNET_NO,
800                                              0,
801                                              GNUNET_TIME_UNIT_FOREVER_REL,
802                                              dst_id,
803                                              queue->size,
804                                              &queue_send,
805                                              peer);
806       return 0;
807   }
808   LOG (GNUNET_ERROR_TYPE_DEBUG, "*   size %u ok\n", queue->size);
809
810   /* Fill buf */
811   switch (queue->type)
812   {
813     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
814     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
815     case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE:
816     case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
817     case GNUNET_MESSAGE_TYPE_MESH_KX:
818     case GNUNET_MESSAGE_TYPE_MESH_ACK:
819     case GNUNET_MESSAGE_TYPE_MESH_POLL:
820       LOG (GNUNET_ERROR_TYPE_DEBUG,
821                   "*   raw: %s\n",
822                   GM_m2s (queue->type));
823       data_size = send_core_data_raw (queue->cls, size, buf);
824       break;
825     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
826       LOG (GNUNET_ERROR_TYPE_DEBUG, "*   path create\n");
827       if (GMC_is_origin (c, GNUNET_YES))
828         data_size = send_core_connection_create (queue->c, size, buf);
829       else
830         data_size = send_core_data_raw (queue->cls, size, buf);
831       break;
832     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
833       LOG (GNUNET_ERROR_TYPE_DEBUG, "*   path ack\n");
834       if (GMC_is_origin (c, GNUNET_NO) ||
835           GMC_is_origin (c, GNUNET_YES))
836         data_size = send_core_connection_ack (queue->c, size, buf);
837       else
838         data_size = send_core_data_raw (queue->cls, size, buf);
839       break;
840     case GNUNET_MESSAGE_TYPE_MESH_DATA:
841     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
842     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
843       /* This should be encapsulted */
844       GNUNET_break (0);
845       data_size = 0;
846       break;
847     default:
848       GNUNET_break (0);
849       LOG (GNUNET_ERROR_TYPE_WARNING, "*   type unknown: %u\n", queue->type);
850       data_size = 0;
851   }
852
853   if (0 < drop_percent &&
854       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
855   {
856     LOG (GNUNET_ERROR_TYPE_WARNING,
857                 "Dropping message of type %s\n",
858                 GM_m2s (queue->type));
859     data_size = 0;
860   }
861
862   /* Free queue, but cls was freed by send_core_* */
863   GMP_queue_destroy (queue, GNUNET_NO);
864
865   /* If more data in queue, send next */
866   queue = peer_get_first_message (peer);
867   if (NULL != queue)
868   {
869     LOG (GNUNET_ERROR_TYPE_DEBUG, "*   more data!\n");
870     if (NULL == peer->core_transmit)
871     {
872       peer->core_transmit =
873           GNUNET_CORE_notify_transmit_ready(core_handle,
874                                             0,
875                                             0,
876                                             GNUNET_TIME_UNIT_FOREVER_REL,
877                                             dst_id,
878                                             queue->size,
879                                             &queue_send,
880                                             peer);
881       queue->start_waiting = GNUNET_TIME_absolute_get ();
882     }
883     else
884     {
885       LOG (GNUNET_ERROR_TYPE_DEBUG,
886                   "*   tmt rdy called somewhere else\n");
887     }
888 //     GMC_start_poll (); FIXME needed?
889   }
890   else
891   {
892 //     GMC_stop_poll(); FIXME needed?
893   }
894
895   LOG (GNUNET_ERROR_TYPE_DEBUG, "*  Return %d\n", data_size);
896   return data_size;
897 }
898
899
900 /******************************************************************************/
901 /********************************    API    ***********************************/
902 /******************************************************************************/
903
904
905 /**
906  * Free a transmission that was already queued with all resources
907  * associated to the request.
908  *
909  * @param queue Queue handler to cancel.
910  * @param clear_cls Is it necessary to free associated cls?
911  */
912 void
913 GMP_queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
914 {
915   struct MeshPeer *peer;
916
917   peer = queue->peer;
918   GNUNET_assert (NULL != queue->c);
919
920   if (GNUNET_YES == clear_cls)
921   {
922     LOG (GNUNET_ERROR_TYPE_DEBUG, "#   queue destroy type %s\n",
923                 GM_m2s (queue->type));
924     switch (queue->type)
925     {
926       case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
927         LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
928         /* fall through */
929       case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
930       case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
931       case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
932       case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE:
933       case GNUNET_MESSAGE_TYPE_MESH_KX:
934       case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
935       case GNUNET_MESSAGE_TYPE_MESH_ACK:
936       case GNUNET_MESSAGE_TYPE_MESH_POLL:
937         GNUNET_free_non_null (queue->cls);
938         break;
939
940       default:
941         GNUNET_break (0);
942         LOG (GNUNET_ERROR_TYPE_ERROR, "#   type %s unknown!\n",
943                     GM_m2s (queue->type));
944     }
945   }
946   GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
947
948   if (queue->type != GNUNET_MESSAGE_TYPE_MESH_ACK &&
949       queue->type != GNUNET_MESSAGE_TYPE_MESH_POLL)
950   {
951     peer->queue_n--;
952   }
953
954   if (NULL != queue->callback)
955   {
956     LOG (GNUNET_ERROR_TYPE_DEBUG, "#   Calling callback\n");
957     queue->callback (queue->callback_cls,
958                      queue->c, queue->type,
959                      queue->fwd, queue->size,
960                      GNUNET_TIME_absolute_get_duration (queue->start_waiting));
961   }
962
963   GNUNET_free (queue);
964 }
965
966
967 /**
968  * @brief Queue and pass message to core when possible.
969  *
970  * @param peer Peer towards which to queue the message.
971  * @param cls Closure (@c type dependant). It will be used by queue_send to
972  *            build the message to be sent if not already prebuilt.
973  * @param type Type of the message, 0 for a raw message.
974  * @param size Size of the message.
975  * @param c Connection this message belongs to (cannot be NULL).
976  * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
977  * @param cont Continuation to be called once CORE has taken the message.
978  * @param cont_cls Closure for @c cont.
979  *
980  * @return Handle to cancel the message before it is sent. Once cont is called
981  *         message has been sent and therefore the handle is no longer valid.
982  */
983 struct MeshPeerQueue *
984 GMP_queue_add (struct MeshPeer *peer, void *cls, uint16_t type, size_t size,
985                struct MeshConnection *c, int fwd,
986                GMP_sent cont, void *cont_cls)
987 {
988   struct MeshPeerQueue *queue;
989   int priority;
990   int call_core;
991
992   LOG (GNUNET_ERROR_TYPE_DEBUG,
993        "queue add %s %s towards %s (size %u) on c %p (%s)\n",
994        GM_f2s (fwd),  GM_m2s (type), GMP_2s(peer),
995        size, c, GMC_2s (c));
996   GNUNET_assert (NULL != c);
997
998   if (NULL == peer->connections)
999   {
1000     /* We are not connected to this peer, ignore request. */
1001     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING %s not a neighbor\n", GMP_2s (peer));
1002     GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
1003                               GNUNET_NO);
1004     return NULL;
1005   }
1006
1007   priority = 0;
1008
1009   if (GNUNET_MESSAGE_TYPE_MESH_POLL == type ||
1010       GNUNET_MESSAGE_TYPE_MESH_ACK == type)
1011   {
1012     priority = 100;
1013   }
1014
1015   LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
1016
1017   call_core = GMC_is_sendable (c, fwd);
1018   queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
1019   queue->cls = cls;
1020   queue->type = type;
1021   queue->size = size;
1022   queue->peer = peer;
1023   queue->c = c;
1024   queue->fwd = fwd;
1025   queue->callback = cont;
1026   queue->callback_cls = cont_cls;
1027   if (100 > priority)
1028   {
1029     GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue);
1030     peer->queue_n++;
1031   }
1032   else
1033   {
1034     GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
1035     call_core = GNUNET_YES;
1036   }
1037
1038   if (NULL == peer->core_transmit && GNUNET_YES == call_core)
1039   {
1040     LOG (GNUNET_ERROR_TYPE_DEBUG,
1041                 "calling core tmt rdy towards %s for %u bytes\n",
1042                 GMP_2s (peer), size);
1043     peer->core_transmit =
1044         GNUNET_CORE_notify_transmit_ready (core_handle,
1045                                            0,
1046                                            0,
1047                                            GNUNET_TIME_UNIT_FOREVER_REL,
1048                                            GNUNET_PEER_resolve2 (peer->id),
1049                                            size,
1050                                            &queue_send,
1051                                            peer);
1052     queue->start_waiting = GNUNET_TIME_absolute_get ();
1053   }
1054   else
1055   {
1056     LOG (GNUNET_ERROR_TYPE_DEBUG,
1057                 "core tmt rdy towards %s already called\n",
1058                 GMP_2s (peer));
1059
1060   }
1061   return queue;
1062 }
1063
1064
1065 /**
1066  * Cancel all queued messages to a peer that belong to a certain connection.
1067  *
1068  * @param peer Peer towards whom to cancel.
1069  * @param c Connection whose queued messages to cancel. Might be destroyed by
1070  *          the sent continuation call.
1071  */
1072 void
1073 GMP_queue_cancel (struct MeshPeer *peer, struct MeshConnection *c)
1074 {
1075   struct MeshPeerQueue *q;
1076   struct MeshPeerQueue *next;
1077   struct MeshPeerQueue *prev;
1078
1079   for (q = peer->queue_head; NULL != q; q = next)
1080   {
1081     prev = q->prev;
1082     if (q->c == c)
1083     {
1084       LOG (GNUNET_ERROR_TYPE_DEBUG,
1085                   "GMP_cancel_queue %s\n",
1086                   GM_m2s (q->type));
1087       GMP_queue_destroy (q, GNUNET_YES);
1088
1089       /* Get next from prev, q->next might be already freed:
1090        * queue destroy -> callback -> GMC_destroy -> cancel_queues -> here
1091        */
1092       if (NULL == prev)
1093         next = peer->queue_head;
1094       else
1095         next = prev->next;
1096     }
1097     else
1098     {
1099       next = q->next;
1100     }
1101   }
1102   if (NULL == peer->queue_head)
1103   {
1104     if (NULL != peer->core_transmit)
1105     {
1106       GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
1107       peer->core_transmit = NULL;
1108     }
1109   }
1110 }
1111
1112
1113 /**
1114  * Get the first transmittable message for a connection.
1115  *
1116  * @param peer Neighboring peer.
1117  * @param c Connection.
1118  *
1119  * @return First transmittable message.
1120  */
1121 static struct MeshPeerQueue *
1122 connection_get_first_message (struct MeshPeer *peer, struct MeshConnection *c)
1123 {
1124   struct MeshPeerQueue *q;
1125
1126   for (q = peer->queue_head; NULL != q; q = q->next)
1127   {
1128     if (q->c != c)
1129       continue;
1130     if (queue_is_sendable (q))
1131     {
1132       LOG (GNUNET_ERROR_TYPE_DEBUG, "  sendable!!\n");
1133       return q;
1134     }
1135     LOG (GNUNET_ERROR_TYPE_DEBUG, "  not sendable\n");
1136   }
1137
1138   return NULL;
1139 }
1140
1141
1142 void
1143 GMP_queue_unlock (struct MeshPeer *peer, struct MeshConnection *c)
1144 {
1145   struct MeshPeerQueue *q;
1146   size_t size;
1147
1148   if (NULL != peer->core_transmit)
1149   {
1150     LOG (GNUNET_ERROR_TYPE_DEBUG, "  already unlocked!\n");
1151     return; /* Already unlocked */
1152   }
1153
1154   q = connection_get_first_message (peer, c);
1155   if (NULL == q)
1156   {
1157     LOG (GNUNET_ERROR_TYPE_DEBUG, "  queue empty!\n");
1158     return; /* Nothing to transmit */
1159   }
1160
1161   size = q->size;
1162   peer->core_transmit =
1163       GNUNET_CORE_notify_transmit_ready (core_handle,
1164                                          GNUNET_NO,
1165                                          0,
1166                                          GNUNET_TIME_UNIT_FOREVER_REL,
1167                                          GNUNET_PEER_resolve2 (peer->id),
1168                                          size,
1169                                          &queue_send,
1170                                          peer);
1171 }
1172
1173
1174 /**
1175  * Initialize the peer subsystem.
1176  *
1177  * @param c Configuration.
1178  */
1179 void
1180 GMP_init (const struct GNUNET_CONFIGURATION_Handle *c)
1181 {
1182   LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
1183   peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1184   if (GNUNET_OK !=
1185       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
1186                                              &max_peers))
1187   {
1188     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1189                                "MESH", "MAX_PEERS", "USING DEFAULT");
1190     max_peers = 1000;
1191   }
1192
1193   if (GNUNET_OK !=
1194       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT",
1195                                              &drop_percent))
1196   {
1197     drop_percent = 0;
1198   }
1199   else
1200   {
1201     LOG (GNUNET_ERROR_TYPE_WARNING,
1202                 "\n***************************************\n"
1203                 "Mesh is running with drop mode enabled.\n"
1204                 "This is NOT a good idea!\n"
1205                 "Remove the DROP_PERCENT option from your configuration.\n"
1206                 "***************************************\n");
1207   }
1208
1209   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1210                                      NULL,      /* Closure passed to MESH functions */
1211                                      &core_init,        /* Call core_init once connected */
1212                                      &core_connect,     /* Handle connects */
1213                                      &core_disconnect,  /* remove peers on disconnects */
1214                                      NULL,      /* Don't notify about all incoming messages */
1215                                      GNUNET_NO, /* For header only in notification */
1216                                      NULL,      /* Don't notify about all outbound messages */
1217                                      GNUNET_NO, /* For header-only out notification */
1218                                      core_handlers);    /* Register these handlers */
1219   if (NULL == core_handle)
1220   {
1221     GNUNET_break (0);
1222     GNUNET_SCHEDULER_shutdown ();
1223     return;
1224   }
1225 }
1226
1227 /**
1228  * Shut down the peer subsystem.
1229  */
1230 void
1231 GMP_shutdown (void)
1232 {
1233   GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
1234
1235   if (core_handle != NULL)
1236   {
1237     GNUNET_CORE_disconnect (core_handle);
1238     core_handle = NULL;
1239   }
1240   GNUNET_PEER_change_rc (myid, -1);
1241 }
1242
1243 /**
1244  * Retrieve the MeshPeer stucture associated with the peer, create one
1245  * and insert it in the appropriate structures if the peer is not known yet.
1246  *
1247  * @param peer_id Full identity of the peer.
1248  *
1249  * @return Existing or newly created peer structure.
1250  */
1251 struct MeshPeer *
1252 GMP_get (const struct GNUNET_PeerIdentity *peer_id)
1253 {
1254   struct MeshPeer *peer;
1255
1256   peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
1257   if (NULL == peer)
1258   {
1259     peer = GNUNET_new (struct MeshPeer);
1260     if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
1261     {
1262       peer_delete_oldest ();
1263     }
1264         GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
1265                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1266         peer->id = GNUNET_PEER_intern (peer_id);
1267   }
1268   peer->last_contact = GNUNET_TIME_absolute_get();
1269
1270   return peer;
1271 }
1272
1273
1274 /**
1275  * Retrieve the MeshPeer stucture associated with the peer, create one
1276  * and insert it in the appropriate structures if the peer is not known yet.
1277  *
1278  * @param peer Short identity of the peer.
1279  *
1280  * @return Existing or newly created peer structure.
1281  */
1282 struct MeshPeer *
1283 GMP_get_short (const GNUNET_PEER_Id peer)
1284 {
1285   return GMP_get (GNUNET_PEER_resolve2 (peer));
1286 }
1287
1288
1289 /**
1290  * Try to establish a new connection to this peer (in its tunnel).
1291  * If the peer doesn't have any path to it yet, try to get one.
1292  * If the peer already has some path, send a CREATE CONNECTION towards it.
1293  *
1294  * @param peer Peer to connect to.
1295  */
1296 void
1297 GMP_connect (struct MeshPeer *peer)
1298 {
1299   struct MeshTunnel3 *t;
1300   struct MeshPeerPath *p;
1301   struct MeshConnection *c;
1302   int rerun_search;
1303
1304   LOG (GNUNET_ERROR_TYPE_DEBUG, "peer_connect towards %s\n", GMP_2s (peer));
1305   t = peer->tunnel;
1306   c = NULL;
1307   rerun_search = GNUNET_NO;
1308
1309   if (NULL != peer->path_head)
1310   {
1311     LOG (GNUNET_ERROR_TYPE_DEBUG, "  some path exists\n");
1312     p = peer_get_best_path (peer);
1313     if (NULL != p)
1314     {
1315       LOG (GNUNET_ERROR_TYPE_DEBUG, "  %u hops\n", p->length);
1316       c = GMT_use_path (t, p);
1317       if (NULL == c)
1318       {
1319         /* This case can happen when the path includes a first hop that is
1320          * not yet known to be connected.
1321          *
1322          * This happens quite often during testing when running mesh
1323          * under valgrind: core connect notifications come very late and the
1324          * DHT result has already come and created a valid path.
1325          * In this case, the peer->connections hashmap will be NULL and
1326          * tunnel_use_path will not be able to create a connection from that
1327          * path.
1328          *
1329          * Re-running the DHT GET should give core time to callback.
1330          *
1331          * GMT_use_path -> GMC_new -> register_neighbors takes care of
1332          * updating statistics about this issue.
1333          */
1334         rerun_search = GNUNET_YES;
1335       }
1336       else
1337       {
1338         GMC_send_create (c);
1339         return;
1340       }
1341     }
1342     else
1343     {
1344       LOG (GNUNET_ERROR_TYPE_DEBUG, "  but is NULL, all paths are in use\n");
1345     }
1346   }
1347
1348   if (NULL != peer->search_h && GNUNET_YES == rerun_search)
1349   {
1350     GMD_search_stop (peer->search_h);
1351     peer->search_h = NULL;
1352     LOG (GNUNET_ERROR_TYPE_DEBUG,
1353          "  Stopping DHT GET for peer %s\n",
1354          GMP_2s (peer));
1355   }
1356
1357   if (NULL == peer->search_h)
1358   {
1359     const struct GNUNET_PeerIdentity *id;
1360
1361     id = GNUNET_PEER_resolve2 (peer->id);
1362     LOG (GNUNET_ERROR_TYPE_DEBUG,
1363                 "  Starting DHT GET for peer %s\n", GMP_2s (peer));
1364     peer->search_h = GMD_search (id, &search_handler, peer);
1365     if (MESH_TUNNEL3_NEW == GMT_get_cstate (t))
1366       GMT_change_cstate (t, MESH_TUNNEL3_SEARCHING);
1367   }
1368 }
1369
1370
1371 /**
1372  * Set tunnel.
1373  *
1374  * @param peer Peer.
1375  * @param t Tunnel.
1376  */
1377 void
1378 GMP_set_tunnel (struct MeshPeer *peer, struct MeshTunnel3 *t)
1379 {
1380   peer->tunnel = t;
1381 }
1382
1383
1384 /**
1385  * Chech whether there is a direct (core level)  connection to peer.
1386  *
1387  * @param peer Peer to check.
1388  *
1389  * @return #GNUNET_YES if there is a direct connection.
1390  */
1391 int
1392 GMP_is_neighbor (const struct MeshPeer *peer)
1393 {
1394   struct MeshPeerPath *path;
1395
1396   if (NULL == peer->connections)
1397     return GNUNET_NO;
1398
1399   for (path = peer->path_head; NULL != path; path = path->next)
1400   {
1401     if (3 > path->length)
1402       return GNUNET_YES;
1403   }
1404
1405   GNUNET_break (0); /* Is not a neighbor but connections is not NULL */
1406   return GNUNET_NO;
1407 }
1408
1409
1410 /**
1411  * Create and initialize a new tunnel towards a peer, in case it has none.
1412  * In case the peer already has a tunnel, nothing is done.
1413  *
1414  * Does not generate any traffic, just creates the local data structures.
1415  *
1416  * @param peer Peer towards which to create the tunnel.
1417  */
1418 void
1419 GMP_add_tunnel (struct MeshPeer *peer)
1420 {
1421   if (NULL != peer->tunnel)
1422     return;
1423   peer->tunnel = GMT_new (peer);
1424 }
1425
1426
1427 /**
1428  * Add a connection to a neighboring peer.
1429  *
1430  * Store that the peer is the first hop of the connection in one
1431  * direction and that on peer disconnect the connection must be
1432  * notified and destroyed, for it will no longer be valid.
1433  *
1434  * @param peer Peer to add connection to.
1435  * @param c Connection to add.
1436  *
1437  * @return GNUNET_OK on success.
1438  */
1439 int
1440 GMP_add_connection (struct MeshPeer *peer,
1441                     struct MeshConnection *c)
1442 {
1443   if (NULL == peer->connections)
1444   {
1445     GNUNET_break (0);
1446     return GNUNET_SYSERR;
1447   }
1448   return GNUNET_CONTAINER_multihashmap_put (peer->connections,
1449                                             GMC_get_id (c),
1450                                             c,
1451                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1452 }
1453
1454
1455 /**
1456  * Add the path to the peer and update the path used to reach it in case this
1457  * is the shortest.
1458  *
1459  * @param peer Destination peer to add the path to.
1460  * @param path New path to add. Last peer must be the peer in arg 1.
1461  *             Path will be either used of freed if already known.
1462  * @param trusted Do we trust that this path is real?
1463  *
1464  * @return path if path was taken, pointer to existing duplicate if exists
1465  *         NULL on error.
1466  */
1467 struct MeshPeerPath *
1468 GMP_add_path (struct MeshPeer *peer, struct MeshPeerPath *path,
1469               int trusted)
1470 {
1471   struct MeshPeerPath *aux;
1472   unsigned int l;
1473   unsigned int l2;
1474
1475   LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
1476        path->length, GMP_2s (peer));
1477
1478   if ((NULL == peer) || (NULL == path))
1479   {
1480     GNUNET_break (0);
1481     path_destroy (path);
1482     return NULL;
1483   }
1484   if (path->peers[path->length - 1] != peer->id)
1485   {
1486     GNUNET_break (0);
1487     path_destroy (path);
1488     return NULL;
1489   }
1490   if (2 >= path->length && GNUNET_NO == trusted)
1491   {
1492     /* Only allow CORE to tell us about direct paths */
1493     path_destroy (path);
1494     return NULL;
1495   }
1496   for (l = 1; l < path->length; l++)
1497   {
1498     if (path->peers[l] == myid)
1499     {
1500       LOG (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
1501       for (l2 = 0; l2 < path->length - l; l2++)
1502       {
1503         path->peers[l2] = path->peers[l + l2];
1504       }
1505       path->length -= l;
1506       l = 1;
1507       path->peers = GNUNET_realloc (path->peers,
1508                                     path->length * sizeof (GNUNET_PEER_Id));
1509     }
1510   }
1511
1512   LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u]\n", path->length);
1513
1514   l = path_get_length (path);
1515   if (0 == l)
1516   {
1517     path_destroy (path);
1518     return NULL;
1519   }
1520
1521   GNUNET_assert (peer->id == path->peers[path->length - 1]);
1522   for (aux = peer->path_head; aux != NULL; aux = aux->next)
1523   {
1524     l2 = path_get_length (aux);
1525     if (l2 > l)
1526     {
1527       LOG (GNUNET_ERROR_TYPE_DEBUG, "  added\n");
1528       GNUNET_CONTAINER_DLL_insert_before (peer->path_head,
1529                                           peer->path_tail, aux, path);
1530       return path;
1531     }
1532     else
1533     {
1534       if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
1535       {
1536         LOG (GNUNET_ERROR_TYPE_DEBUG, "  already known\n");
1537         path_destroy (path);
1538         return aux;
1539       }
1540     }
1541   }
1542   GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, peer->path_tail,
1543                                     path);
1544   LOG (GNUNET_ERROR_TYPE_DEBUG, "  added last\n");
1545   return path;
1546 }
1547
1548
1549 /**
1550  * Add the path to the origin peer and update the path used to reach it in case
1551  * this is the shortest.
1552  * The path is given in peer_info -> destination, therefore we turn the path
1553  * upside down first.
1554  *
1555  * @param peer Peer to add the path to, being the origin of the path.
1556  * @param path New path to add after being inversed.
1557  *             Path will be either used or freed.
1558  * @param trusted Do we trust that this path is real?
1559  *
1560  * @return path if path was taken, pointer to existing duplicate if exists
1561  *         NULL on error.
1562  */
1563 struct MeshPeerPath *
1564 GMP_add_path_to_origin (struct MeshPeer *peer,
1565                         struct MeshPeerPath *path,
1566                         int trusted)
1567 {
1568   if (NULL == path)
1569     return NULL;
1570   path_invert (path);
1571   return GMP_add_path (peer, path, trusted);
1572 }
1573
1574
1575 /**
1576  * Adds a path to the info of all the peers in the path
1577  *
1578  * @param p Path to process.
1579  * @param confirmed Whether we know if the path works or not.
1580  */
1581 void
1582 GMP_add_path_to_all (const struct MeshPeerPath *p, int confirmed)
1583 {
1584   unsigned int i;
1585
1586   /* TODO: invert and add */
1587   for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
1588   for (i++; i < p->length; i++)
1589   {
1590     struct MeshPeer *aux;
1591     struct MeshPeerPath *copy;
1592
1593     aux = GMP_get_short (p->peers[i]);
1594     copy = path_duplicate (p);
1595     copy->length = i + 1;
1596     GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
1597   }
1598 }
1599
1600
1601 /**
1602  * Remove any path to the peer that has the extact same peers as the one given.
1603  *
1604  * @param peer Peer to remove the path from.
1605  * @param path Path to remove. Is always destroyed .
1606  */
1607 void
1608 GMP_remove_path (struct MeshPeer *peer, struct MeshPeerPath *path)
1609 {
1610   struct MeshPeerPath *iter;
1611   struct MeshPeerPath *next;
1612
1613   GNUNET_assert (myid == path->peers[0]);
1614   GNUNET_assert (peer->id == path->peers[path->length - 1]);
1615
1616   for (iter = peer->path_head; NULL != iter; iter = next)
1617   {
1618     next = iter->next;
1619     if (0 == memcmp (path->peers, iter->peers,
1620                      sizeof (GNUNET_PEER_Id) * path->length))
1621     {
1622       GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter);
1623       path_destroy (iter);
1624       if (path == iter)
1625         return;
1626     }
1627   }
1628   path_destroy (path);
1629 }
1630
1631
1632 /**
1633  * Remove a connection from a neighboring peer.
1634  *
1635  * @param peer Peer to remove connection from.
1636  * @param c Connection to remove.
1637  *
1638  * @return GNUNET_OK on success.
1639  */
1640 int
1641 GMP_remove_connection (struct MeshPeer *peer,
1642                        const struct MeshConnection *c)
1643 {
1644   if (NULL == peer || NULL == peer->connections)
1645   {
1646     LOG (GNUNET_ERROR_TYPE_DEBUG,
1647          "Peer %s is not a neighbor!\n",
1648          GMP_2s (peer));
1649     return GNUNET_SYSERR;
1650   }
1651   return GNUNET_CONTAINER_multihashmap_remove (peer->connections,
1652                                                GMC_get_id (c),
1653                                                c);
1654 }
1655
1656 /**
1657  * Start the DHT search for new paths towards the peer: we don't have
1658  * enough good connections.
1659  *
1660  * @param peer Destination peer.
1661  */
1662 void
1663 GMP_start_search (struct MeshPeer *peer)
1664 {
1665   if (NULL != peer->search_h)
1666   {
1667     GNUNET_break (0);
1668     return;
1669   }
1670
1671   peer->search_h = GMD_search (GMP_get_id (peer), &search_handler, peer);
1672 }
1673
1674
1675 /**
1676  * Stop the DHT search for new paths towards the peer: we already have
1677  * enough good connections.
1678  *
1679  * @param peer Destination peer.
1680  */
1681 void
1682 GMP_stop_search (struct MeshPeer *peer)
1683 {
1684   if (NULL == peer->search_h)
1685   {
1686     GNUNET_break (0);
1687     return;
1688   }
1689
1690   GMD_search_stop (peer->search_h);
1691   peer->search_h = NULL;
1692 }
1693
1694
1695 /**
1696  * Get the Full ID of a peer.
1697  *
1698  * @param peer Peer to get from.
1699  *
1700  * @return Full ID of peer.
1701  */
1702 const struct GNUNET_PeerIdentity *
1703 GMP_get_id (const struct MeshPeer *peer)
1704 {
1705   return GNUNET_PEER_resolve2 (peer->id);
1706 }
1707
1708
1709 /**
1710  * Get the Short ID of a peer.
1711  *
1712  * @param peer Peer to get from.
1713  *
1714  * @return Short ID of peer.
1715  */
1716 GNUNET_PEER_Id
1717 GMP_get_short_id (const struct MeshPeer *peer)
1718 {
1719   return peer->id;
1720 }
1721
1722
1723 /**
1724  * Get the tunnel towards a peer.
1725  *
1726  * @param peer Peer to get from.
1727  *
1728  * @return Tunnel towards peer.
1729  */
1730 struct MeshTunnel3 *
1731 GMP_get_tunnel (const struct MeshPeer *peer)
1732 {
1733   GNUNET_assert (NULL != peer->tunnel);
1734   return peer->tunnel;
1735 }
1736
1737
1738 /**
1739  * Get the static string for a peer ID.
1740  *
1741  * @param peer Peer.
1742  *
1743  * @return Static string for it's ID.
1744  */
1745 const char *
1746 GMP_2s (const struct MeshPeer *peer)
1747 {
1748   if (NULL == peer)
1749     return "(NULL)";
1750   return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
1751 }