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