gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r27681 - in gnunet: . src/exit src/fs src/include src/mesh


From: gnunet
Subject: [GNUnet-SVN] r27681 - in gnunet: . src/exit src/fs src/include src/mesh src/pt src/set src/stream src/vpn
Date: Fri, 28 Jun 2013 16:34:55 +0200

Author: bartpolot
Date: 2013-06-28 16:34:55 +0200 (Fri, 28 Jun 2013)
New Revision: 27681

Added:
   gnunet/src/include/gnunet_mesh_service.h
   gnunet/src/mesh/gnunet-service-mesh.c
   gnunet/src/mesh/mesh.h
   gnunet/src/mesh/mesh_api.c
   gnunet/src/mesh/mesh_protocol.h
   gnunet/src/mesh/mesh_test_lib.c
   gnunet/src/mesh/mesh_test_lib.h
   gnunet/src/mesh/test_mesh.conf
   gnunet/src/mesh/test_mesh_local.c
   gnunet/src/mesh/test_mesh_small.c
Removed:
   gnunet/src/include/gnunet_mesh2_service.h
   gnunet/src/include/gnunet_mesh_service.h
   gnunet/src/mesh/gnunet-service-mesh-new.c
   gnunet/src/mesh/gnunet-service-mesh.c
   gnunet/src/mesh/mesh.h
   gnunet/src/mesh/mesh2.h
   gnunet/src/mesh/mesh2_api.c
   gnunet/src/mesh/mesh2_protocol.h
   gnunet/src/mesh/mesh2_test_lib.c
   gnunet/src/mesh/mesh2_test_lib.h
   gnunet/src/mesh/mesh_api.c
   gnunet/src/mesh/mesh_protocol.h
   gnunet/src/mesh/mesh_test_lib.c
   gnunet/src/mesh/mesh_test_lib.h
   gnunet/src/mesh/test_mesh.conf
   gnunet/src/mesh/test_mesh2.conf
   gnunet/src/mesh/test_mesh2_local.c
   gnunet/src/mesh/test_mesh2_small.c
   gnunet/src/mesh/test_mesh_2dtorus.c
   gnunet/src/mesh/test_mesh_2dtorus.conf
   gnunet/src/mesh/test_mesh_api.c
   gnunet/src/mesh/test_mesh_local_1.c
   gnunet/src/mesh/test_mesh_local_2.c
   gnunet/src/mesh/test_mesh_local_traffic.c
   gnunet/src/mesh/test_mesh_small.c
   gnunet/src/mesh/test_mesh_small.conf
   gnunet/src/mesh/test_mesh_tree_api.c
Modified:
   gnunet/
   gnunet/src/exit/gnunet-daemon-exit.c
   gnunet/src/fs/gnunet-service-fs_mesh.c
   gnunet/src/include/block_mesh.h
   gnunet/src/include/gnunet_stream_lib.h
   gnunet/src/mesh/Makefile.am
   gnunet/src/mesh/gnunet-mesh.c
   gnunet/src/mesh/mesh_path.c
   gnunet/src/mesh/mesh_path.h
   gnunet/src/mesh/plugin_block_mesh.c
   gnunet/src/pt/gnunet-daemon-pt.c
   gnunet/src/set/Makefile.am
   gnunet/src/set/gnunet-service-set.h
   gnunet/src/stream/stream_api.c
   gnunet/src/vpn/gnunet-service-vpn.c
Log:
Replace mesh with new version

Index: gnunet
===================================================================
--- gnunet      2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet      2013-06-28 14:34:55 UTC (rev 27681)

Property changes on: gnunet
___________________________________________________________________
Modified: svn:ignore
## -25,3 +25,4 ##
 stamp-h1
 .metadata
 *kdev*
+test-driver
Modified: gnunet/src/exit/gnunet-daemon-exit.c
===================================================================
--- gnunet/src/exit/gnunet-daemon-exit.c        2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/exit/gnunet-daemon-exit.c        2013-06-28 14:34:55 UTC (rev 
27681)
@@ -209,6 +209,12 @@
   struct GNUNET_MESH_Tunnel *tunnel;
 
   /**
+   * Who is the other end of this tunnel.
+   * FIXME is this needed? Only used for debugging messages
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
    * Active tunnel transmission request (or NULL).
    */
   struct GNUNET_MESH_TransmitHandle *th;
@@ -493,7 +499,6 @@
   ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
                                              GNUNET_NO,
                                              GNUNET_TIME_UNIT_FOREVER_REL,
-                                             NULL,
                                              sizeof (struct 
GNUNET_MessageHeader) + r,
                                              &transmit_reply_to_mesh,
                                              ts);
@@ -506,18 +511,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel 
*tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *ts = *tunnel_ctx;
   const struct GNUNET_TUN_DnsHeader *dns;
@@ -782,7 +784,6 @@
     s->th = GNUNET_MESH_notify_transmit_ready (tunnel, 
                                               GNUNET_NO /* corking */, 
                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                              NULL,
                                               tnq->len,
                                               &send_to_peer_notify_callback,
                                               s);
@@ -799,7 +800,6 @@
     s->th = GNUNET_MESH_notify_transmit_ready (tunnel, 
                                               GNUNET_NO /* corking */, 
                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                              NULL,
                                               tnq->len,
                                               &send_to_peer_notify_callback,
                                               s);
@@ -817,19 +817,19 @@
  * @param tnq message to queue
  */
 static void
-send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
+send_packet_to_mesh_tunnel (struct TunnelState *s,
                            struct TunnelMessageQueue *tnq)
 {
-  struct TunnelState *s;
+  struct GNUNET_MESH_Tunnel *mesh_tunnel;
 
-  s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
+  mesh_tunnel = s->tunnel;
   GNUNET_assert (NULL != s);
   GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head, 
s->specifics.tcp_udp.tail, tnq);
   if (NULL == s->th)
     s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
                                                GNUNET_NO /* cork */,
                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                              NULL, tnq->len,
+                                              tnq->len,
                                               &send_to_peer_notify_callback,
                                               s);
 }
@@ -1019,8 +1019,7 @@
   memcpy (&i2v->icmp_header,
          icmp,
          pktlen);
-  send_packet_to_mesh_tunnel (state->tunnel,
-                             tnq);
+  send_packet_to_mesh_tunnel (state, tnq);
 }
 
 
@@ -1097,8 +1096,7 @@
   memcpy (&urm[1],
          &udp[1],
          pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
-  send_packet_to_mesh_tunnel (state->tunnel,
-                             tnq);
+  send_packet_to_mesh_tunnel (state, tnq);
 }
 
 
@@ -1186,8 +1184,7 @@
   memcpy (&tdm->tcp_header,
          buf, 
          pktlen);
-  send_packet_to_mesh_tunnel (state->tunnel,
-                             tnq);
+  send_packet_to_mesh_tunnel (state, tnq);
 }
 
 
@@ -1796,18 +1793,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel 
*tunnel,
                      void **tunnel_ctx GNUNET_UNUSED,
-                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_TcpServiceStartMessage *start;
@@ -1853,7 +1847,7 @@
   /* setup fresh connection */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received data from %s for forwarding to TCP service %s on port 
%u\n",
-             GNUNET_i2s (sender),
+             GNUNET_i2s (&state->peer),
              GNUNET_h2s (&start->service_descriptor),
              (unsigned int) ntohs (start->tcp_header.destination_port));  
   if (NULL == (state->specifics.tcp_udp.serv = find_service (tcp_services, 
&start->service_descriptor, 
@@ -1884,18 +1878,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
                     void **tunnel_ctx GNUNET_UNUSED,
-                    const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                    const struct GNUNET_MessageHeader *message,
-                    const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                    const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_TcpInternetStartMessage *start;
@@ -1984,7 +1975,7 @@
     char buf[INET6_ADDRSTRLEN];
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received data from %s for starting TCP stream to %s:%u\n",
-               GNUNET_i2s (sender),
+               GNUNET_i2s (&state->peer),
                inet_ntop (af, 
                           &state->specifics.tcp_udp.ri.remote_address.address,
                           buf, sizeof (buf)),
@@ -2008,18 +1999,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
                  void **tunnel_ctx GNUNET_UNUSED,
-                 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                 const struct GNUNET_MessageHeader *message,
-                 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                 const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_TcpDataMessage *data;
@@ -2069,7 +2057,7 @@
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received additional %u bytes of data from %s for TCP stream to 
%s:%u\n",
                pkt_len,
-               GNUNET_i2s (sender),
+               GNUNET_i2s (&state->peer),
                inet_ntop (state->specifics.tcp_udp.ri.remote_address.af, 
                           &state->specifics.tcp_udp.ri.remote_address.address,
                           buf, sizeof (buf)),
@@ -2244,18 +2232,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel 
*tunnel,
                     void **tunnel_ctx GNUNET_UNUSED,
-                    const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                    const struct GNUNET_MessageHeader *message,
-                    const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                    const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_IcmpInternetMessage *msg;
@@ -2428,7 +2413,7 @@
     char buf[INET6_ADDRSTRLEN];
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received ICMP data from %s for forwarding to %s\n",
-               GNUNET_i2s (sender),
+               GNUNET_i2s (&state->peer),
                inet_ntop (af, 
                           &state->specifics.tcp_udp.ri.remote_address.address,
                           buf, sizeof (buf)));
@@ -2498,18 +2483,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel 
*tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_IcmpServiceMessage *msg;
@@ -2544,7 +2526,7 @@
   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received data from %s for forwarding to ICMP service %s\n",
-             GNUNET_i2s (sender),
+             GNUNET_i2s (&state->peer),
              GNUNET_h2s (&msg->service_descriptor));
   if (NULL == state->specifics.tcp_udp.serv)
   {
@@ -2789,18 +2771,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
                     void **tunnel_ctx GNUNET_UNUSED,
-                    const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                    const struct GNUNET_MessageHeader *message,
-                    const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                    const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_UdpInternetMessage *msg;
@@ -2877,7 +2856,7 @@
     char buf[INET6_ADDRSTRLEN];
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received data from %s for forwarding to UDP %s:%u\n",
-               GNUNET_i2s (sender),
+               GNUNET_i2s (&state->peer),
                inet_ntop (af, 
                           &state->specifics.tcp_udp.ri.remote_address.address,
                           buf, sizeof (buf)),
@@ -2903,18 +2882,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel 
*tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *state = *tunnel_ctx;
   const struct GNUNET_EXIT_UdpServiceMessage *msg;
@@ -2946,7 +2922,7 @@
   pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received data from %s for forwarding to UDP service %s on port %u\n",
-       GNUNET_i2s (sender),
+       GNUNET_i2s (&state->peer),
        GNUNET_h2s (&msg->service_descriptor),
        (unsigned int) ntohs (msg->destination_port));  
   if (NULL == (state->specifics.tcp_udp.serv = find_service (udp_services, 
&msg->service_descriptor, 
@@ -2978,17 +2954,17 @@
  * @param cls closure
  * @param tunnel new handle to the tunnel
  * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
+ * @param port destination port
  * @return initial tunnel context for the tunnel
  */
 static void *
 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
-            const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
-            const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+            const struct GNUNET_PeerIdentity *initiator, uint32_t port)
 {
   struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
 
   s->is_dns = GNUNET_SYSERR;
+  s->peer = *initiator;
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# Inbound MESH tunnels created"),
                            1, GNUNET_NO);
@@ -3338,7 +3314,7 @@
     {NULL, 0, 0}
   };
 
-  static GNUNET_MESH_ApplicationType apptypes[] = {
+  static uint32_t apptypes[] = {
     GNUNET_APPLICATION_TYPE_END,
     GNUNET_APPLICATION_TYPE_END,
     GNUNET_APPLICATION_TYPE_END,
@@ -3413,7 +3389,7 @@
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("No useful service enabled.  Exiting.\n"));
     GNUNET_SCHEDULER_shutdown ();
-    return;    
+    return;
   }
 
   dns_exit = NULL;
@@ -3436,18 +3412,21 @@
 
 
   app_idx = 0;
-  if (GNUNET_YES == ipv4_exit)    
+  if (GNUNET_YES == ipv4_exit)
   {
+    // FIXME use regex to put info
     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
     app_idx++;
   }
-  if (GNUNET_YES == ipv6_exit)    
+  if (GNUNET_YES == ipv6_exit)
   {
+    // FIXME use regex to put info
     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
     app_idx++;
   }
   if (NULL != dns_exit)
   {
+    // FIXME use regex to put info
     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER;
     app_idx++;
   }
@@ -3568,7 +3547,7 @@
     = GNUNET_MESH_connect (cfg, NULL, 
                           &new_tunnel, 
                           &clean_tunnel, handlers,
-                           apptypes);
+                           apptypes); // FIXME use ports
   if (NULL == mesh_handle)
   {
     GNUNET_SCHEDULER_shutdown ();

Modified: gnunet/src/fs/gnunet-service-fs_mesh.c
===================================================================
--- gnunet/src/fs/gnunet-service-fs_mesh.c      2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/fs/gnunet-service-fs_mesh.c      2013-06-28 14:34:55 UTC (rev 
27681)
@@ -41,7 +41,7 @@
 #include "platform.h"
 #include "gnunet_constants.h"
 #include "gnunet_util_lib.h"
-#include "gnunet_mesh2_service.h"
+#include "gnunet_mesh_service.h"
 #include "gnunet_protocols.h"
 #include "gnunet_applications.h"
 #include "gnunet-service-fs.h"

Modified: gnunet/src/include/block_mesh.h
===================================================================
--- gnunet/src/include/block_mesh.h     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/include/block_mesh.h     2013-06-28 14:34:55 UTC (rev 27681)
@@ -48,10 +48,6 @@
      */
   struct GNUNET_PeerIdentity id;
 
-    /**
-     * Type of service offered
-     */
-  GNUNET_MESH_ApplicationType type;
 };
 
 #if 0                           /* keep Emacsens' auto-indent happy */

Deleted: gnunet/src/include/gnunet_mesh2_service.h
===================================================================
--- gnunet/src/include/gnunet_mesh2_service.h   2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/include/gnunet_mesh2_service.h   2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,398 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010, 2011, 2012, 2013 Christian Grothoff (and other 
contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file include/gnunet_mesh2_service.h
- * @brief mesh service; establish tunnels to distant peers
- * @author Christian Grothoff
- *
- * TODO:
- * - need to do sanity check that this is consistent
- *   with current ideas for the multicast layer's needs
- */
-
-#ifndef GNUNET_MESH_SERVICE_H
-#define GNUNET_MESH_SERVICE_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_util_lib.h"
-#include "gnunet_transport_service.h"
-
-/**
- * Version number of GNUnet-mesh API.
- */
-#define GNUNET_MESH_VERSION 0x00000001
-
-
-/**
- * Opaque handle to the service.
- */
-struct GNUNET_MESH_Handle;
-
-/**
- * Opaque handle to a tunnel.
- */
-struct GNUNET_MESH_Tunnel;
-
-
-/**
- * Functions with this signature are called whenever a message is
- * received.
- * 
- * Each time the function must call GNUNET_MESH_receive_done on the tunnel
- * in order to receive the next message. This doesn't need to be immediate:
- * can be delayed if some processing is done on the message.
- *
- * @param cls Closure (set from GNUNET_MESH_connect).
- * @param tunnel Connection to the other end.
- * @param tunnel_ctx Place to store local state associated with the tunnel.
- * @param message The actual message.
- * 
- * @return GNUNET_OK to keep the tunnel open,
- *         GNUNET_SYSERR to close it (signal serious error).
- */
-typedef int (*GNUNET_MESH_MessageCallback) (void *cls,
-                                            struct GNUNET_MESH_Tunnel *tunnel,
-                                            void **tunnel_ctx,
-                                            const struct GNUNET_MessageHeader 
*message);
-
-
-/**
- * Message handler.  Each struct specifies how to handle on particular
- * type of message received.
- */
-struct GNUNET_MESH_MessageHandler
-{
-  /**
-   * Function to call for messages of "type".
-   */
-  GNUNET_MESH_MessageCallback callback;
-
-  /**
-   * Type of the message this handler covers.
-   */
-  uint16_t type;
-
-  /**
-   * Expected size of messages of this type.  Use 0 for variable-size.
-   * If non-zero, messages of the given type will be discarded if they
-   * do not have the right size.
-   */
-  uint16_t expected_size;
-};
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- * Only called (once) upon reception of data with a message type which was
- * subscribed to in GNUNET_MESH_connect. A call to GNUNET_MESH_tunnel_destroy
- * causes te tunnel to be ignored and no further notifications are sent about
- * the same tunnel.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param port Port this tunnel is for.
- * @return initial tunnel context for the tunnel
- *         (can be NULL -- that's not an error)
- */
-typedef void *(GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls,
-                                                              struct
-                                                              
GNUNET_MESH_Tunnel
-                                                              * tunnel,
-                                                              const struct
-                                                              
GNUNET_PeerIdentity
-                                                              * initiator,
-                                                              uint32_t port);
-
-
-/**
- * Function called whenever a tunnel is destroyed.  Should clean up
- * any associated state. 
- * 
- * It must NOT call GNUNET_MESH_tunnel_destroy on the tunnel.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls,
-                                             const struct GNUNET_MESH_Tunnel *
-                                             tunnel, void *tunnel_ctx);
-
-
-/**
- * Connect to the mesh service.
- *
- * @param cfg Configuration to use.
- * @param cls Closure for the various callbacks that follow (including 
- *            handlers in the handlers array).
- * @param new_tunnel Function called when an *inbound* tunnel is created.
- *                   Can be NULL if no inbound tunnels are desired.
- * @param cleaner Function called when a tunnel is destroyed by the remote 
peer.
- *                It is NOT called if GNUNET_MESH_tunnel_destroy is called on
- *                the tunnel.
- * @param handlers Callbacks for messages we care about, NULL-terminated. Each
- *                 one must call GNUNET_MESH_receive_done on the tunnel to
- *                 receive the next message.  Messages of a type that is not
- *                 in the handlers array are ignored if received. 
- * @param ports NULL or 0-terminated array of port numbers for incoming 
tunnels.
- * 
- * @return handle to the mesh service NULL on error
- *         (in this case, init is never called)
- */
-struct GNUNET_MESH_Handle *
-GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
-                     GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                     GNUNET_MESH_TunnelEndHandler cleaner,
-                     const struct GNUNET_MESH_MessageHandler *handlers,
-                     const uint32_t *ports);
-
-
-/**
- * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
- * disconnect callbacks will be called on any still connected peers, notifying
- * about their disconnection. The registered inbound tunnel cleaner will be
- * called should any inbound tunnels still exist.
- *
- * @param handle connection to mesh to disconnect
- */
-void
-GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle);
-
-
-/**
- * Create a new tunnel (we're initiator and will be allowed to add/remove peers
- * and to broadcast).
- *
- * @param h mesh handle
- * @param tunnel_ctx client's tunnel context to associate with the tunnel
- * @param peer peer identity the tunnel should go to
- * @param port Port number.
- * @return handle to the tunnel
- */
-struct GNUNET_MESH_Tunnel *
-GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, 
-                           void *tunnel_ctx,
-                           const struct GNUNET_PeerIdentity *peer,
-                           uint32_t port);
-
-
-/**
- * Destroy an existing tunnel.
- * 
- * The existing end callback for the tunnel will be called immediately.
- * Any pending outgoing messages will be sent but no incoming messages will be
- * accepted and no data callbacks will be called.
- *
- * @param tunnel Tunnel handle, becomes invalid after this call.
- */
-void
-GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-/**
- * Turn on/off the buffering status of the tunnel.
- * 
- * @param tunnel Tunnel affected.
- * @param buffer GNUNET_YES to turn buffering on (default),
- *               GNUNET_NO otherwise.
- */
-void
-GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer);
-
-
-/**
- * Handle for a transmission request.
- */
-struct GNUNET_MESH_TransmitHandle;
-
-
-/**
- * Ask the mesh to call "notify" once it is ready to transmit the
- * given number of bytes to the specified tunnel.
- * Only one call can be active at any time, to issue another request,
- * wait for the callback or cancel the current request.
- *
- * @param tunnel tunnel to use for transmission
- * @param cork is corking allowed for this transmission?
- * @param maxdelay how long can the message wait?
- * @param notify_size how many bytes of buffer space does notify want?
- * @param notify function to call when buffer space is available;
- *        will be called with NULL on timeout or if the overall queue
- *        for this peer is larger than queue_size and this is currently
- *        the message with the lowest priority
- * @param notify_cls closure for notify
- * @return non-NULL if the notify callback was queued,
- *         NULL if we can not even queue the request (insufficient
- *         memory); if NULL is returned, "notify" will NOT be called.
- */
-struct GNUNET_MESH_TransmitHandle *
-GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
-                                   struct GNUNET_TIME_Relative maxdelay,
-                                   size_t notify_size,
-                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
-                                   void *notify_cls);
-
-
-/**
- * Cancel the specified transmission-ready notification.
- *
- * @param th handle that was returned by "notify_transmit_ready".
- */
-void
-GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle
-                                          *th);
-
-
-/**
- * Indicate readiness to receive the next message on a tunnel.
- * 
- * Should only be called once per handler called.
- *
- * @param tunnel Tunnel that will be allowed to call another handler.
- */
-void
-GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-
-/******************************************************************************/
-/********************       MONITORING /DEBUG API     
*************************/
-/******************************************************************************/
-/* The following calls are not useful for normal MESH operation, but for      
*/
-/* debug and monitoring of the mesh state. They can be safely ignored.        
*/
-/* The API can change at any point without notice.                            
*/
-/* Please contact the developer if you consider any of this calls useful for  
*/
-/* normal mesh applications.                                                  
*/
-/******************************************************************************/
-
-/**
- * Method called to retrieve information about each tunnel the mesh peer
- * is aware of.
- *
- * @param cls Closure.
- * @param tunnel_number Tunnel number.
- * @param origin that started the tunnel (owner).
- * @param target other endpoint of the tunnel
- */
-typedef void (*GNUNET_MESH_TunnelsCB) (void *cls,
-                                       uint32_t tunnel_number,
-                                       const struct GNUNET_PeerIdentity 
*origin,
-                                       const struct GNUNET_PeerIdentity 
*target);
-
-
-/**
- * Method called to retrieve information about a specific tunnel the mesh peer
- * is aware of, including all transit nodes.
- *
- * @param cls Closure.
- * @param peer Peer in the tunnel's tree.
- * @param parent Parent of the current peer. All 0 when peer is root.
- */
-typedef void (*GNUNET_MESH_TunnelCB) (void *cls,
-                                      const struct GNUNET_PeerIdentity *peer,
-                                      const struct GNUNET_PeerIdentity 
*parent);
-
-
-/**
- * Request information about the running mesh peer.
- * The callback will be called for every tunnel known to the service,
- * listing all active peers that belong to the tunnel.
- *
- * If called again on the same handle, it will overwrite the previous
- * callback and cls. To retrieve the cls, monitor_cancel must be
- * called first.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
-                         GNUNET_MESH_TunnelsCB callback,
-                         void *callback_cls);
-
-
-/**
- * Request information about a specific tunnel of the running mesh peer.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param initiator ID of the owner of the tunnel.
- * @param tunnel_number Tunnel number.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
-                         struct GNUNET_PeerIdentity *initiator,
-                         uint32_t tunnel_number,
-                         GNUNET_MESH_TunnelCB callback,
-                         void *callback_cls);
-
-
-/**
- * Cancel a monitor request. The monitor callback will not be called.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Mesh handle.
- *
- * @return Closure given to GNUNET_MESH_monitor, if any.
- */
-void *
-GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h);
-
-
-/**
- * Create a message queue for a mesh tunnel.
- * The message queue can only be used to transmit messages,
- * not to receive them.
- *
- * @param tunnel the tunnel to create the message qeue for
- * @return a message queue to messages over the tunnel
- */
-struct GNUNET_MQ_Handle *
-GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_MESH_SERVICE_H */
-#endif
-/* end of gnunet_mesh_service.h */

Deleted: gnunet/src/include/gnunet_mesh_service.h
===================================================================
--- gnunet/src/include/gnunet_mesh_service.h    2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/include/gnunet_mesh_service.h    2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,539 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file include/gnunet_mesh_service.h
- * @brief mesh service; establish tunnels to distant peers
- * @author Christian Grothoff
- */
-
-#ifndef GNUNET_MESH_SERVICE_H
-#define GNUNET_MESH_SERVICE_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_util_lib.h"
-#include "gnunet_transport_service.h"
-
-/**
- * Version number of GNUnet-mesh API.
- */
-#define GNUNET_MESH_VERSION 0x00000000
-
-
-/**
- * Opaque handle to the service.
- */
-struct GNUNET_MESH_Handle;
-
-/**
- * Opaque handle to a tunnel.
- */
-struct GNUNET_MESH_Tunnel;
-
-/**
- * Functions with this signature are called whenever a message is
- * received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-typedef int (*GNUNET_MESH_MessageCallback) (void *cls,
-                                            struct GNUNET_MESH_Tunnel * tunnel,
-                                            void **tunnel_ctx,
-                                            const struct GNUNET_PeerIdentity *
-                                            sender,
-                                            const struct GNUNET_MessageHeader *
-                                            message,
-                                            const struct GNUNET_ATS_Information
-                                            * atsi);
-
-
-/**
- * Message handler.  Each struct specifies how to handle on particular
- * type of message received.
- */
-struct GNUNET_MESH_MessageHandler
-{
-  /**
-   * Function to call for messages of "type".
-   */
-  GNUNET_MESH_MessageCallback callback;
-
-  /**
-   * Type of the message this handler covers.
-   */
-  uint16_t type;
-
-  /**
-   * Expected size of messages of this type.  Use 0 for variable-size.
-   * If non-zero, messages of the given type will be discarded if they
-   * do not have the right size.
-   */
-  uint16_t expected_size;
-
-};
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- * Only called (once) upon reception of data with a message type which was
- * subscribed to in GNUNET_MESH_connect. A call to GNUNET_MESH_tunnel_destroy
- * causes te tunnel to be ignored and no further notifications are sent about
- * the same tunnel.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel
- *         (can be NULL -- that's not an error)
- */
-typedef void *(GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls,
-                                                              struct
-                                                              
GNUNET_MESH_Tunnel
-                                                              * tunnel,
-                                                              const struct
-                                                              
GNUNET_PeerIdentity
-                                                              * initiator,
-                                                              const struct
-                                                              
GNUNET_ATS_Information
-                                                              * atsi);
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.  This function is NOT called if the client has
- * explicitly asked for the tunnel to be destroyed using
- * GNUNET_MESH_tunnel_destroy. It must NOT call GNUNET_MESH_tunnel_destroy on
- * the tunnel.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls,
-                                             const struct GNUNET_MESH_Tunnel *
-                                             tunnel, void *tunnel_ctx);
-
-
-/**
- * Type for an application.  Values defined in gnunet_applications.h
- * DEPRECATED - not present in mesh2
- */
-typedef uint32_t GNUNET_MESH_ApplicationType;
-
-
-/**
- * Connect to the mesh service.
- *
- * @param cfg configuration to use
- * @param cls closure for the various callbacks that follow
- *            (including handlers in the handlers array)
- * @param new_tunnel function called when an *inbound* tunnel is created
- * @param cleaner function called when an *inbound* tunnel is destroyed by the
- *                remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
- *                is called on the tunnel
- * @param handlers callbacks for messages we care about, NULL-terminated
- *                note that the mesh is allowed to drop notifications about
- *                inbound messages if the client does not process them fast
- *                enough (for this notification type, a bounded queue is used)
- * @param stypes list of the applications that this client claims to provide
- * @return handle to the mesh service NULL on error
- *         (in this case, init is never called)
- */
-struct GNUNET_MESH_Handle *
-GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
-                     GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                     GNUNET_MESH_TunnelEndHandler cleaner,
-                     const struct GNUNET_MESH_MessageHandler *handlers,
-                     const GNUNET_MESH_ApplicationType *stypes);
-
-
-/**
- * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
- * disconnect callbacks will be called on any still connected peers, notifying
- * about their disconnection. The registered inbound tunnel cleaner will be
- * called should any inbound tunnels still exist.
- *
- * @param handle connection to mesh to disconnect
- */
-void
-GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle);
-
-
-/**
- * Method called whenever a peer has disconnected from the tunnel.
- * Implementations of this callback must NOT call
- * GNUNET_MESH_tunnel_destroy immediately, but instead schedule those
- * to run in some other task later.  However, calling 
- * "GNUNET_MESH_notify_transmit_ready_cancel" is allowed.
- *
- * @param cls closure
- * @param peer peer identity the tunnel stopped working with
- */
-typedef void (*GNUNET_MESH_PeerDisconnectHandler) (void *cls,
-                                                   const struct
-                                                   GNUNET_PeerIdentity * peer);
-
-
-/**
- * Method called whenever a peer has connected to the tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel was created to, NULL on timeout
- * @param atsi performance data for the connection
- *
- * TODO: change to return int to let client allow the new peer or not?
- */
-typedef void (*GNUNET_MESH_PeerConnectHandler) (void *cls,
-                                                const struct 
GNUNET_PeerIdentity
-                                                * peer,
-                                                const struct
-                                                GNUNET_ATS_Information * atsi);
-
-
-/**
- * Announce to ther peer the availability of services described by the regex,
- * in order to be reachable to other peers via connect_by_string.
- * 
- * Note that the first GNUNET_REGEX_INITIAL_BYTES characters are considered
- * to be part of a prefix, (for instance 'gnunet://').
- * If you put a variable part in there (*, +. ()), all matching strings
- * will be stored in the DHT.
- *
- * @param h Handle to mesh.
- * @param regex String with the regular expression describing local services.
- * @param compression_characters How many characters can be assigned to one
- *                               edge of the graph. The bigger the variability
- *                               of the data, the smaller this parameter should
- *                               be (down to 1).
- *                               For maximum compression, use strlen (regex)
- *                               or 0 (special value). Use with care!
- */
-void
-GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
-                            const char *regex,
-                            unsigned int compression_characters);
-
-
-/**
- * Create a new tunnel (we're initiator and will be allowed to add/remove peers
- * and to broadcast).
- *
- * @param h mesh handle
- * @param tunnel_ctx client's tunnel context to associate with the tunnel
- * @param connect_handler function to call when peers are actually connected
- * @param disconnect_handler function to call when peers are disconnected
- * @param handler_cls closure for connect/disconnect handlers
- */
-struct GNUNET_MESH_Tunnel *
-GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
-                           GNUNET_MESH_PeerConnectHandler connect_handler,
-                           GNUNET_MESH_PeerDisconnectHandler 
disconnect_handler,
-                           void *handler_cls);
-
-/**
- * Destroy an existing tunnel. The existing callback for the tunnel will NOT
- * be called.
- *
- * @param tunnel tunnel handle
- */
-void
-GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-/**
- * Request that the tunnel data rate is limited to the speed of the slowest
- * receiver.
- * 
- * @param tunnel Tunnel affected.
- */
-void
-GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-/**
- * Request that the tunnel data rate is limited to the speed of the fastest
- * receiver. This is the default behavior.
- * 
- * @param tunnel Tunnel affected.
- */
-void
-GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-/**
- * Turn on/off the buffering status of the tunnel.
- * 
- * @param tunnel Tunnel affected.
- * @param buffer GNUNET_YES to turn buffering on (default),
- *               GNUNET_NO otherwise.
- */
-void
-GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer);
-
-
-/**
- * Request that a peer should be added to the tunnel.  The connect handler
- * will be called when the peer connects
- *
- * @param tunnel handle to existing tunnel
- * @param peer peer to add
- */
-void
-GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
-                                      const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Request that a peer should be removed from the tunnel.  The existing
- * disconnect handler will be called ONCE if we were connected.
- *
- * @param tunnel handle to existing tunnel
- * @param peer peer to remove
- */
-void
-GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
-                                      const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Request that the mesh should try to connect to a peer supporting the given
- * message type.
- *
- * @param tunnel handle to existing tunnel
- * @param app_type application type that must be supported by the peer
- *                 (MESH should discover peer in proximity handling this type)
- */
-void
-GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
-                                          GNUNET_MESH_ApplicationType 
app_type);
-
-
-/**
- * Request that the mesh should try to connect to a peer matching the
- * description given in the service string.
- *
- * @param tunnel handle to existing tunnel
- * @param description string describing the destination node requirements
- */
-void
-GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
-                                            const char *description);
-
-
-/**
- * Request that the given peer isn't added to this tunnel in calls to
- * connect_by_* calls, (due to misbehaviour, bad performance, ...).
- *
- * @param tunnel handle to existing tunnel.
- * @param peer peer identity of the peer which should be blacklisted
- *                  for the tunnel.
- */
-void
-GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
-                            const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Request that the given peer isn't blacklisted anymore from this tunnel,
- * and therefore can be added in future calls to connect_by_*.
- * The peer must have been previously blacklisted for this tunnel.
- *
- * @param tunnel handle to existing tunnel.
- * @param peer peer identity of the peer which shouldn't be blacklisted
- *                  for the tunnel anymore.
- */
-void
-GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
-                              const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Handle for a transmission request.
- */
-struct GNUNET_MESH_TransmitHandle;
-
-
-/**
- * Ask the mesh to call "notify" once it is ready to transmit the
- * given number of bytes to the specified tunnel or target.
- * Only one call can be active at any time, to issue another request,
- * wait for the callback or cancel the current request.
- *
- * @param tunnel tunnel to use for transmission
- * @param cork is corking allowed for this transmission?
- * @param maxdelay how long can the message wait?
- * @param target destination for the message
- *               NULL for multicast to all tunnel targets
- * @param notify_size how many bytes of buffer space does notify want?
- * @param notify function to call when buffer space is available;
- *        will be called with NULL on timeout or if the overall queue
- *        for this peer is larger than queue_size and this is currently
- *        the message with the lowest priority
- * @param notify_cls closure for notify
- * @return non-NULL if the notify callback was queued,
- *         NULL if we can not even queue the request (insufficient
- *         memory); if NULL is returned, "notify" will NOT be called.
- */
-struct GNUNET_MESH_TransmitHandle *
-GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
-                                   struct GNUNET_TIME_Relative maxdelay,
-                                   const struct GNUNET_PeerIdentity *target,
-                                   size_t notify_size,
-                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
-                                   void *notify_cls);
-
-
-/**
- * Cancel the specified transmission-ready notification.
- *
- * @param th handle that was returned by "notify_transmit_ready".
- */
-void
-GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle
-                                          *th);
-
-
-/**
- * Method called to retrieve information about each tunnel the mesh peer
- * is aware of.
- *
- * @param cls Closure.
- * @param initiator Peer that started the tunnel (owner).
- * @param tunnel_number Tunnel number.
- * @param peers Array of peer identities that participate in the tunnel.
- * @param npeers Number of peers in peers.
- */
-typedef void (*GNUNET_MESH_TunnelsCB) (void *cls,
-                                       const struct GNUNET_PeerIdentity *owner,
-                                       unsigned int tunnel_number,
-                                       const struct GNUNET_PeerIdentity *peers,
-                                       unsigned int npeers);
-
-
-/**
- * Method called to retrieve information about a specific tunnel the mesh peer
- * is aware of, including all transit nodes.
- *
- * @param cls Closure.
- * @param peer Peer in the tunnel's tree.
- * @param parent Parent of the current peer. All 0 when peer is root.
- */
-typedef void (*GNUNET_MESH_TunnelCB) (void *cls,
-                                      const struct GNUNET_PeerIdentity *peer,
-                                      const struct GNUNET_PeerIdentity 
*parent);
-
-
-/**
- * Request information about the running mesh peer.
- * The callback will be called for every tunnel known to the service,
- * listing all active peers that blong to the tunnel.
- *
- * If called again on the same handle, it will overwrite the previous
- * callback and cls. To retrieve the cls, monitor_cancel must be
- * called first.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
-                         GNUNET_MESH_TunnelsCB callback,
-                         void *callback_cls);
-
-
-/**
- * Request information about a specific tunnel of the running mesh peer.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param initiator ID of the owner of the tunnel.
- * @param tunnel_number Tunnel number.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
-                         struct GNUNET_PeerIdentity *initiator,
-                         unsigned int tunnel_number,
-                         GNUNET_MESH_TunnelCB callback,
-                         void *callback_cls);
-
-
-/**
- * Cancel a monitor request. The monitor callback will not be called.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Mesh handle.
- *
- * @return Closure given to GNUNET_MESH_monitor, if any.
- */
-void *
-GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h);
-
-
-/**
- * Transition API for tunnel ctx management
- * 
- * FIXME deprecated
- */
-void
-GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data);
-
-/**
- * Transition API for tunnel ctx management
- * 
- * FIXME deprecated
- */
-void *
-GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_MESH_SERVICE_H */
-#endif
-/* end of gnunet_mesh_service.h */

Copied: gnunet/src/include/gnunet_mesh_service.h (from rev 27670, 
gnunet/src/include/gnunet_mesh2_service.h)
===================================================================
--- gnunet/src/include/gnunet_mesh_service.h                            (rev 0)
+++ gnunet/src/include/gnunet_mesh_service.h    2013-06-28 14:34:55 UTC (rev 
27681)
@@ -0,0 +1,398 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009, 2010, 2011, 2012, 2013 Christian Grothoff (and other 
contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file include/gnunet_mesh_service.h
+ * @brief mesh service; establish tunnels to distant peers
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - need to do sanity check that this is consistent
+ *   with current ideas for the multicast layer's needs
+ */
+
+#ifndef GNUNET_MESH_SERVICE_H
+#define GNUNET_MESH_SERVICE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+#include "gnunet_transport_service.h"
+
+/**
+ * Version number of GNUnet-mesh API.
+ */
+#define GNUNET_MESH_VERSION 0x00000001
+
+
+/**
+ * Opaque handle to the service.
+ */
+struct GNUNET_MESH_Handle;
+
+/**
+ * Opaque handle to a tunnel.
+ */
+struct GNUNET_MESH_Tunnel;
+
+
+/**
+ * Functions with this signature are called whenever a message is
+ * received.
+ * 
+ * Each time the function must call GNUNET_MESH_receive_done on the tunnel
+ * in order to receive the next message. This doesn't need to be immediate:
+ * can be delayed if some processing is done on the message.
+ *
+ * @param cls Closure (set from GNUNET_MESH_connect).
+ * @param tunnel Connection to the other end.
+ * @param tunnel_ctx Place to store local state associated with the tunnel.
+ * @param message The actual message.
+ * 
+ * @return GNUNET_OK to keep the tunnel open,
+ *         GNUNET_SYSERR to close it (signal serious error).
+ */
+typedef int (*GNUNET_MESH_MessageCallback) (void *cls,
+                                            struct GNUNET_MESH_Tunnel *tunnel,
+                                            void **tunnel_ctx,
+                                            const struct GNUNET_MessageHeader 
*message);
+
+
+/**
+ * Message handler.  Each struct specifies how to handle on particular
+ * type of message received.
+ */
+struct GNUNET_MESH_MessageHandler
+{
+  /**
+   * Function to call for messages of "type".
+   */
+  GNUNET_MESH_MessageCallback callback;
+
+  /**
+   * Type of the message this handler covers.
+   */
+  uint16_t type;
+
+  /**
+   * Expected size of messages of this type.  Use 0 for variable-size.
+   * If non-zero, messages of the given type will be discarded if they
+   * do not have the right size.
+   */
+  uint16_t expected_size;
+};
+
+
+/**
+ * Method called whenever another peer has added us to a tunnel
+ * the other peer initiated.
+ * Only called (once) upon reception of data with a message type which was
+ * subscribed to in GNUNET_MESH_connect. A call to GNUNET_MESH_tunnel_destroy
+ * causes te tunnel to be ignored and no further notifications are sent about
+ * the same tunnel.
+ *
+ * @param cls closure
+ * @param tunnel new handle to the tunnel
+ * @param initiator peer that started the tunnel
+ * @param port Port this tunnel is for.
+ * @return initial tunnel context for the tunnel
+ *         (can be NULL -- that's not an error)
+ */
+typedef void *(GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls,
+                                                              struct
+                                                              
GNUNET_MESH_Tunnel
+                                                              * tunnel,
+                                                              const struct
+                                                              
GNUNET_PeerIdentity
+                                                              * initiator,
+                                                              uint32_t port);
+
+
+/**
+ * Function called whenever a tunnel is destroyed.  Should clean up
+ * any associated state. 
+ * 
+ * It must NOT call GNUNET_MESH_tunnel_destroy on the tunnel.
+ *
+ * @param cls closure (set from GNUNET_MESH_connect)
+ * @param tunnel connection to the other end (henceforth invalid)
+ * @param tunnel_ctx place where local state associated
+ *                   with the tunnel is stored
+ */
+typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls,
+                                             const struct GNUNET_MESH_Tunnel *
+                                             tunnel, void *tunnel_ctx);
+
+
+/**
+ * Connect to the mesh service.
+ *
+ * @param cfg Configuration to use.
+ * @param cls Closure for the various callbacks that follow (including 
+ *            handlers in the handlers array).
+ * @param new_tunnel Function called when an *inbound* tunnel is created.
+ *                   Can be NULL if no inbound tunnels are desired.
+ * @param cleaner Function called when a tunnel is destroyed by the remote 
peer.
+ *                It is NOT called if GNUNET_MESH_tunnel_destroy is called on
+ *                the tunnel.
+ * @param handlers Callbacks for messages we care about, NULL-terminated. Each
+ *                 one must call GNUNET_MESH_receive_done on the tunnel to
+ *                 receive the next message.  Messages of a type that is not
+ *                 in the handlers array are ignored if received. 
+ * @param ports NULL or 0-terminated array of port numbers for incoming 
tunnels.
+ * 
+ * @return handle to the mesh service NULL on error
+ *         (in this case, init is never called)
+ */
+struct GNUNET_MESH_Handle *
+GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
+                     GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
+                     GNUNET_MESH_TunnelEndHandler cleaner,
+                     const struct GNUNET_MESH_MessageHandler *handlers,
+                     const uint32_t *ports);
+
+
+/**
+ * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
+ * disconnect callbacks will be called on any still connected peers, notifying
+ * about their disconnection. The registered inbound tunnel cleaner will be
+ * called should any inbound tunnels still exist.
+ *
+ * @param handle connection to mesh to disconnect
+ */
+void
+GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle);
+
+
+/**
+ * Create a new tunnel (we're initiator and will be allowed to add/remove peers
+ * and to broadcast).
+ *
+ * @param h mesh handle
+ * @param tunnel_ctx client's tunnel context to associate with the tunnel
+ * @param peer peer identity the tunnel should go to
+ * @param port Port number.
+ * @return handle to the tunnel
+ */
+struct GNUNET_MESH_Tunnel *
+GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, 
+                           void *tunnel_ctx,
+                           const struct GNUNET_PeerIdentity *peer,
+                           uint32_t port);
+
+
+/**
+ * Destroy an existing tunnel.
+ * 
+ * The existing end callback for the tunnel will be called immediately.
+ * Any pending outgoing messages will be sent but no incoming messages will be
+ * accepted and no data callbacks will be called.
+ *
+ * @param tunnel Tunnel handle, becomes invalid after this call.
+ */
+void
+GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel);
+
+
+/**
+ * Turn on/off the buffering status of the tunnel.
+ * 
+ * @param tunnel Tunnel affected.
+ * @param buffer GNUNET_YES to turn buffering on (default),
+ *               GNUNET_NO otherwise.
+ */
+void
+GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer);
+
+
+/**
+ * Handle for a transmission request.
+ */
+struct GNUNET_MESH_TransmitHandle;
+
+
+/**
+ * Ask the mesh to call "notify" once it is ready to transmit the
+ * given number of bytes to the specified tunnel.
+ * Only one call can be active at any time, to issue another request,
+ * wait for the callback or cancel the current request.
+ *
+ * @param tunnel tunnel to use for transmission
+ * @param cork is corking allowed for this transmission?
+ * @param maxdelay how long can the message wait?
+ * @param notify_size how many bytes of buffer space does notify want?
+ * @param notify function to call when buffer space is available;
+ *        will be called with NULL on timeout or if the overall queue
+ *        for this peer is larger than queue_size and this is currently
+ *        the message with the lowest priority
+ * @param notify_cls closure for notify
+ * @return non-NULL if the notify callback was queued,
+ *         NULL if we can not even queue the request (insufficient
+ *         memory); if NULL is returned, "notify" will NOT be called.
+ */
+struct GNUNET_MESH_TransmitHandle *
+GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
+                                   struct GNUNET_TIME_Relative maxdelay,
+                                   size_t notify_size,
+                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
+                                   void *notify_cls);
+
+
+/**
+ * Cancel the specified transmission-ready notification.
+ *
+ * @param th handle that was returned by "notify_transmit_ready".
+ */
+void
+GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle
+                                          *th);
+
+
+/**
+ * Indicate readiness to receive the next message on a tunnel.
+ * 
+ * Should only be called once per handler called.
+ *
+ * @param tunnel Tunnel that will be allowed to call another handler.
+ */
+void
+GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel);
+
+
+
+/******************************************************************************/
+/********************       MONITORING /DEBUG API     
*************************/
+/******************************************************************************/
+/* The following calls are not useful for normal MESH operation, but for      
*/
+/* debug and monitoring of the mesh state. They can be safely ignored.        
*/
+/* The API can change at any point without notice.                            
*/
+/* Please contact the developer if you consider any of this calls useful for  
*/
+/* normal mesh applications.                                                  
*/
+/******************************************************************************/
+
+/**
+ * Method called to retrieve information about each tunnel the mesh peer
+ * is aware of.
+ *
+ * @param cls Closure.
+ * @param tunnel_number Tunnel number.
+ * @param origin that started the tunnel (owner).
+ * @param target other endpoint of the tunnel
+ */
+typedef void (*GNUNET_MESH_TunnelsCB) (void *cls,
+                                       uint32_t tunnel_number,
+                                       const struct GNUNET_PeerIdentity 
*origin,
+                                       const struct GNUNET_PeerIdentity 
*target);
+
+
+/**
+ * Method called to retrieve information about a specific tunnel the mesh peer
+ * is aware of, including all transit nodes.
+ *
+ * @param cls Closure.
+ * @param peer Peer in the tunnel's tree.
+ * @param parent Parent of the current peer. All 0 when peer is root.
+ */
+typedef void (*GNUNET_MESH_TunnelCB) (void *cls,
+                                      const struct GNUNET_PeerIdentity *peer,
+                                      const struct GNUNET_PeerIdentity 
*parent);
+
+
+/**
+ * Request information about the running mesh peer.
+ * The callback will be called for every tunnel known to the service,
+ * listing all active peers that belong to the tunnel.
+ *
+ * If called again on the same handle, it will overwrite the previous
+ * callback and cls. To retrieve the cls, monitor_cancel must be
+ * called first.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the mesh peer.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ */
+void
+GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
+                         GNUNET_MESH_TunnelsCB callback,
+                         void *callback_cls);
+
+
+/**
+ * Request information about a specific tunnel of the running mesh peer.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the mesh peer.
+ * @param initiator ID of the owner of the tunnel.
+ * @param tunnel_number Tunnel number.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ */
+void
+GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
+                         struct GNUNET_PeerIdentity *initiator,
+                         uint32_t tunnel_number,
+                         GNUNET_MESH_TunnelCB callback,
+                         void *callback_cls);
+
+
+/**
+ * Cancel a monitor request. The monitor callback will not be called.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Mesh handle.
+ *
+ * @return Closure given to GNUNET_MESH_monitor, if any.
+ */
+void *
+GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h);
+
+
+/**
+ * Create a message queue for a mesh tunnel.
+ * The message queue can only be used to transmit messages,
+ * not to receive them.
+ *
+ * @param tunnel the tunnel to create the message qeue for
+ * @return a message queue to messages over the tunnel
+ */
+struct GNUNET_MQ_Handle *
+GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_MESH_SERVICE_H */
+#endif
+/* end of gnunet_mesh_service.h */

Modified: gnunet/src/include/gnunet_stream_lib.h
===================================================================
--- gnunet/src/include/gnunet_stream_lib.h      2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/include/gnunet_stream_lib.h      2013-06-28 14:34:55 UTC (rev 
27681)
@@ -151,7 +151,7 @@
 struct GNUNET_STREAM_Socket *
 GNUNET_STREAM_open (const struct GNUNET_CONFIGURATION_Handle *cfg,
                     const struct GNUNET_PeerIdentity *target,
-                    GNUNET_MESH_ApplicationType app_port,
+                    uint32_t app_port,
                     GNUNET_STREAM_OpenCallback open_cb,
                    void *open_cb_cls,
                    ...);
@@ -252,7 +252,7 @@
  */
 struct GNUNET_STREAM_ListenSocket *
 GNUNET_STREAM_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                      GNUNET_MESH_ApplicationType app_port,
+                      uint32_t app_port,
                       GNUNET_STREAM_ListenCallback listen_cb,
                       void *listen_cb_cls,
                       ...);

Modified: gnunet/src/mesh/Makefile.am
===================================================================
--- gnunet/src/mesh/Makefile.am 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/Makefile.am 2013-06-28 14:34:55 UTC (rev 27681)
@@ -20,21 +20,6 @@
 
 AM_CLFAGS = -g
 
-if HAVE_EXPERIMENTAL
-  noinst_LIB_EXP = libgnunetmesh2test.a
-  EXP_LIB = libgnunetmesh2.la
-  EXP_LIBEXEC = gnunet-service-mesh-new
-  EXP_TESTS = \
-    test_mesh2_local \
-    test_mesh2_small_forward \
-    test_mesh2_small_signal  \
-    test_mesh2_small_speed  \
-    test_mesh2_small_speed_ack  \
-    test_mesh2_small_speed_nobuf  \
-    test_mesh2_small_speed_backwards  \
-    test_mesh2_small_speed_nobuf_backwards
-endif
-
 libexec_PROGRAMS = \
  gnunet-service-mesh $(EXP_LIBEXEC)
 
@@ -58,6 +43,7 @@
  $(top_builddir)/src/block/libgnunetblock.la \
  $(top_builddir)/src/util/libgnunetutil.la
 
+
 libgnunetmesh_la_SOURCES = \
   mesh_api.c mesh_common.c
 libgnunetmesh_la_LIBADD = \
@@ -66,42 +52,8 @@
   $(LTLIBINTL)
 libgnunetmesh_la_LDFLAGS = \
   $(GN_LIB_LDFLAGS) $(WINFLAGS) \
-  -version-info 2:1:1
+  -version-info 3:0:0
 
-libgnunetmesh2_la_SOURCES = \
-  mesh2_api.c mesh_common.c
-libgnunetmesh2_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(XLIB) \
-  $(LTLIBINTL)
-libgnunetmesh2_la_LDFLAGS = \
-  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
-  -version-info 2:2:1
-
-
-gnunet_service_mesh_SOURCES = \
- gnunet-service-mesh.c \
- mesh_tunnel_tree.c mesh_tunnel_tree.h \
- mesh_common.c
-gnunet_service_mesh_CFLAGS = $(AM_CFLAGS)
-gnunet_service_mesh_LDADD = \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/regex/libgnunetregex.la \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/core/libgnunetcore.la \
-  $(top_builddir)/src/dht/libgnunetdht.la \
-  $(top_builddir)/src/block/libgnunetblock.la 
-gnunet_service_mesh_DEPENDENCIES = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/core/libgnunetcore.la \
-  $(top_builddir)/src/dht/libgnunetdht.la \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/block/libgnunetblock.la \
-  $(top_builddir)/src/regex/libgnunetregex.la
-if LINUX
-gnunet_service_mesh_LDFLAGS = -lrt
-endif
-
 gnunet_mesh_SOURCES = \
   gnunet-mesh.c
 gnunet_mesh_LDADD = \
@@ -110,25 +62,25 @@
 gnunet_mesh_DEPENDENCIES = \
   libgnunetmesh.la
 
-gnunet_service_mesh_new_SOURCES = \
- gnunet-service-mesh-new.c \
+gnunet_service_mesh_SOURCES = \
+ gnunet-service-mesh.c \
  mesh_path.c \
  mesh_common.c
-gnunet_service_mesh_new_CFLAGS = $(AM_CFLAGS)
-gnunet_service_mesh_new_LDADD = \
+gnunet_service_mesh_CFLAGS = $(AM_CFLAGS)
+gnunet_service_mesh_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/core/libgnunetcore.la \
   $(top_builddir)/src/dht/libgnunetdht.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/block/libgnunetblock.la
-gnunet_service_mesh_new_DEPENDENCIES = \
+gnunet_service_mesh_DEPENDENCIES = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/core/libgnunetcore.la \
   $(top_builddir)/src/dht/libgnunetdht.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/block/libgnunetblock.la
 if LINUX
-gnunet_service_mesh_new_LDFLAGS = -lrt
+  gnunet_service_mesh_LDFLAGS = -lrt
 endif
 
 if HAVE_TESTING
@@ -144,222 +96,75 @@
 libgnunetmeshtest_a_DEPENDENCIES = \
   libgnunetmesh.la
 
-libgnunetmesh2test_a_SOURCES = \
-  mesh2_test_lib.c mesh2_test_lib.h
-libgnunetmesh2test_a_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testbed/libgnunettestbed.la \
- $(top_builddir)/src/mesh/libgnunetmesh2.la
-libgnunetmesh2test_a_DEPENDENCIES = \
-  libgnunetmesh2.la
-
 if HAVE_TESTING
 check_PROGRAMS = \
- test_mesh_api \
- test_mesh_tree_api \
- test_mesh_local_1 \
- test_mesh_local_2 \
- test_mesh_local_traffic_fwd \
- test_mesh_local_traffic_bck \
- test_mesh_local_traffic_both \
- test_mesh_2dtorus \
- test_mesh_small_unicast \
- test_mesh_small_signal \
- test_mesh_small_speed \
- test_mesh_small_speed_nobuf \
- test_mesh_small_speed_backwards \
- test_mesh_small_speed_nobuf_backwards \
- test_mesh_small_speed_ack \
- $(EXP_TESTS)
+  test_mesh_local \
+  test_mesh_small_forward \
+  test_mesh_small_signal  \
+  test_mesh_small_speed  \
+  test_mesh_small_speed_ack  \
+  test_mesh_small_speed_nobuf  \
+  test_mesh_small_speed_backwards  \
+  test_mesh_small_speed_nobuf_backwards
 endif
 
-test_mesh_api_SOURCES = \
- test_mesh_api.c
-test_mesh_api_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la
-test_mesh_api_DEPENDENCIES = \
-  libgnunetmesh.la \
-   $(top_builddir)/src/util/libgnunetutil.la
-
-test_mesh_tree_api_SOURCES = \
- test_mesh_tree_api.c
-test_mesh_tree_api_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/dht/libgnunetdht.la
-test_mesh_tree_api_DEPENDENCIES = \
-  libgnunetmesh.la \
-  $(top_builddir)/src/dht/libgnunetdht.la
-
-test_mesh_local_1_SOURCES = \
- test_mesh_local_1.c
-test_mesh_local_1_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la
-test_mesh_local_1_DEPENDENCIES = \
-  libgnunetmesh.la
-
-test_mesh_local_2_SOURCES = \
- test_mesh_local_2.c
-test_mesh_local_2_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la
-test_mesh_local_2_DEPENDENCIES = \
-  libgnunetmesh.la
-
-test_mesh_local_traffic_fwd_SOURCES = \
- test_mesh_local_traffic.c
-test_mesh_local_traffic_fwd_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la
-test_mesh_local_traffic_fwd_DEPENDENCIES = \
-  libgnunetmesh.la
-
-test_mesh_local_traffic_bck_SOURCES = \
- test_mesh_local_traffic.c
-test_mesh_local_traffic_bck_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la
-test_mesh_local_traffic_bck_DEPENDENCIES = \
-  libgnunetmesh.la
-
-test_mesh_local_traffic_both_SOURCES = \
- test_mesh_local_traffic.c
-test_mesh_local_traffic_both_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la
-test_mesh_local_traffic_both_DEPENDENCIES = \
-  libgnunetmesh.la
-
-
 ld_mesh_test_lib = \
-  $(top_builddir)/src/mesh/libgnunetmeshtest.a \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testbed/libgnunettestbed.la \
   $(top_builddir)/src/mesh/libgnunetmesh.la \
-  $(top_builddir)/src/testbed/libgnunettestbed.la \
-  $(top_builddir)/src/util/libgnunetutil.la 
+  $(top_builddir)/src/mesh/libgnunetmeshtest.a
 
 dep_mesh_test_lib = \
-  libgnunetmeshtest.a \
-  libgnunetmesh.la
+  libgnunetmesh.la \
+  libgnunetmeshtest.a
 
-test_mesh_2dtorus_SOURCES = \
- test_mesh_2dtorus.c
-test_mesh_2dtorus_LDADD = $(ld_mesh_test_lib)
-test_mesh_2dtorus_DEPENDENCIES = $(dep_mesh_test_lib)
+test_mesh_local_SOURCES = \
+  test_mesh_local.c
+test_mesh_local_LDADD = $(ld_mesh_test_lib)
+test_mesh_local_DEPENDENCIES = $(dep_mesh_test_lib)
 
-test_mesh_small_unicast_SOURCES = \
- test_mesh_small.c
-test_mesh_small_unicast_LDADD = $(ld_mesh_test_lib)
-test_mesh_small_unicast_DEPENDENCIES = $(dep_mesh_test_lib)
+test_mesh_small_forward_SOURCES = \
+  test_mesh_small.c
+test_mesh_small_forward_LDADD = $(ld_mesh_test_lib)
+test_mesh_small_forward_DEPENDENCIES = $(dep_mesh_test_lib)
 
 test_mesh_small_signal_SOURCES = \
- test_mesh_small.c
+  test_mesh_small.c
 test_mesh_small_signal_LDADD = $(ld_mesh_test_lib)
 test_mesh_small_signal_DEPENDENCIES = $(dep_mesh_test_lib)
 
+test_mesh_small_speed_SOURCES = \
+  test_mesh_small.c
+test_mesh_small_speed_LDADD = $(ld_mesh_test_lib)
+test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib)
+
 test_mesh_small_speed_ack_SOURCES = \
- test_mesh_small.c
+  test_mesh_small.c
 test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib)
 test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib)
 
-test_mesh_small_speed_SOURCES = \
- test_mesh_small.c
-test_mesh_small_speed_LDADD = $(ld_mesh_test_lib)
-test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib)
-
 test_mesh_small_speed_nobuf_SOURCES = \
- test_mesh_small.c
+  test_mesh_small.c
 test_mesh_small_speed_nobuf_LDADD = $(ld_mesh_test_lib)
 test_mesh_small_speed_nobuf_DEPENDENCIES = $(dep_mesh_test_lib)
 
 test_mesh_small_speed_backwards_SOURCES = \
- test_mesh_small.c
+  test_mesh_small.c
 test_mesh_small_speed_backwards_LDADD = $(ld_mesh_test_lib)
 test_mesh_small_speed_backwards_DEPENDENCIES = $(dep_mesh_test_lib)
 
 test_mesh_small_speed_nobuf_backwards_SOURCES = \
- test_mesh_small.c
+  test_mesh_small.c
 test_mesh_small_speed_nobuf_backwards_LDADD = $(ld_mesh_test_lib)
 test_mesh_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh_test_lib)
 
 
-ld_mesh2_test_lib = \
-  $(top_builddir)/src/mesh/libgnunetmesh2test.a \
-  $(top_builddir)/src/mesh/libgnunetmesh2.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
-  $(top_builddir)/src/testbed/libgnunettestbed.la \
-  $(top_builddir)/src/util/libgnunetutil.la 
-
-dep_mesh2_test_lib = \
-  libgnunetmesh2test.a \
-  libgnunetmesh2.la
-
-test_mesh2_local_SOURCES = \
-  test_mesh2_local.c
-test_mesh2_local_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_local_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_forward_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_forward_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_forward_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_signal_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_signal_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_signal_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_speed_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_speed_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_speed_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_speed_ack_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_speed_ack_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_speed_ack_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_speed_nobuf_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_speed_nobuf_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_speed_nobuf_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_speed_backwards_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_speed_backwards_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_speed_backwards_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-test_mesh2_small_speed_nobuf_backwards_SOURCES = \
-  test_mesh2_small.c
-test_mesh2_small_speed_nobuf_backwards_LDADD = $(ld_mesh2_test_lib)
-test_mesh2_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh2_test_lib)
-
-
 if ENABLE_TEST_RUN
 TESTS = \
- $(EXP_TESTS) \
- test_mesh_api \
- test_mesh_tree_api \
- test_mesh_local_1 test_mesh_local_2 \
- test_mesh_local_traffic_fwd \
- test_mesh_local_traffic_bck \
- test_mesh_local_traffic_both \
- test_mesh_2dtorus \
- test_mesh_small_unicast \
- test_mesh_small_signal \
- test_mesh_small_speed \
- test_mesh_small_speed_nobuf \
- test_mesh_small_speed_backwards
+ $(check_PROGRAMS)
 endif
 
 EXTRA_DIST = \
   mesh.h mesh_protocol.h \
-  test_mesh.conf \
-  test_mesh_2dtorus.conf \
-  test_mesh_small.conf
+  test_mesh.conf

Modified: gnunet/src/mesh/gnunet-mesh.c
===================================================================
--- gnunet/src/mesh/gnunet-mesh.c       2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/gnunet-mesh.c       2013-06-28 14:34:55 UTC (rev 27681)
@@ -73,25 +73,19 @@
  * Method called to retrieve information about each tunnel the mesh peer
  * is aware of.
  *
- * @param cls Closure (unused).
- * @param initiator Peer that started the tunnel (owner).
+ * @param cls Closure.
  * @param tunnel_number Tunnel number.
- * @param peers Array of peer identities that participate in the tunnel.
- * @param npeers Number of peers in peers.
+ * @param origin that started the tunnel (owner).
+ * @param target other endpoint of the tunnel
  */
 static void
 tunnels_callback (void *cls,
-                 const struct GNUNET_PeerIdentity *initiator,
-                 unsigned int tunnel_number,
-                 const struct GNUNET_PeerIdentity *peers,
-                 unsigned int npeers)
+                  uint32_t tunnel_number,
+                  const struct GNUNET_PeerIdentity *origin,
+                  const struct GNUNET_PeerIdentity *target)
 {
-  unsigned int i;
-
-  fprintf (stdout, "Tunnel %s [%u]: %u peers\n",
-           GNUNET_i2s_full (initiator), tunnel_number, npeers);
-  for (i = 0; i < npeers; i++)
-    fprintf (stdout, " * %s\n", GNUNET_i2s_full (&peers[i]));
+  fprintf (stdout, "Tunnel %s [%u]\n",
+           GNUNET_i2s_full (origin), tunnel_number);
   fprintf (stdout, "\n");
 }
 
@@ -169,7 +163,7 @@
   static const struct GNUNET_MESH_MessageHandler handlers[] = {
     {NULL, 0, 0} /* FIXME add option to monitor msg types */
   };
-  GNUNET_MESH_ApplicationType apps = 0; /* FIXME add option to monitor apps */
+  /* FIXME add option to monitor apps */
 
   if (args[0] != NULL)
   {
@@ -178,10 +172,10 @@
   }
   mh = GNUNET_MESH_connect (cfg,
                             NULL, /* cls */
-                            NULL, /* nt */
+                            NULL, /* new tunnel */
                             NULL, /* cleaner */
                             handlers,
-                            &apps);
+                            NULL);
   if (NULL == mh)
     GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
   else

Deleted: gnunet/src/mesh/gnunet-service-mesh-new.c
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh-new.c   2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/mesh/gnunet-service-mesh-new.c   2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,5205 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001-2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/gnunet-service-mesh-new.c
- * @brief GNUnet MESH service
- * @author Bartlomiej Polot
- *
- * TODO:
- * - relay corking down to core
- * - set ttl relative to path length
- * - add signatures
- * - add encryption
- * - keep queues until receiving ACK
- * TODO END
- */
-
-#include "platform.h"
-#include "mesh2.h"
-#include "mesh2_protocol.h"
-#include "mesh_path.h"
-#include "block_mesh.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_statistics_service.h"
-
-#define MESH_BLOOM_SIZE         128
-
-#define MESH_DEBUG_DHT          GNUNET_NO
-#define MESH_DEBUG_CONNECTION   GNUNET_NO
-#define MESH_DEBUG_TIMING       __LINUX__ && GNUNET_NO
-
-#define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
-                                  GNUNET_TIME_UNIT_MINUTES,\
-                                  10)
-
-#if MESH_DEBUG_CONNECTION
-#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_CONN(...)
-#endif
-
-#if MESH_DEBUG_DHT
-#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_DHT(...)
-#endif
-
-#if MESH_DEBUG_TIMING
-#include <time.h>
-double __sum;
-uint64_t __count;
-struct timespec __mesh_start;
-struct timespec __mesh_end;
-#define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start))
-#define INTERVAL_END \
-do {\
-  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\
-  double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\
-  if (__diff < 0) __diff += 1000000000;\
-  __sum += __diff;\
-  __count++;\
-} while (0)
-#define INTERVAL_SHOW \
-if (0 < __count)\
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", 
__sum/__count)
-#else
-#define INTERVAL_START
-#define INTERVAL_END
-#define INTERVAL_SHOW
-#endif
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/** FWD declaration */
-struct MeshPeerInfo;
-struct MeshClient;
-
-
-/**
- * Struct containing info about a queued transmission to this peer
- */
-struct MeshPeerQueue
-{
-    /**
-      * DLL next
-      */
-  struct MeshPeerQueue *next;
-
-    /**
-      * DLL previous
-      */
-  struct MeshPeerQueue *prev;
-
-    /**
-     * Peer this transmission is directed to.
-     */
-  struct MeshPeerInfo *peer;
-
-    /**
-     * Tunnel this message belongs to.
-     */
-  struct MeshTunnel *tunnel;
-
-    /**
-     * Pointer to info stucture used as cls.
-     */
-  void *cls;
-
-    /**
-     * Type of message
-     */
-  uint16_t type;
-
-    /**
-     * Size of the message
-     */
-  size_t size;
-};
-
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct MeshPeerInfo
-{
-    /**
-     * ID of the peer
-     */
-  GNUNET_PEER_Id id;
-
-    /**
-     * Last time we heard from this peer
-     */
-  struct GNUNET_TIME_Absolute last_contact;
-
-    /**
-     * Number of attempts to reconnect so far
-     */
-  int n_reconnect_attempts;
-
-    /**
-     * Paths to reach the peer, ordered by ascending hop count
-     */
-  struct MeshPeerPath *path_head;
-
-    /**
-     * Paths to reach the peer, ordered by ascending hop count
-     */
-  struct MeshPeerPath *path_tail;
-
-    /**
-     * Handle to stop the DHT search for a path to this peer
-     */
-  struct GNUNET_DHT_GetHandle *dhtget;
-
-    /**
-     * Array of tunnels this peer is the target of.
-     * Most probably a small amount, therefore not a hashmap.
-     * When the path to the peer changes, notify these tunnels to let them
-     * re-adjust their path trees.
-     */
-  struct MeshTunnel **tunnels;
-
-    /**
-     * Number of tunnels this peers participates in
-     */
-  unsigned int ntunnels;
-
-   /**
-    * Transmission queue to core DLL head
-    */
-  struct MeshPeerQueue *queue_head;
-
-   /**
-    * Transmission queue to core DLL tail
-    */
-   struct MeshPeerQueue *queue_tail;
-
-   /**
-    * How many messages are in the queue to this peer.
-    */
-   unsigned int queue_n;
-
-   /**
-    * Handle for queued transmissions
-    */
-  struct GNUNET_CORE_TransmitHandle *core_transmit;
-};
-
-
-/**
- * Struct to encapsulate all the Flow Control information to a peer in the
- * context of a tunnel: Same peer in different tunnels will have independent
- * flow control structures, allowing to choke/free tunnels according to its
- * own criteria.
- */
-struct MeshFlowControl
-{
-  /**
-   * ID of the last packet sent towards the peer.
-   */
-  uint32_t last_pid_sent;
-
-  /**
-   * ID of the last packet received from the peer.
-   */
-  uint32_t last_pid_recv;
-
-  /**
-   * Last ACK sent to the peer (peer can't send more than this PID).
-   */
-  uint32_t last_ack_sent;
-
-  /**
-   * Last ACK sent towards the origin (for traffic towards leaf node).
-   */
-  uint32_t last_ack_recv;
-
-  /**
-   * How many payload messages are in the queue towards this peer.
-   */
-  uint32_t queue_n;
-
-  /**
-   * Task to poll the peer in case of a lost ACK causes stall.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier poll_task;
-
-  /**
-   * How frequently to poll for ACKs.
-   */
-  struct GNUNET_TIME_Relative poll_time;
-
-  /**
-   * On which tunnel to poll.
-   * Using an explicit poll_ctx would not help memory wise,
-   * since the allocated context would have to be stored in the
-   * fc struct in order to free it upon cancelling poll_task.
-   */
-  struct MeshTunnel *t;
-};
-
-
-/**
- * Globally unique tunnel identification (owner + number)
- * DO NOT USE OVER THE NETWORK
- */
-struct MESH_TunnelID
-{
-    /**
-     * Node that owns the tunnel
-     */
-  GNUNET_PEER_Id oid;
-
-    /**
-     * Tunnel number to differentiate all the tunnels owned by the node oid
-     * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
-     */
-  MESH_TunnelNumber tid;
-};
-
-
-/**
- * Struct containing all information regarding a tunnel
- * For an intermediate node the improtant info used will be:
- * - id        Tunnel unique identification
- * - paths[0]  To know where to send it next
- * - metainfo: ready, speeds, accounting
- */
-struct MeshTunnel
-{
-    /**
-     * Tunnel ID
-     */
-  struct MESH_TunnelID id;
-
-    /**
-     * Port of the tunnel.
-     */
-  uint32_t port;
-
-    /**
-     * State of the tunnel.
-     */
-  enum MeshTunnelState state;
-
-    /**
-     * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
-     */
-  MESH_TunnelNumber local_tid;
-
-    /**
-     * Local tunnel number for local destination clients (incoming number)
-     * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same
-     * number.
-     */
-  MESH_TunnelNumber local_tid_dest;
-
-    /**
-     * Is the tunnel bufferless (minimum latency)?
-     */
-  int nobuffer;
-
-    /**
-     * Force sending ACK? Flag to allow duplicate ACK on POLL.
-     */
-  int force_ack;
-
-    /**
-     * How many messages do we accept in the forward queue.
-     */
-  unsigned int queue_max;
-
-    /**
-     * Last time the tunnel was used
-     */
-  struct GNUNET_TIME_Absolute timestamp;
-
-    /**
-     * Destination of the tunnel.
-     */
-  GNUNET_PEER_Id dest;
-
-    /**
-     * Next hop in the tunnel. If 0, @c client must be set.
-     */
-  GNUNET_PEER_Id next_hop;
-
-    /**
-     * Previous hop in the tunnel. If 0, @c owner must be set.
-     */
-  GNUNET_PEER_Id prev_hop;
-
-    /**
-     * Flow control information about @c next_hop or @c client.
-     */
-  struct MeshFlowControl next_fc;
-
-  /**
-   * Flow control information about @c prev_hop or @c owner.
-   */
-  struct MeshFlowControl prev_fc;
-
-    /**
-     * Client owner of the tunnel, if any
-     */
-  struct MeshClient *owner;
-
-    /**
-     * Client destination of the tunnel, if any.
-     */
-  struct MeshClient *client;
-
-    /**
-     * Task to keep the used paths alive at the owner,
-     * time tunnel out on all the other peers.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier maintenance_task;
-
-    /**
-     * Path being used for the tunnel.
-     */
-  struct MeshPeerPath *path;
-
-    /**
-     * Flag to signal the destruction of the tunnel.
-     * If this is set GNUNET_YES the tunnel will be destroyed
-     * when the queue is empty.
-     */
-  int destroy;
-
-    /**
-     * Total messages pending for this tunnels, payload or not.
-     */
-  unsigned int pending_messages;
-};
-
-
-/**
- * Struct containing information about a client of the service
- * 
- * TODO: add a list of 'waiting' ports
- */
-struct MeshClient
-{
-    /**
-     * Linked list next
-     */
-  struct MeshClient *next;
-
-    /**
-     * Linked list prev
-     */
-  struct MeshClient *prev;
-
-    /**
-     * Tunnels that belong to this client, indexed by local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *own_tunnels;
-
-   /**
-     * Tunnels this client has accepted, indexed by incoming local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
-
-    /**
-     * Handle to communicate with the client
-     */
-  struct GNUNET_SERVER_Client *handle;
-
-    /**
-     * Ports that this client has declared interest in.
-     * Indexed by a GMC_hash32 (type), contains *Client.
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *ports;
-
-    /**
-     * Whether the client is active or shutting down (don't send confirmations
-     * to a client that is shutting down.
-     */
-  int shutting_down;
-
-    /**
-     * ID of the client, mainly for debug messages
-     */
-  unsigned int id;
-
-};
-
-
-/******************************************************************************/
-/************************      DEBUG FUNCTIONS     
****************************/
-/******************************************************************************/
-
-#if MESH_DEBUG
-/**
- * GNUNET_SCHEDULER_Task for printing a message after some operation is done
- * @param cls string to print
- * @param success  GNUNET_OK if the PUT was transmitted,
- *                GNUNET_NO on timeout,
- *                GNUNET_SYSERR on disconnect from service
- *                after the PUT message was transmitted
- *                (so we don't know if it was received or not)
- */
-
-#if 0
-static void
-mesh_debug (void *cls, int success)
-{
-  char *s = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
-}
-#endif
-
-/* FIXME */
-unsigned int debug_fwd_ack;
-unsigned int debug_bck_ack;
-
-#endif
-
-/******************************************************************************/
-/***********************      GLOBAL VARIABLES     
****************************/
-/******************************************************************************/
-
-/************************** Configuration parameters 
**************************/
-
-/**
- * How often to send tunnel keepalives. Tunnels timeout after 4 missed.
- */
-static struct GNUNET_TIME_Relative refresh_path_time;
-
-/**
- * How often to PUT own ID in the DHT.
- */
-static struct GNUNET_TIME_Relative id_announce_time;
-
-/**
- * Maximum time allowed to connect to a peer found by string.
- */
-static struct GNUNET_TIME_Relative connect_timeout;
-
-/**
- * Default TTL for payload packets.
- */
-static unsigned long long default_ttl;
-
-/**
- * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
- */
-static unsigned long long dht_replication_level;
-
-/**
- * How many tunnels are we willing to maintain.
- * Local tunnels are always allowed, even if there are more tunnels than max.
- */
-static unsigned long long max_tunnels;
-
-/**
- * How many messages *in total* are we willing to queue, divided by number of 
- * tunnels to get tunnel queue size.
- */
-static unsigned long long max_msgs_queue;
-
-/**
- * How many peers do we want to remember?
- */
-static unsigned long long max_peers;
-
-
-/*************************** Static global variables 
**************************/
-
-/**
- * Hostkey generation context
- */
-static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen;
-
-/**
- * DLL with all the clients, head.
- */
-static struct MeshClient *clients_head;
-
-/**
- * DLL with all the clients, tail.
- */
-static struct MeshClient *clients_tail;
-
-/**
- * Tunnels known, indexed by MESH_TunnelID (MeshTunnel).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
-
-/**
- * Number of tunnels known.
- */
-static unsigned long long n_tunnels;
-
-/**
- * Tunnels incoming, indexed by MESH_TunnelNumber
- * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
-
-/**
- * Peers known, indexed by PeerIdentity (MeshPeerInfo).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *peers;
-
-/*
- * Handle to communicate with transport
- */
-// static struct GNUNET_TRANSPORT_Handle *transport_handle;
-
-/**
- * Handle to communicate with core.
- */
-static struct GNUNET_CORE_Handle *core_handle;
-
-/**
- * Handle to use DHT.
- */
-static struct GNUNET_DHT_Handle *dht_handle;
-
-/**
- * Handle to server.
- */
-static struct GNUNET_SERVER_Handle *server_handle;
-
-/**
- * Handle to the statistics service.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Notification context, to send messages to local clients.
- */
-static struct GNUNET_SERVER_NotificationContext *nc;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-static GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-static struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Own private key.
- */
-static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
-
-/**
- * Own public key.
- */
-static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key;
-
-/**
- * Tunnel ID for the next created tunnel (global tunnel number).
- */
-static MESH_TunnelNumber next_tid;
-
-/**
- * Tunnel ID for the next incoming tunnel (local tunnel number).
- */
-static MESH_TunnelNumber next_local_tid;
-
-/**
- * All ports clients of this peer have opened.
- */
-static struct GNUNET_CONTAINER_MultiHashMap *ports;
-
-/**
- * Task to periodically announce itself in the network.
- */
-GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
-
-/**
- * Next ID to assign to a client.
- */
-unsigned int next_client_id;
-
-
-/******************************************************************************/
-/***********************         DECLARATIONS        
**************************/
-/******************************************************************************/
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param exp when will this value expire
- * @param key key of the result
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- */
-static void
-dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
-                    const struct GNUNET_HashCode * key,
-                    const struct GNUNET_PeerIdentity *get_path,
-                    unsigned int get_path_length,
-                    const struct GNUNET_PeerIdentity *put_path,
-                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
-                    size_t size, const void *data);
-
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer Full identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_get (const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer Short identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_get_short (const GNUNET_PEER_Id peer);
-
-
-/**
- * Build a PeerPath from the paths returned from the DHT, reversing the paths
- * to obtain a local peer -> destination path and interning the peer ids.
- *
- * @return Newly allocated and created path
- */
-static struct MeshPeerPath *
-path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
-                     unsigned int get_path_length,
-                     const struct GNUNET_PeerIdentity *put_path,
-                     unsigned int put_path_length);
-
-
-/**
- * Adds a path to the peer_infos of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-static void
-path_add_to_peers (struct MeshPeerPath *p, int confirmed);
-
-
-
-/**
- * Search for a tunnel by global ID using full PeerIdentities.
- *
- * @param oid owner of the tunnel.
- * @param tid global tunnel number.
- *
- * @return tunnel handler, NULL if doesn't exist.
- */
-static struct MeshTunnel *
-tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
-
-
-/**
- * Notify a tunnel that a connection has broken that affects at least
- * some of its peers.
- *
- * @param t Tunnel affected.
- * @param p1 Peer that got disconnected from p2.
- * @param p2 Peer that got disconnected from p1.
- *
- * @return Short ID of the peer disconnected (either p1 or p2).
- *         0 if the tunnel remained unaffected.
- */
-static GNUNET_PEER_Id
-tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
-                                 GNUNET_PEER_Id p2);
-
-
-/**
- * @brief Use the given path for the tunnel.
- * Update the next and prev hops (and RCs).
- * (Re)start the path refresh in case the tunnel is locally owned.
- * 
- * @param t Tunnel to update.
- * @param p Path to use.
- */
-static void
-tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p);
-
-/**
- * Tunnel is empty: destroy it.
- * 
- * Notifies all participants (peers, cleints) about the destruction.
- * 
- * @param t Tunnel to destroy. 
- */
-static void
-tunnel_destroy_empty (struct MeshTunnel *t);
-
-/**
- * @brief Queue and pass message to core when possible.
- * 
- * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status
- * and accounts for it. In case the queue is full, the message is dropped and
- * a break issued.
- * 
- * Otherwise, message is treated as internal and allowed to go regardless of 
- * queue status.
- *
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- *            build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @param dst Neighbor to send message to.
- * @param t Tunnel this message belongs to.
- */
-static void
-queue_add (void *cls, uint16_t type, size_t size,
-           struct MeshPeerInfo *dst, struct MeshTunnel *t);
-
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- */
-static void
-queue_destroy (struct MeshPeerQueue *queue, int clear_cls);
-
-
-/**
- * @brief Get the next transmittable message from the queue.
- *
- * This will be the head, except in the case of being a data packet
- * not allowed by the destination peer.
- *
- * @param peer Destination peer.
- *
- * @return The next viable MeshPeerQueue element to send to that peer.
- *         NULL when there are no transmittable messages.
- */
-struct MeshPeerQueue *
-queue_get_next (const struct MeshPeerInfo *peer);
-
-
-/**
- * Core callback to write a queued packet to core buffer
- *
- * @param cls Closure (peer info).
- * @param size Number of bytes available in buf.
- * @param buf Where the to write the message.
- *
- * @return number of bytes written to buf
- */
-static size_t
-queue_send (void *cls, size_t size, void *buf);
-
-
-/******************************************************************************/
-/************************    PERIODIC FUNCTIONS    
****************************/
-/******************************************************************************/
-
-/**
- * Periodically announce self id in the DHT
- *
- * @param cls closure
- * @param tc task context
- */
-static void
-announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PBlock block;
-
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-    return;
-  }
-  /* TODO
-   * - Set data expiration in function of X
-   * - Adapt X to churn
-   */
-  DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
-
-  block.id = my_full_id;
-  block.type = htonl (0);
-  GNUNET_DHT_put (dht_handle,   /* DHT handle */
-                  &my_full_id.hashPubKey,       /* Key to use */
-                  dht_replication_level,     /* Replication level */
-                  GNUNET_DHT_RO_RECORD_ROUTE | 
GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
-                  GNUNET_BLOCK_TYPE_MESH_PEER,       /* Block type */
-                  sizeof (block),  /* Size of the data */
-                  (const char *) &block, /* Data itself */
-                  GNUNET_TIME_UNIT_FOREVER_ABS,  /* Data expiration */
-                  GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
-                  NULL,         /* Continuation */
-                  NULL);        /* Continuation closure */
-  announce_id_task =
-      GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
-}
-
-
-/******************************************************************************/
-/******************      GENERAL HELPER FUNCTIONS      
************************/
-/******************************************************************************/
-
-
-/**
- * Check if client has registered with the service and has not disconnected
- *
- * @param client the client to check
- *
- * @return non-NULL if client exists in the global DLL
- */
-static struct MeshClient *
-client_get (struct GNUNET_SERVER_Client *client)
-{
-  struct MeshClient *c;
-
-  c = clients_head;
-  while (NULL != c)
-  {
-    if (c->handle == client)
-      return c;
-    c = c->next;
-  }
-  return NULL;
-}
-
-
-/**
- * Deletes a tunnel from a client (either owner or destination). To be used on
- * tunnel destroy.
- *
- * @param c Client whose tunnel to delete.
- * @param t Tunnel which should be deleted.
- */
-static void
-client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
-{
-  struct GNUNET_HashCode hash;
-
-  if (c == t->owner)
-  {
-    GMC_hash32 (t->local_tid, &hash);
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
-                                                         &hash,
-                                                         t));
-  }
-  else if (c == t->client)
-  {
-    GMC_hash32 (t->local_tid_dest, &hash);
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
-                                                         &hash,
-                                                         t));
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-}
-
-/**
- * Notify the appropriate client that a new incoming tunnel was created.
- *
- * @param t Tunnel that was created.
- */
-static void
-send_client_tunnel_create (struct MeshTunnel *t)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-
-  if (NULL == t->client)
-    return;
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
-  msg.tunnel_id = htonl (t->local_tid_dest);
-  msg.port = htonl (t->port);
-  GNUNET_PEER_resolve (t->id.oid, &msg.peer);
-  GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
-                                              &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Notify dest client that the incoming tunnel is no longer valid.
- *
- * @param c Client to notify..
- * @param t Tunnel that is destroyed.
- */
-static void
-send_client_tunnel_destroy (struct MeshClient *c, struct MeshTunnel *t)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (c != t->client && c != t->owner)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-  msg.tunnel_id = htonl (t->local_tid_dest);
-  msg.port = htonl (0);
-  memset(&msg.peer, 0, sizeof (msg.peer));
-  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                              &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Iterator over all the peers to remove the oldest not-used entry.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- *
- * FIXME implement
- */
-static int
-peer_info_timeout (void *cls,
-                   const struct GNUNET_HashCode *key,
-                   void *value)
-{
-  return GNUNET_YES;
-}
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer Full identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_get (const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeerInfo *peer_info;
-
-  peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
-  if (NULL == peer_info)
-  {
-    peer_info =
-        (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
-    if (GNUNET_CONTAINER_multihashmap_size (peers) > max_peers)
-    {
-      GNUNET_CONTAINER_multihashmap_iterate (peers,
-                                             &peer_info_timeout,
-                                             NULL);
-    }
-    GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-    peer_info->id = GNUNET_PEER_intern (peer);
-  }
-  peer_info->last_contact = GNUNET_TIME_absolute_get();
-
-  return peer_info;
-}
-
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer Short identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_get_short (const GNUNET_PEER_Id peer)
-{
-  struct GNUNET_PeerIdentity id;
-
-  GNUNET_PEER_resolve (peer, &id);
-  return peer_get (&id);
-}
-
-
-/**
- * Choose the best path towards a peer considering the tunnel properties.
- * 
- * @param peer The destination peer.
- * @param t The tunnel the path is for.
- *
- * @return Best current known path towards the peer, if any.
- */
-static struct MeshPeerPath *
-peer_get_best_path (const struct MeshPeerInfo *peer, const struct MeshTunnel 
*t)
-{
-  struct MeshPeerPath *best_p;
-  struct MeshPeerPath *p;
-  unsigned int best_cost;
-  unsigned int cost;
-
-  best_p = p = peer->path_head;
-  best_cost = cost = p->length;
-  while (NULL != p)
-  {
-    if ((cost = p->length) < best_cost)
-    {
-      best_cost = cost;
-      best_p = p;
-    }
-        p = p->next;
-  }
-  return best_p;
-}
-
-/**
-  * Core callback to write a pre-constructed data packet to core buffer
-  *
-  * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
-  * @param size Number of bytes available in buf.
-  * @param buf Where the to write the message.
-  *
-  * @return number of bytes written to buf
-  */
-static size_t
-send_core_data_raw (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *msg = cls;
-  size_t total_size;
-
-  GNUNET_assert (NULL != msg);
-  total_size = ntohs (msg->size);
-
-  if (total_size > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  memcpy (buf, msg, total_size);
-  GNUNET_free (cls);
-  return total_size;
-}
-
-
-/**
- * Sends an already built message to a peer, properly registrating
- * all used resources.
- *
- * @param message Message to send. Function makes a copy of it.
- * @param peer Short ID of the neighbor whom to send the message.
- * @param t Tunnel on which this message is transmitted.
- */
-static void
-send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                       GNUNET_PEER_Id peer,
-                       struct MeshTunnel *t)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerInfo *neighbor;
-  struct MeshPeerPath *p;
-  void *data;
-  size_t size;
-  uint16_t type;
-
-//   GNUNET_TRANSPORT_try_connect(); FIXME use?
-
-  if (0 == peer)
-    return;
-
-  size = ntohs (message->size);
-  data = GNUNET_malloc (size);
-  memcpy (data, message, size);
-  type = ntohs(message->type);
-  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type ||
-      GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
-  {
-    struct GNUNET_MESH_Data *u;
-
-    u = (struct GNUNET_MESH_Data *) data;
-    u->ttl = htonl (ntohl (u->ttl) - 1);
-  }
-  GNUNET_PEER_resolve (peer, &id);
-  neighbor = peer_get (&id);
-  for (p = neighbor->path_head; NULL != p; p = p->next)
-  {
-    if (2 >= p->length)
-    {
-      break;
-    }
-  }
-  if (NULL == p)
-  {
-#if MESH_DEBUG
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  %s IS NOT DIRECTLY CONNECTED\n",
-                GNUNET_i2s(&id));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  PATHS TO %s:\n",
-                GNUNET_i2s(&id));
-    for (p = neighbor->path_head; NULL != p; p = p->next)
-    {
-      struct GNUNET_PeerIdentity debug_id;
-      unsigned int i;
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "    path with %u hops through:\n",
-                  p->length);
-      for (i = 0; i < p->length; i++)
-      {
-        GNUNET_PEER_resolve(p->peers[i], &debug_id);
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "      hop %u: %s\n",
-                    i, GNUNET_i2s(&debug_id));
-      }
-    }
-#endif
-    GNUNET_break (0); // FIXME sometimes fails (testing disconnect?)
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    " no direct connection to %s\n",
-                    GNUNET_i2s (&id));
-    GNUNET_free (data);
-    return;
-  }
-  if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type)
-    type = 0;
-  queue_add (data,
-             type,
-             size,
-             neighbor,
-             t);
-}
-
-
-/**
- * Sends a CREATE PATH message for a path to a peer, properly registrating
- * all used resources.
- *
- * @param t Tunnel for which the path is created.
- */
-static void
-send_create_path (struct MeshTunnel *t)
-{
-  struct MeshPeerInfo *neighbor;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send create path\n");
-  neighbor = peer_get_short (t->next_hop);
-  queue_add (t,
-             GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE,
-             sizeof (struct GNUNET_MESH_CreateTunnel) +
-                (t->path->length * sizeof (struct GNUNET_PeerIdentity)),
-             neighbor,
-             t);
-  t->state = MESH_TUNNEL_WAITING;
-}
-
-
-/**
- * Sends a PATH ACK message in reponse to a received PATH_CREATE directed to 
us.
- *
- * @param t Tunnel which to confirm.
- */
-static void
-send_path_ack (struct MeshTunnel *t) 
-{
-  struct MeshPeerInfo *peer;
-
-  peer = peer_get_short (t->prev_hop);
-
-  queue_add (t,
-             GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
-             sizeof (struct GNUNET_MESH_PathACK),
-             peer,
-             t);
-}
-
-
-/**
- * Try to establish a new connection to this peer in the given tunnel.
- * If the peer doesn't have any path to it yet, try to get one.
- * If the peer already has some path, send a CREATE PATH towards it.
- *
- * @param peer PeerInfo of the peer.
- * @param t Tunnel for which to create the path, if possible.
- */
-static void
-peer_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
-{
-  struct MeshPeerPath *p;
-
-  if (NULL != peer->path_head)
-  {
-    p = peer_get_best_path (peer, t);
-    tunnel_use_path (t, p);
-    send_create_path (t);
-  }
-  else if (NULL == peer->dhtget)
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (peer->id, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
-    peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
-                                         GNUNET_BLOCK_TYPE_MESH_PEER, /* type 
*/
-                                         &id.hashPubKey,     /* key to search 
*/
-                                         dht_replication_level, /* replication 
level */
-                                         GNUNET_DHT_RO_RECORD_ROUTE |
-                                         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                                         NULL,       /* xquery */
-                                         0,     /* xquery bits */
-                                         &dht_get_id_handler, peer);
-    t->state = MESH_TUNNEL_SEARCHING;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "There is no path but the DHT GET is already started.\n");
-  }
-}
-
-
-/**
- * Destroy the peer_info and free any allocated resources linked to it
- *
- * @param pi The peer_info to destroy.
- *
- * @return GNUNET_OK on success
- */
-static int
-peer_info_destroy (struct MeshPeerInfo *pi)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerPath *p;
-  struct MeshPeerPath *nextp;
-  unsigned int i;
-
-  GNUNET_PEER_resolve (pi->id, &id);
-  GNUNET_PEER_change_rc (pi->id, -1);
-
-  if (GNUNET_YES !=
-      GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi))
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "removing peer %s, not in hashmap\n", GNUNET_i2s (&id));
-  }
-  if (NULL != pi->dhtget)
-  {
-    GNUNET_DHT_get_stop (pi->dhtget);
-  }
-  p = pi->path_head;
-  while (NULL != p)
-  {
-    nextp = p->next;
-    GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p);
-    path_destroy (p);
-    p = nextp;
-  }
-  for (i = 0; i < pi->ntunnels; i++)
-    tunnel_destroy_empty (pi->tunnels[i]);
-  GNUNET_array_grow (pi->tunnels, pi->ntunnels, 0);
-  GNUNET_free (pi);
-  return GNUNET_OK;
-}
-
-
-/**
- * Remove all paths that rely on a direct connection between p1 and p2
- * from the peer itself and notify all tunnels about it.
- *
- * @param peer PeerInfo of affected peer.
- * @param p1 GNUNET_PEER_Id of one peer.
- * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
- *           no longer is.
- *
- * TODO: optimize (see below)
- */
-static void
-peer_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
-                       GNUNET_PEER_Id p2)
-{
-  struct MeshPeerPath *p;
-  struct MeshPeerPath *next;
-  struct MeshPeerInfo *peer_d;
-  GNUNET_PEER_Id d;
-  unsigned int destroyed;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n");
-  destroyed = 0;
-  for (p = peer->path_head; NULL != p; p = next)
-  {
-    next = p->next;
-    for (i = 0; i < (p->length - 1); i++)
-    {
-      if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
-          (p->peers[i] == p2 && p->peers[i + 1] == p1))
-      {
-        GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
-        path_destroy (p);
-        destroyed++;
-        break;
-      }
-    }
-  }
-  if (0 == destroyed)
-    return;
-
-  for (i = 0; i < peer->ntunnels; i++)
-  {
-    d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
-    if (0 == d)
-      continue;
-
-    peer_d = peer_get_short (d);
-    next = peer_get_best_path (peer_d, peer->tunnels[i]);
-    tunnel_use_path (peer->tunnels[i], next);
-    peer_connect (peer_d, peer->tunnels[i]);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n");
-}
-
-
-/**
- * Add the path to the peer and update the path used to reach it in case this
- * is the shortest.
- *
- * @param peer_info Destination peer to add the path to.
- * @param path New path to add. Last peer must be the peer in arg 1.
- *             Path will be either used of freed if already known.
- * @param trusted Do we trust that this path is real?
- */
-void
-peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
-                    int trusted)
-{
-  struct MeshPeerPath *aux;
-  unsigned int l;
-  unsigned int l2;
-
-  if ((NULL == peer_info) || (NULL == path))
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return;
-  }
-  if (path->peers[path->length - 1] != peer_info->id)
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return;
-  }
-  if (2 >= path->length && GNUNET_NO == trusted)
-  {
-    /* Only allow CORE to tell us about direct paths */
-    path_destroy (path);
-    return;
-  }
-  for (l = 1; l < path->length; l++)
-  {
-    if (path->peers[l] == myid)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
-      for (l2 = 0; l2 < path->length - l; l2++)
-      {
-        path->peers[l2] = path->peers[l + l2];
-      }
-      path->length -= l;
-      l = 1;
-      path->peers =
-          GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
-    }
-  }
-#if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (peer_info->id, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
-                path->length, GNUNET_i2s (&id));
-  }
-#endif
-  l = path_get_length (path);
-  if (0 == l)
-  {
-    path_destroy (path);
-    return;
-  }
-
-  GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
-  for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
-  {
-    l2 = path_get_length (aux);
-    if (l2 > l)
-    {
-      GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
-                                          peer_info->path_tail, aux, path);
-      return;
-    }
-    else
-    {
-      if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
-      {
-        path_destroy (path);
-        return;
-      }
-    }
-  }
-  GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
-                                    path);
-  return;
-}
-
-
-/**
- * Add the path to the origin peer and update the path used to reach it in case
- * this is the shortest.
- * The path is given in peer_info -> destination, therefore we turn the path
- * upside down first.
- *
- * @param peer_info Peer to add the path to, being the origin of the path.
- * @param path New path to add after being inversed.
- *             Path will be either used or freed.
- * @param trusted Do we trust that this path is real?
- */
-static void
-peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
-                              struct MeshPeerPath *path, int trusted)
-{
-  path_invert (path);
-  peer_info_add_path (peer_info, path, trusted);
-}
-
-
-/**
- * Add a tunnel to the list of tunnels a peer participates in.
- * Update the tunnel's destination.
- * 
- * @param p Peer to add to.
- * @param t Tunnel to add.
- */
-static void
-peer_info_add_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
-{
-  if (0 != t->dest)
-  {
-    GNUNET_break (t->dest == p->id);
-    return;
-  }
-  t->dest = p->id;
-  GNUNET_PEER_change_rc (t->dest, 1);
-  GNUNET_array_append (p->tunnels, p->ntunnels, t);
-}
-
-
-/**
- * Remove a tunnel from the list of tunnels a peer participates in.
- * Free the tunnel's destination.
- * 
- * @param p Peer to clean.
- * @param t Tunnel to remove.
- */
-static void
-peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
-{
-  unsigned int i;
-
-  if (t->dest == p->id)
-  {
-      GNUNET_PEER_change_rc (t->dest, -1);
-      t->dest = 0;
-  }
-  for (i = 0; i < p->ntunnels; i++)
-  {
-    if (p->tunnels[i] == t)
-    {
-      p->tunnels[i] = p->tunnels[p->ntunnels - 1];
-      GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1);
-      return;
-    }
-  }
-}
-
-
-/**
- * Function called if the connection to the peer has been stalled for a while,
- * possibly due to a missed ACK. Poll the peer about its ACK status.
- *
- * @param cls Closure (poll ctx).
- * @param tc TaskContext.
- */
-static void
-tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshFlowControl *fc = cls;
-  struct GNUNET_MESH_Poll msg;
-  struct MeshTunnel *t = fc->t;
-  GNUNET_PEER_Id peer;
-
-  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    return;
-  }
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
-  msg.header.size = htons (sizeof (msg));
-  msg.tid = htonl (t->id.tid);
-  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-
-  if (fc == &t->prev_fc)
-  {
-    peer = t->prev_hop;
-  }
-  else if (fc == &t->next_fc)
-  {
-    peer = t->next_hop;
-  }
-  else
-  {
-    GNUNET_break (0);
-    return;
-  }
-  send_prebuilt_message (&msg.header, peer, t);
-  fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
-  fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
-                                                &tunnel_poll, fc);
-}
-
-
-/**
- * Build a PeerPath from the paths returned from the DHT, reversing the paths
- * to obtain a local peer -> destination path and interning the peer ids.
- *
- * @return Newly allocated and created path
- */
-static struct MeshPeerPath *
-path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
-                     unsigned int get_path_length,
-                     const struct GNUNET_PeerIdentity *put_path,
-                     unsigned int put_path_length)
-{
-  struct MeshPeerPath *p;
-  GNUNET_PEER_Id id;
-  int i;
-
-  p = path_new (1);
-  p->peers[0] = myid;
-  GNUNET_PEER_change_rc (myid, 1);
-  i = get_path_length;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   GET has %d hops.\n", i);
-  for (i--; i >= 0; i--)
-  {
-    id = GNUNET_PEER_intern (&get_path[i]);
-    if (p->length > 0 && id == p->peers[p->length - 1])
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
-      GNUNET_PEER_change_rc (id, -1);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from GET: %s.\n",
-                  GNUNET_i2s (&get_path[i]));
-      p->length++;
-      p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * 
p->length);
-      p->peers[p->length - 1] = id;
-    }
-  }
-  i = put_path_length;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   PUT has %d hops.\n", i);
-  for (i--; i >= 0; i--)
-  {
-    id = GNUNET_PEER_intern (&put_path[i]);
-    if (id == myid)
-    {
-      /* PUT path went through us, so discard the path up until now and start
-       * from here to get a much shorter (and loop-free) path.
-       */
-      path_destroy (p);
-      p = path_new (0);
-    }
-    if (p->length > 0 && id == p->peers[p->length - 1])
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
-      GNUNET_PEER_change_rc (id, -1);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from PUT: %s.\n",
-                  GNUNET_i2s (&put_path[i]));
-      p->length++;
-      p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * 
p->length);
-      p->peers[p->length - 1] = id;
-    }
-  }
-#if MESH_DEBUG
-  if (get_path_length > 0)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of GET: %s)\n",
-                GNUNET_i2s (&get_path[0]));
-  if (put_path_length > 0)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of PUT: %s)\n",
-                GNUNET_i2s (&put_path[0]));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   In total: %d hops\n",
-              p->length);
-  for (i = 0; i < p->length; i++)
-  {
-    struct GNUNET_PeerIdentity peer_id;
-
-    GNUNET_PEER_resolve (p->peers[i], &peer_id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "       %u: %s\n", p->peers[i],
-                GNUNET_i2s (&peer_id));
-  }
-#endif
-  return p;
-}
-
-
-/**
- * Adds a path to the peer_infos of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-static void
-path_add_to_peers (struct MeshPeerPath *p, int confirmed)
-{
-  unsigned int i;
-
-  /* TODO: invert and add */
-  for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
-  for (i++; i < p->length; i++)
-  {
-    struct MeshPeerInfo *aux;
-    struct MeshPeerPath *copy;
-
-    aux = peer_get_short (p->peers[i]);
-    copy = path_duplicate (p);
-    copy->length = i + 1;
-    peer_info_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
-  }
-}
-
-
-/**
- * Send keepalive packets for a peer
- *
- * @param cls Closure (tunnel for which to send the keepalive).
- * @param tc Notification context.
- */
-static void
-path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Search for a tunnel among the incoming tunnels
- *
- * @param tid the local id of the tunnel
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get_incoming (MESH_TunnelNumber tid)
-{
-  struct GNUNET_HashCode hash;
-
-  GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
-  GMC_hash32 (tid, &hash);
-  return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
-}
-
-
-/**
- * Search for a tunnel among the tunnels for a client
- *
- * @param c the client whose tunnels to search in
- * @param tid the local id of the tunnel
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
-{
-  if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    return tunnel_get_incoming (tid);
-  }
-  else
-  {
-    struct GNUNET_HashCode hash;
-
-    GMC_hash32 (tid, &hash);
-    return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
-  }
-}
-
-
-/**
- * Search for a tunnel by global ID using PEER_ID
- *
- * @param pi owner of the tunnel
- * @param tid global tunnel number
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
-{
-  struct MESH_TunnelID id;
-  struct GNUNET_HashCode hash;
-
-  id.oid = pi;
-  id.tid = tid;
-
-  GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
-  return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
-}
-
-
-/**
- * Search for a tunnel by global ID using full PeerIdentities
- *
- * @param oid owner of the tunnel
- * @param tid global tunnel number
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
-{
-  return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
-}
-
-
-/**
- * Add a client to a tunnel, initializing all needed data structures.
- * 
- * @param t Tunnel to which add the client.
- * @param c Client which to add to the tunnel.
- */
-static void
-tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
-{
-  struct GNUNET_HashCode hash;
-
-  if (NULL != t->client)
-  {
-    GNUNET_break(0);
-    return;
-  }
-  GMC_hash32 (t->local_tid_dest, &hash);
-  if (GNUNET_OK !=
-      GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  t->client = c;
-}
-
-
-static void
-tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p)
-{
-  unsigned int own_pos;
-
-  for (own_pos = 0; own_pos < p->length; own_pos++)
-  {
-    if (p->peers[own_pos] == myid)
-      break;
-  }
-  if (own_pos > p->length - 1)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if (own_pos < p->length - 1)
-    t->next_hop = p->peers[own_pos + 1];
-  else
-    t->next_hop = p->peers[own_pos];
-  GNUNET_PEER_change_rc (t->next_hop, 1);
-  if (0 < own_pos)
-    t->prev_hop = p->peers[own_pos - 1];
-  else
-    t->prev_hop = p->peers[0];
-  GNUNET_PEER_change_rc (t->prev_hop, 1);
-
-  if (NULL != t->path)
-    path_destroy (t->path);
-  t->path = path_duplicate (p);
-  if (0 == own_pos)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
-      GNUNET_SCHEDULER_cancel (t->maintenance_task);
-    t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time,
-                                                        &path_refresh, t);
-  }
-}
-
-
-/**
- * Notifies a tunnel that a connection has broken that affects at least
- * some of its peers. Sends a notification towards the root of the tree.
- * In case the peer is the owner of the tree, notifies the client that owns
- * the tunnel and tries to reconnect.
- *
- * @param t Tunnel affected.
- * @param p1 Peer that got disconnected from p2.
- * @param p2 Peer that got disconnected from p1.
- *
- * @return Short ID of the peer disconnected (either p1 or p2).
- *         0 if the tunnel remained unaffected.
- */
-static GNUNET_PEER_Id
-tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
-                                 GNUNET_PEER_Id p2)
-{
-//   if (myid != p1 && myid != p2) FIXME
-//   {
-//     return;
-//   }
-// 
-//   if (tree_get_predecessor (t->tree) != 0)
-//   {
-//     /* We are the peer still connected, notify owner of the disconnection. 
*/
-//     struct GNUNET_MESH_PathBroken msg;
-//     struct GNUNET_PeerIdentity neighbor;
-// 
-//     msg.header.size = htons (sizeof (msg));
-//     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
-//     GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-//     msg.tid = htonl (t->id.tid);
-//     msg.peer1 = my_full_id;
-//     GNUNET_PEER_resolve (pid, &msg.peer2);
-//     GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
-//     send_prebuilt_message (&msg.header, &neighbor, t);
-//   }
-  return 0;
-}
-
-
-/**
- * Build a local ACK message and send it to a local client.
- * 
- * @param t Tunnel on which to send the ACK.
- * @param c Client to whom send the ACK.
- * @param ack Value of the ACK.
- */
-static void
-send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack)
-{
-  struct GNUNET_MESH_LocalAck msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest);
-  msg.ack = htonl (ack); 
-  GNUNET_SERVER_notification_context_unicast(nc,
-                                              c->handle,
-                                              &msg.header,
-                                              GNUNET_NO);
-}
-
-/**
- * Build an ACK message and queue it to send to the given peer.
- * 
- * @param t Tunnel on which to send the ACK.
- * @param peer Peer to whom send the ACK.
- * @param ack Value of the ACK.
- */
-static void
-send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer,  uint32_t ack)
-{
-  struct GNUNET_MESH_ACK msg;
-
-  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
-  msg.pid = htonl (ack);
-  msg.tid = htonl (t->id.tid);
-
-  send_prebuilt_message (&msg.header, peer, t);
-}
-
-
-/**
- * Send an ACK informing the predecessor about the available buffer space.
- * In case there is no predecessor, inform the owning client.
- * If buffering is off, send only on behalf of children or self if endpoint.
- * If buffering is on, send when sent to children and buffer space is free.
- * Note that although the name is fwd_ack, the FWD mean forward *traffic*,
- * the ACK itself goes "back" (towards root).
- * 
- * @param t Tunnel on which to send the ACK.
- * @param type Type of message that triggered the ACK transmission.
- */
-static void
-tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
-{
-  uint32_t ack;
-
-  /* Is it after unicast retransmission? */
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "ACK due to FWD DATA retransmission\n");
-      if (GNUNET_YES == t->nobuffer)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
-        return;
-      }
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      t->force_ack = GNUNET_YES;
-      break;
-    default:
-      GNUNET_break (0);
-  }
-
-  /* Check if we need to transmit the ACK */
-  if (t->queue_max > t->next_fc.queue_n * 4 &&
-      GMC_is_pid_bigger(t->prev_fc.last_ack_sent, t->prev_fc.last_pid_recv) &&
-      GNUNET_NO == t->force_ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  t->qmax: %u, t->qn: %u\n",
-                t->queue_max, t->next_fc.queue_n);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  t->pid: %u, t->ack: %u\n",
-                t->prev_fc.last_pid_recv, t->prev_fc.last_ack_sent);
-    return;
-  }
-
-  /* Ok, ACK might be necessary, what PID to ACK? */
-  ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n;
-  if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
-    return;
-  }
-
-  t->prev_fc.last_ack_sent = ack;
-  if (NULL != t->owner)
-    send_local_ack (t, t->owner, ack);
-  else if (0 != t->prev_hop)
-    send_ack (t, t->prev_hop, ack);
-  else
-    GNUNET_break (0);
-  debug_fwd_ack++;
-  t->force_ack = GNUNET_NO;
-}
-
-
-/**
- * Send an ACK informing the children node/client about the available
- * buffer space.
- * If buffering is off, send only on behalf of root (can be self).
- * If buffering is on, send when sent to predecessor and buffer space is free.
- * Note that although the name is bck_ack, the BCK mean backwards *traffic*,
- * the ACK itself goes "forward" (towards children/clients).
- * 
- * @param t Tunnel on which to send the ACK.
- * @param type Type of message that triggered the ACK transmission.
- */
-static void
-tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
-{
-  uint32_t ack;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending BCK ACK on tunnel %u [%u] due to %s\n",
-              t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type));
-  /* Is it after data to_origin retransmission? */
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      if (GNUNET_YES == t->nobuffer)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "    Not sending ACK, nobuffer + traffic\n");
-        return;
-      }
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      t->force_ack = GNUNET_YES;
-      break;
-    default:
-      GNUNET_break (0);
-  }
-
-  /* TODO: Check if we need to transmit the ACK (as in fwd) */
-
-  ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n;
-
-  if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "    Not sending ACK, not needed, last ack sent was %u\n",
-                t->next_fc.last_ack_sent);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "    Sending BCK ACK %u (last sent: %u)\n",
-              ack, t->next_fc.last_ack_sent);
-  t->next_fc.last_ack_sent = ack;
-
-  if (NULL != t->client)
-    send_local_ack (t, t->client, ack);
-  else if (0 != t->next_hop)
-    send_ack (t, t->next_hop, ack);
-  else
-    GNUNET_break (0);
-  t->force_ack = GNUNET_NO;
-}
-
-
-/**
- * Modify the unicast message TID from global to local and send to client.
- * 
- * @param t Tunnel on which to send the message.
- * @param msg Message to modify and send.
- */
-static void
-tunnel_send_client_ucast (struct MeshTunnel *t,
-                          const struct GNUNET_MESH_Data *msg)
-{
-  struct GNUNET_MESH_Data *copy;
-  uint16_t size = ntohs (msg->header.size);
-  char cbuf[size];
-
-  if (size < sizeof (struct GNUNET_MESH_Data) +
-             sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-  if (NULL == t->client)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  copy = (struct GNUNET_MESH_Data *) cbuf;
-  memcpy (copy, msg, size);
-  copy->tid = htonl (t->local_tid_dest);
-  GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
-                                              &copy->header, GNUNET_NO);
-}
-
-
-/**
- * Modify the to_origin  message TID from global to local and send to client.
- * 
- * @param t Tunnel on which to send the message.
- * @param msg Message to modify and send.
- */
-static void
-tunnel_send_client_to_orig (struct MeshTunnel *t,
-                            const struct GNUNET_MESH_Data *msg)
-{
-  struct GNUNET_MESH_Data *copy;
-  uint16_t size = ntohs (msg->header.size);
-  char cbuf[size];
-
-  if (size < sizeof (struct GNUNET_MESH_Data) +
-             sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-  if (NULL == t->owner)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  copy = (struct GNUNET_MESH_Data *) cbuf;
-  memcpy (cbuf, msg, size);
-  copy->tid = htonl (t->local_tid);
-  GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
-                                              &copy->header, GNUNET_NO);
-}
-
-
-/**
- * @brief Re-initiate traffic to this peer if necessary.
- *
- * Check if there is traffic queued towards this peer
- * and the core transmit handle is NULL (traffic was stalled).
- * If so, call core tmt rdy.
- *
- * @param peer_id Short ID of peer to which initiate traffic.
- */
-static void
-peer_unlock_queue(GNUNET_PEER_Id peer_id)
-{
-  struct MeshPeerInfo *peer;
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerQueue *q;
-  size_t size;
-
-  peer = peer_get_short (peer_id);
-  if (NULL != peer->core_transmit)
-    return;
-
-  q = queue_get_next (peer);
-  if (NULL == q)
-  {
-    /* Might br multicast traffic already sent to this particular peer but
-     * not to other children in this tunnel.
-     * This way t->queue_n would be > 0 but the queue of this particular peer
-     * would be empty.
-     */
-    return;
-  }
-  size = q->size;
-  GNUNET_PEER_resolve (peer->id, &id);
-  peer->core_transmit =
-        GNUNET_CORE_notify_transmit_ready(core_handle,
-                                          0,
-                                          0,
-                                          GNUNET_TIME_UNIT_FOREVER_REL,
-                                          &id,
-                                          size,
-                                          &queue_send,
-                                          peer);
-        return;
-}
-
-
-/**
- * Send a message to all peers and clients in this tunnel that the tunnel
- * is no longer valid. If some peer or client should not receive the message,
- * should be zero'ed out before calling this function.
- *
- * @param t The tunnel whose peers and clients to notify.
- */
-static void
-tunnel_send_destroy (struct MeshTunnel *t)
-{
-  struct GNUNET_MESH_TunnelDestroy msg;
-  struct GNUNET_PeerIdentity id;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);
-  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-  msg.tid = htonl (t->id.tid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  sending tunnel destroy for tunnel: %s [%X]\n",
-              GNUNET_i2s (&msg.oid), t->id.tid);
-
-  if (NULL == t->client && 0 != t->next_hop)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  child: %u\n", t->next_hop);
-    GNUNET_PEER_resolve (t->next_hop, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  sending forward to %s\n",
-                GNUNET_i2s (&id));
-    send_prebuilt_message (&msg.header, t->next_hop, t);
-  }
-  if (NULL == t->owner && 0 != t->prev_hop)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  parent: %u\n", t->prev_hop);
-    GNUNET_PEER_resolve (t->prev_hop, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  sending back to %s\n",
-                GNUNET_i2s (&id));
-    send_prebuilt_message (&msg.header, t->prev_hop, t);
-  }
-  if (NULL != t->owner)
-  {
-    send_client_tunnel_destroy (t->owner, t);
-  }
-  if (NULL != t->client)
-  {
-    send_client_tunnel_destroy (t->client, t);
-  }
-}
-
-
-/**
- * Cancel all transmissions towards a neighbor that belongs to a certain 
tunnel.
- *
- * @param t Tunnel which to cancel.
- * @param neighbor Short ID of the neighbor to whom cancel the transmissions.
- */
-static void
-peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t)
-{
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerQueue *pq;
-  struct MeshPeerQueue *next;
-
-  if (0 == neighbor)
-    return; /* Was local peer, 0'ed in tunnel_destroy_iterator */
-  peer_info = peer_get_short (neighbor);
-  for (pq = peer_info->queue_head; NULL != pq; pq = next)
-  {
-    next = pq->next;
-    if (pq->tunnel == t)
-    {
-      if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
-          GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type)
-      {
-        /* Should have been removed on destroy children */
-        GNUNET_break (0);
-      }
-      queue_destroy (pq, GNUNET_YES);
-    }
-  }
-  if (NULL == peer_info->queue_head && NULL != peer_info->core_transmit)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel(peer_info->core_transmit);
-    peer_info->core_transmit = NULL;
-  }
-}
-
-
-/**
- * Destroy the tunnel.
- * 
- * This function does not generate any warning traffic to clients or peers.
- * 
- * Tasks:
- * Remove the tunnel from peer_info's and clients' hashmaps.
- * Cancel messages belonging to this tunnel queued to neighbors.
- * Free any allocated resources linked to the tunnel.
- *
- * @param t the tunnel to destroy
- *
- * @return GNUNET_OK on success
- */
-static int
-tunnel_destroy (struct MeshTunnel *t)
-{
-  struct MeshClient *c;
-  struct GNUNET_HashCode hash;
-  int r;
-
-  if (NULL == t)
-    return GNUNET_OK;
-
-  r = GNUNET_OK;
-  c = t->owner;
-#if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (t->id.oid, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s [%x]\n",
-                GNUNET_i2s (&id), t->id.tid);
-    if (NULL != c)
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-  }
-#endif
-
-  GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
-  if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
-  {
-    GNUNET_break (0);
-    r = GNUNET_SYSERR;
-  }
-
-  if (NULL != c)
-  {
-    GMC_hash32 (t->local_tid, &hash);
-    if (GNUNET_YES !=
-        GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
-    {
-      GNUNET_break (0);
-      r = GNUNET_SYSERR;
-    }
-  }
-
-  if (NULL != t->client)
-  {
-    c = t->client;
-    GMC_hash32 (t->local_tid_dest, &hash);
-    if (GNUNET_YES !=
-          GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
-    {
-      GNUNET_break (0);
-      r = GNUNET_SYSERR;
-    }
-    if (GNUNET_YES != 
-      GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
-    {
-      GNUNET_break (0);
-      r = GNUNET_SYSERR;
-    }
-  }
-
-  if (0 != t->prev_hop)
-  {
-    peer_cancel_queues (t->prev_hop, t);
-    GNUNET_PEER_change_rc (t->prev_hop, -1);
-  }
-  if (0 != t->next_hop)
-  {
-    peer_cancel_queues (t->next_hop, t);
-    GNUNET_PEER_change_rc (t->next_hop, -1);
-  }
-  if (0 != t->dest) {
-      peer_info_remove_tunnel (peer_get_short (t->dest), t);
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
-    GNUNET_SCHEDULER_cancel (t->maintenance_task);
-
-  n_tunnels--;
-  GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
-  path_destroy (t->path);
-  GNUNET_free (t);
-  return r;
-}
-
-/**
- * Tunnel is empty: destroy it.
- * 
- * Notifies all participants (peers, cleints) about the destruction.
- * 
- * @param t Tunnel to destroy. 
- */
-static void
-tunnel_destroy_empty (struct MeshTunnel *t)
-{
-  #if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (t->id.oid, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "executing destruction of empty tunnel %s [%X]\n",
-                GNUNET_i2s (&id), t->id.tid);
-  }
-  #endif
-
-  if (GNUNET_NO == t->destroy)
-    tunnel_send_destroy (t);
-  if (0 == t->pending_messages)
-    tunnel_destroy (t);
-  else
-    t->destroy = GNUNET_YES;
-}
-
-/**
- * Initialize a Flow Control structure to the initial state.
- * 
- * @param fc Flow Control structure to initialize.
- */
-static void
-fc_init (struct MeshFlowControl *fc)
-{
-  fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
-  fc->last_pid_recv = (uint32_t) -1;
-  fc->last_ack_sent = (uint32_t) -1; /* No traffic allowed yet */
-  fc->last_ack_recv = (uint32_t) -1;
-  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-  fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
-  fc->queue_n = 0;
-}
-
-/**
- * Create a new tunnel
- * 
- * @param owner Who is the owner of the tunnel (short ID).
- * @param tid Tunnel Number of the tunnel.
- * @param client Clients that owns the tunnel, NULL for foreign tunnels.
- * @param local Tunnel Number for the tunnel, for the client point of view.
- * 
- * @return A new initialized tunnel. NULL on error.
- */
-static struct MeshTunnel *
-tunnel_new (GNUNET_PEER_Id owner,
-            MESH_TunnelNumber tid,
-            struct MeshClient *client,
-            MESH_TunnelNumber local)
-{
-  struct MeshTunnel *t;
-  struct GNUNET_HashCode hash;
-
-  if (n_tunnels >= max_tunnels && NULL == client)
-    return NULL;
-
-  t = GNUNET_malloc (sizeof (struct MeshTunnel));
-  t->id.oid = owner;
-  t->id.tid = tid;
-  t->queue_max = (max_msgs_queue / max_tunnels) + 1;
-  t->owner = client;
-  fc_init (&t->next_fc);
-  fc_init (&t->prev_fc);
-  t->local_tid = local;
-  n_tunnels++;
-  GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO);
-
-  GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
-  if (GNUNET_OK !=
-      GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
-  {
-    GNUNET_break (0);
-    tunnel_destroy (t);
-    if (NULL != client)
-    {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
-    }
-    return NULL;
-  }
-
-  if (NULL != client)
-  {
-    GMC_hash32 (t->local_tid, &hash);
-    if (GNUNET_OK !=
-        GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t,
-                                          
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
-    {
-      tunnel_destroy (t);
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
-      return NULL;
-    }
-  }
-
-  return t;
-}
-
-
-
-/**
- * Iterator for deleting each tunnel whose client endpoint disconnected.
- *
- * @param cls Closure (client that has disconnected).
- * @param key The hash of the local tunnel id (used to access the hashmap).
- * @param value The value stored at the key (tunnel to destroy).
- *
- * @return GNUNET_OK, keep iterating.
- */
-static int
-tunnel_destroy_iterator (void *cls,
-                         const struct GNUNET_HashCode * key,
-                         void *value)
-{
-  struct MeshTunnel *t = value;
-  struct MeshClient *c = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Tunnel %X / %X destroy, due to client %u shutdown.\n",
-              t->local_tid, t->local_tid_dest, c->id);
-  client_delete_tunnel (c, t);
-  if (c == t->client)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", 
c->id);
-    t->client = NULL;
-    if (0 != t->next_hop) { /* destroy could come before a path is used */
-        GNUNET_PEER_change_rc (t->next_hop, -1);
-        t->next_hop = 0;
-    }
-  }
-  else if (c == t->owner)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id);
-    t->owner = NULL;
-    if (0 != t->prev_hop) { /* destroy could come before a path is used */
-        GNUNET_PEER_change_rc (t->prev_hop, -1);
-        t->prev_hop = 0;
-    }
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-  tunnel_destroy_empty (t);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Timeout function, destroys tunnel if called
- *
- * @param cls Closure (tunnel to destroy).
- * @param tc TaskContext
- */
-static void
-tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshTunnel *t = cls;
-  struct GNUNET_PeerIdentity id;
-
-  t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  GNUNET_PEER_resolve(t->id.oid, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Tunnel %s [%X] timed out. Destroying.\n",
-              GNUNET_i2s(&id), t->id.tid);
-  if (NULL != t->client)
-    send_client_tunnel_destroy (t->client, t);
-  tunnel_destroy (t); /* Do not notify other */
-}
-
-
-/**
- * Resets the tunnel timeout. Starts it if no timeout was running.
- *
- * @param t Tunnel whose timeout to reset.
- *
- * TODO use heap to improve efficiency of scheduler.
- */
-static void
-tunnel_reset_timeout (struct MeshTunnel *t)
-{
-  if (NULL != t->owner || 0 != t->local_tid || 0 == t->prev_hop)
-    return;
-  if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
-    GNUNET_SCHEDULER_cancel (t->maintenance_task);
-  t->maintenance_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (refresh_path_time, 4), &tunnel_timeout, 
t);
-}
-
-
-/******************************************************************************/
-/****************      MESH NETWORK HANDLER HELPERS     
***********************/
-/******************************************************************************/
-
-/**
- * Function to send a create path packet to a peer.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-send_core_path_create (void *cls, size_t size, void *buf)
-{
-  struct MeshTunnel *t = cls;
-  struct GNUNET_MESH_CreateTunnel *msg;
-  struct GNUNET_PeerIdentity *peer_ptr;
-  struct MeshPeerPath *p = t->path;
-  size_t size_needed;
-  uint32_t opt;
-  int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n");
-  size_needed =
-      sizeof (struct GNUNET_MESH_CreateTunnel) +
-      p->length * sizeof (struct GNUNET_PeerIdentity);
-
-  if (size < size_needed || NULL == buf)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg = (struct GNUNET_MESH_CreateTunnel *) buf;
-  msg->header.size = htons (size_needed);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
-  msg->tid = ntohl (t->id.tid);
-
-  opt = 0;
-  if (GNUNET_YES == t->nobuffer)
-    opt |= MESH_TUNNEL_OPT_NOBUFFER;
-  msg->opt = htonl (opt);
-  msg->port = htonl (t->port);
-
-  peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
-  for (i = 0; i < p->length; i++)
-  {
-    GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "CREATE PATH (%u bytes long) sent!\n", size_needed);
-  return size_needed;
-}
-
-
-/**
- * Creates a path ack message in buf and frees all unused resources.
- *
- * @param cls closure (MeshTransmissionDescriptor)
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-send_core_path_ack (void *cls, size_t size, void *buf)
-{
-  struct MeshTunnel *t = cls;
-  struct GNUNET_MESH_PathACK *msg = buf;
-
-  GNUNET_assert (NULL != t);
-  if (sizeof (struct GNUNET_MESH_PathACK) > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  t->prev_fc.last_ack_sent = t->nobuffer ? 0 : t->queue_max - 1;
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
-  GNUNET_PEER_resolve (t->id.oid, &msg->oid);
-  msg->tid = htonl (t->id.tid);
-  msg->peer_id = my_full_id;
-  msg->ack = htonl (t->prev_fc.last_ack_sent);
-
-  /* TODO add signature */
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n");
-  return sizeof (struct GNUNET_MESH_PathACK);
-}
-
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- */
-static void
-queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
-{
-  struct MeshFlowControl *fc;
-
-  if (GNUNET_YES == clear_cls)
-  {
-    switch (queue->type)
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO, "   cancelling TUNNEL_DESTROY\n");
-        GNUNET_break (GNUNET_YES == queue->tunnel->destroy);
-        /* fall through */
-      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      case GNUNET_MESSAGE_TYPE_MESH_ACK:
-      case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "   prebuilt message\n");
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "   type %s\n",
-                    GNUNET_MESH_DEBUG_M2S (queue->type));
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type create path\n");
-        break;
-      default:
-        GNUNET_break (0);
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "   type %s unknown!\n",
-                    GNUNET_MESH_DEBUG_M2S (queue->type));
-    }
-    GNUNET_free_non_null (queue->cls);
-  }
-  GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head,
-                               queue->peer->queue_tail,
-                               queue);
-
-  /* Delete from appropriate fc in the tunnel */
-  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type ||
-      GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type )
-  {
-    if (queue->peer->id == queue->tunnel->prev_hop)
-      fc = &queue->tunnel->prev_fc;
-    else if (queue->peer->id == queue->tunnel->next_hop)
-      fc = &queue->tunnel->next_fc;
-    else
-    {
-      GNUNET_break (0);
-      return;
-    }
-    fc->queue_n--;
-  }
-  GNUNET_free (queue);
-}
-
-
-/**
- * @brief Get the next transmittable message from the queue.
- *
- * This will be the head, except in the case of being a data packet
- * not allowed by the destination peer.
- *
- * @param peer Destination peer.
- *
- * @return The next viable MeshPeerQueue element to send to that peer.
- *         NULL when there are no transmittable messages.
- */
-struct MeshPeerQueue *
-queue_get_next (const struct MeshPeerInfo *peer)
-{
-  struct MeshPeerQueue *q;
-
-  struct GNUNET_MESH_Data *dmsg;
-  struct MeshTunnel* t;
-  uint32_t pid;
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   selecting message\n");
-  for (q = peer->queue_head; NULL != q; q = q->next)
-  {
-    t = q->tunnel;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "*     %s\n",
-                GNUNET_MESH_DEBUG_M2S (q->type));
-    dmsg = (struct GNUNET_MESH_Data *) q->cls;
-    pid = ntohl (dmsg->pid);
-    switch (q->type)
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-        ack = t->next_fc.last_ack_recv;
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-        ack = t->prev_fc.last_ack_recv;
-        break;
-      default:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "*   OK!\n");
-        return q;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "*     ACK: %u, PID: %u\n",
-                ack, pid);
-    if (GNUNET_NO == GMC_is_pid_bigger (pid, ack))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*   OK!\n");
-      return q;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*     NEXT!\n");
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "*   nothing found\n");
-  return NULL;
-}
-
-
-static size_t
-queue_send (void *cls, size_t size, void *buf)
-{
-  struct MeshPeerInfo *peer = cls;
-  struct GNUNET_MessageHeader *msg;
-  struct MeshPeerQueue *queue;
-  struct MeshTunnel *t;
-  struct GNUNET_PeerIdentity dst_id;
-  struct MeshFlowControl *fc;
-  size_t data_size;
-  uint32_t pid;
-  uint16_t type;
-
-  peer->core_transmit = NULL;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send\n");
-  queue = queue_get_next (peer);
-
-  /* Queue has no internal mesh traffic nor sendable payload */
-  if (NULL == queue)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   not ready, return\n");
-    if (NULL == peer->queue_head)
-      GNUNET_break (0); /* Core tmt_rdy should've been canceled */
-    return 0;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   not empty\n");
-
-  GNUNET_PEER_resolve (peer->id, &dst_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "*   towards %s\n",
-              GNUNET_i2s (&dst_id));
-  /* Check if buffer size is enough for the message */
-  if (queue->size > size)
-  {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*   not enough room, reissue\n");
-      peer->core_transmit =
-          GNUNET_CORE_notify_transmit_ready (core_handle,
-                                             GNUNET_NO,
-                                             0,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &dst_id,
-                                             queue->size,
-                                             &queue_send,
-                                             peer);
-      return 0;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   size ok\n");
-
-  t = queue->tunnel;
-  GNUNET_assert (0 < t->pending_messages);
-  t->pending_messages--;
-  type = 0;
-
-  /* Fill buf */
-  switch (queue->type)
-  {
-    case 0:
-    case GNUNET_MESSAGE_TYPE_MESH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_POLL:
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN:
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY:
-    case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*   raw: %s\n",
-                  GNUNET_MESH_DEBUG_M2S (queue->type));
-      /* Fall through */
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      data_size = send_core_data_raw (queue->cls, size, buf);
-      msg = (struct GNUNET_MessageHeader *) buf;
-      type = ntohs (msg->type);
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   path create\n");
-      data_size = send_core_path_create (queue->cls, size, buf);
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   path ack\n");
-      data_size = send_core_path_ack (queue->cls, size, buf);
-      break;
-    default:
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "*   type unknown: %u\n",
-                  queue->type);
-      data_size = 0;
-  }
-
-  /* Free queue, but cls was freed by send_core_* */
-  queue_destroy (queue, GNUNET_NO);
-
-  /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
-  pid = ((struct GNUNET_MESH_Data *) buf)->pid;
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      t->next_fc.last_pid_sent = pid;
-      tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      t->prev_fc.last_pid_sent = pid;
-      tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
-      break;
-    default:
-      break;
-  }
-
-  if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*  destroying tunnel!\n");
-    tunnel_destroy (t);
-  }
-
-  /* If more data in queue, send next */
-  queue = queue_get_next (peer);
-  if (NULL != queue)
-  {
-      struct GNUNET_PeerIdentity id;
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   more data!\n");
-      GNUNET_PEER_resolve (peer->id, &id);
-      peer->core_transmit =
-          GNUNET_CORE_notify_transmit_ready(core_handle,
-                                            0,
-                                            0,
-                                            GNUNET_TIME_UNIT_FOREVER_REL,
-                                            &id,
-                                            queue->size,
-                                            &queue_send,
-                                            peer);
-  }
-  else if (NULL != peer->queue_head)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "*   %s stalled\n",
-                GNUNET_i2s (&my_full_id));
-    if (peer->id == t->next_hop)
-      fc = &t->next_fc;
-    else if (peer->id == t->prev_hop)
-      fc = &t->prev_fc;
-    else
-    {
-      GNUNET_break (0);
-      fc = NULL;
-    }
-    if (NULL != fc && GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
-    {
-      fc->t = t;
-      fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
-                                                    &tunnel_poll, fc);
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*  Return %d\n", data_size);
-  return data_size;
-}
-
-
-/**
- * @brief Queue and pass message to core when possible.
- * 
- * If type is payload (UNICAST, TO_ORIGIN) checks for queue status and
- * accounts for it. In case the queue is full, the message is dropped and
- * a break issued.
- * 
- * Otherwise, message is treated as internal and allowed to go regardless of 
- * queue status.
- *
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- *            build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @param dst Neighbor to send message to.
- * @param t Tunnel this message belongs to.
- */
-static void
-queue_add (void *cls, uint16_t type, size_t size,
-           struct MeshPeerInfo *dst, struct MeshTunnel *t)
-{
-  struct MeshPeerQueue *queue;
-  struct GNUNET_PeerIdentity id;
-  unsigned int *n;
-
-  n = NULL;
-  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type)
-  {
-    n = &t->next_fc.queue_n;
-  }
-  else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
-  {
-    n = &t->prev_fc.queue_n;
-  }
-  if (NULL != n)
-  {
-    if (*n >= t->queue_max)
-    {
-      GNUNET_break(0);
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "queue full: %u/%u\n",
-                  *n, t->queue_max);
-      GNUNET_STATISTICS_update(stats,
-                               "# messages dropped (buffer full)",
-                               1, GNUNET_NO);
-      return; /* Drop message */
-    }
-    (*n)++;
-  }
-  queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
-  queue->cls = cls;
-  queue->type = type;
-  queue->size = size;
-  queue->peer = dst;
-  queue->tunnel = t;
-  GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
-  if (NULL == dst->core_transmit)
-  {
-    GNUNET_PEER_resolve (dst->id, &id);
-    dst->core_transmit =
-        GNUNET_CORE_notify_transmit_ready (core_handle,
-                                           0,
-                                           0,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           &id,
-                                           size,
-                                           &queue_send,
-                                           dst);
-  }
-  t->pending_messages++;
-}
-
-
-/******************************************************************************/
-/********************      MESH NETWORK HANDLERS     
**************************/
-/******************************************************************************/
-
-
-/**
- * Core handler for path creation
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
-                         const struct GNUNET_MessageHeader *message)
-{
-  unsigned int own_pos;
-  uint16_t size;
-  uint16_t i;
-  MESH_TunnelNumber tid;
-  struct GNUNET_MESH_CreateTunnel *msg;
-  struct GNUNET_PeerIdentity *pi;
-  struct MeshPeerPath *path;
-  struct MeshPeerInfo *dest_peer_info;
-  struct MeshPeerInfo *orig_peer_info;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a path create msg [%s]\n",
-              GNUNET_i2s (&my_full_id));
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_MESH_CreateTunnel))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  size -= sizeof (struct GNUNET_MESH_CreateTunnel);
-  if (size % sizeof (struct GNUNET_PeerIdentity))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  size /= sizeof (struct GNUNET_PeerIdentity);
-  if (size < 1)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
-  msg = (struct GNUNET_MESH_CreateTunnel *) message;
-
-  tid = ntohl (msg->tid);
-  pi = (struct GNUNET_PeerIdentity *) &msg[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "    path is for tunnel %s[%X].\n", GNUNET_i2s (pi), tid);
-  t = tunnel_get (pi, tid);
-  if (NULL == t) /* might be a local tunnel */
-  {
-    uint32_t opt;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating tunnel\n");
-    t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0);
-    if (NULL == t)
-    {
-      GNUNET_break (0);
-      return GNUNET_OK;
-    }
-    t->port = ntohl (msg->port);
-    opt = ntohl (msg->opt);
-    if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER))
-    {
-      t->nobuffer = GNUNET_YES;
-      t->queue_max = 1;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  nobuffer:%d\n", t->nobuffer);
-
-    tunnel_reset_timeout (t);
-  }
-  t->state = MESH_TUNNEL_WAITING;
-  dest_peer_info =
-      GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
-  if (NULL == dest_peer_info)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Creating PeerInfo for destination.\n");
-    dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
-    dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
-    GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
-                                       dest_peer_info,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  }
-  orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
-  if (NULL == orig_peer_info)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Creating PeerInfo for origin.\n");
-    orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
-    orig_peer_info->id = GNUNET_PEER_intern (pi);
-    GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
-  path = path_new (size);
-  own_pos = 0;
-  for (i = 0; i < size; i++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
-                GNUNET_i2s (&pi[i]));
-    path->peers[i] = GNUNET_PEER_intern (&pi[i]);
-    if (path->peers[i] == myid)
-      own_pos = i;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
-  if (own_pos == 0 && path->peers[own_pos] != myid)
-  {
-    /* create path: self not found in path through self */
-    GNUNET_break_op (0);
-    path_destroy (path);
-    tunnel_destroy (t);
-    return GNUNET_OK;
-  }
-  path_add_to_peers (path, GNUNET_NO);
-  tunnel_use_path (t, path);
-
-  peer_info_add_tunnel (dest_peer_info, t);
-
-  if (own_pos == size - 1)
-  {
-    struct MeshClient *c;
-    struct GNUNET_HashCode hc;
-
-    /* Find target client */
-    GMC_hash32 (t->port, &hc);
-    c = GNUNET_CONTAINER_multihashmap_get (ports, &hc);
-    if (NULL == c)
-    {
-      /* TODO send reject */
-      return GNUNET_OK;
-    }
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
-    peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_YES);
-
-    /* Assign local tid */
-    while (NULL != tunnel_get_incoming (next_local_tid))
-      next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-    t->local_tid_dest = next_local_tid++;
-    next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-
-    tunnel_add_client (t, c);
-    send_client_tunnel_create (t);
-    send_path_ack (t);
-  }
-  else
-  {
-    struct MeshPeerPath *path2;
-
-    t->next_hop = path->peers[own_pos + 1];
-    GNUNET_PEER_change_rc(t->next_hop, 1);
-
-    /* It's for somebody else! Retransmit. */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
-    path2 = path_duplicate (path);
-    peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
-    peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
-    send_create_path (t);
-  }
-  return GNUNET_OK;
-}
-
-
-
-/**
- * Core handler for path ACKs
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PathACK *msg;
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerPath *p;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
-              GNUNET_i2s (&my_full_id));
-  msg = (struct GNUNET_MESH_PathACK *) message;
-  t = tunnel_get (&msg->oid, ntohl(msg->tid));
-  if (NULL == t)
-  {
-    /* TODO notify that we don't know the tunnel */
-    GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, 
GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  don't know the tunnel %s [%X]!\n",
-                GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %s [%X]\n",
-              GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-
-  peer_info = peer_get (&msg->peer_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by peer %s\n",
-              GNUNET_i2s (&msg->peer_id));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
-              GNUNET_i2s (peer));
-
-  /* Add path to peers? */
-  p = t->path;
-  if (NULL != p)
-  {
-    path_add_to_peers (p, GNUNET_YES);
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-  t->state = MESH_TUNNEL_READY;
-  t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0;
-  t->prev_fc.last_ack_sent = ntohl (msg->ack);
-
-  /* Message for us? */
-  if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct 
GNUNET_PeerIdentity)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
-    if (NULL == t->owner)
-    {
-      GNUNET_break_op (0);
-      return GNUNET_OK;
-    }
-    if (NULL != peer_info->dhtget)
-    {
-      GNUNET_DHT_get_stop (peer_info->dhtget);
-      peer_info->dhtget = NULL;
-    }
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
-    return GNUNET_OK;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  not for us, retransmitting...\n");
-  peer_info = peer_get (&msg->oid);
-  send_prebuilt_message (message, t->prev_hop, t);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for notifications of broken paths
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
-                         const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PathBroken *msg;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer));
-  msg = (struct GNUNET_MESH_PathBroken *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
-              GNUNET_i2s (&msg->peer1));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
-              GNUNET_i2s (&msg->peer2));
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  if (NULL == t)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1),
-                                   GNUNET_PEER_search (&msg->peer2));
-  return GNUNET_OK;
-
-}
-
-
-/**
- * Core handler for tunnel destruction
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelDestroy *msg;
-  struct MeshTunnel *t;
-
-  msg = (struct GNUNET_MESH_TunnelDestroy *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a TUNNEL DESTROY packet from %s\n",
-              GNUNET_i2s (peer));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  for tunnel %s [%u]\n",
-              GNUNET_i2s (&msg->oid), ntohl (msg->tid));
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  if (NULL == t)
-  {
-    /* Probably already got the message from another path,
-     * destroyed the tunnel and retransmitted to children.
-     * Safe to ignore.
-     */
-    GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
-                              1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n",
-                t->local_tid, t->local_tid_dest);
-  }
-  if (GNUNET_PEER_search (peer) == t->prev_hop)
-  {
-    // TODO check owner's signature
-    // TODO add owner's signatue to tunnel for retransmission
-    peer_cancel_queues (t->prev_hop, t);
-    GNUNET_PEER_change_rc (t->prev_hop, -1);
-    t->prev_hop = 0;
-  }
-  else if (GNUNET_PEER_search (peer) == t->next_hop)
-  {
-    // TODO check dest's signature
-    // TODO add dest's signatue to tunnel for retransmission
-    peer_cancel_queues (t->next_hop, t);
-    GNUNET_PEER_change_rc (t->next_hop, -1);
-    t->next_hop = 0;
-  }
-  else
-  {
-    GNUNET_break_op (0);
-    // TODO check both owner AND destination's signature to see which matches
-    // TODO restransmit in appropriate direction
-    return GNUNET_OK;
-  }
-  tunnel_destroy_empty (t);
-
-  // TODO: add timeout to destroy the tunnel anyway
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic going from the origin to a peer
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- * @param message message
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Data *msg;
-  struct MeshTunnel *t;
-  uint32_t pid;
-  uint32_t ttl;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a unicast packet from %s\n",
-              GNUNET_i2s (peer));
-  /* Check size */
-  size = ntohs (message->size);
-  if (size <
-      sizeof (struct GNUNET_MESH_Data) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-  msg = (struct GNUNET_MESH_Data *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
-              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
-  /* Check tunnel */
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  if (NULL == t)
-  {
-    /* TODO notify back: we don't know this tunnel */
-    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  pid = ntohl (msg->pid);
-  if (t->prev_fc.last_pid_recv == pid)
-  {
-    GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                " Already seen pid %u, DROPPING!\n", pid);
-    return GNUNET_OK;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " pid %u not seen yet, forwarding\n", pid);
-  }
-
-  if (GMC_is_pid_bigger (pid, t->prev_fc.last_ack_sent))
-  {
-    GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received PID %u, ACK %u\n",
-                pid, t->prev_fc.last_ack_sent);
-    tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_POLL);
-    return GNUNET_OK;
-  }
-  t->prev_fc.last_pid_recv = pid;
-
-  tunnel_reset_timeout (t);
-  if (t->dest == myid)
-  {
-    /* TODO signature verification */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  it's for us! sending to clients...\n");
-    GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO);
-    tunnel_send_client_ucast (t, msg);
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
-    return GNUNET_OK;
-  }
-  if (0 == t->next_hop)
-  {
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-  ttl = ntohl (msg->ttl);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
-  if (ttl == 0)
-  {
-    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  not for us, retransmitting...\n");
-
-  send_prebuilt_message (message, t->next_hop, t);
-  GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic toward the owner of a tunnel
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Data *msg;
-  struct MeshTunnel *t;
-  size_t size;
-  uint32_t pid;
-  uint32_t ttl;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n",
-              GNUNET_i2s (peer));
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_MESH_Data) +     /* Payload must be */
-      sizeof (struct GNUNET_MessageHeader))     /* at least a header */
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  msg = (struct GNUNET_MESH_Data *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
-              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  pid = ntohl (msg->pid);
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know this tunnel (whom)? */
-    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received to_origin with PID %u on unknown tunnel %s [%u]\n",
-                pid, GNUNET_i2s (&msg->oid), ntohl (msg->tid));
-    return GNUNET_OK;
-  }
-
-  if (t->next_fc.last_pid_recv == pid)
-  {
-    /* already seen this packet, drop */
-    GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, 
GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " Already seen pid %u, DROPPING!\n", pid);
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-
-  if (GMC_is_pid_bigger (pid, t->next_fc.last_ack_sent))
-  {
-    GNUNET_STATISTICS_update (stats, "# unsolicited to_orig", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received PID %u, ACK %u\n",
-                pid, t->next_fc.last_ack_sent);
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
-    return GNUNET_OK;
-  }
-  t->next_fc.last_pid_recv = pid;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " pid %u not seen yet, forwarding\n", pid);
-
-  if (myid == t->id.oid)
-  {
-    /* TODO signature verification */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  it's for us! sending to clients...\n");
-    GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO);
-    tunnel_send_client_to_orig (t, msg);
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  not for us, retransmitting...\n");
-
-  if (0 == t->prev_hop) /* No owner AND no prev hop */
-  {
-    if (GNUNET_YES == t->destroy)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "to orig received on a dying tunnel %s [%X]\n",
-                  GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-      return GNUNET_OK;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "unknown to origin at %s\n",
-                GNUNET_i2s (&my_full_id));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "from peer %s\n",
-                GNUNET_i2s (peer));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "on tunnel %s [%X]\n",
-                GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-    return GNUNET_OK;
-  }
-  ttl = ntohl (msg->ttl);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
-  if (ttl == 0)
-  {
-    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-  send_prebuilt_message (message, t->prev_hop, t);
-  GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic point-to-point acks.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                 const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ACK *msg;
-  struct MeshTunnel *t;
-  GNUNET_PEER_Id id;
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
-              GNUNET_i2s (peer));
-  msg = (struct GNUNET_MESH_ACK *) message;
-
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know this tunnel (whom)? */
-    GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  ack = ntohl (msg->pid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u\n", ack);
-
-  /* Is this a forward or backward ACK? */
-  id = GNUNET_PEER_search (peer);
-  if (t->next_hop == id)
-  {
-    debug_fwd_ack++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
-    if (GNUNET_SCHEDULER_NO_TASK != t->next_fc.poll_task &&
-        GMC_is_pid_bigger (ack, t->next_fc.last_ack_recv))
-    {
-      GNUNET_SCHEDULER_cancel (t->next_fc.poll_task);
-      t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
-      t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
-    }
-    t->next_fc.last_ack_recv = ack;
-    peer_unlock_queue (t->next_hop);
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-  }
-  else if (t->prev_hop == id)
-  {
-    debug_bck_ack++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
-    if (GNUNET_SCHEDULER_NO_TASK != t->prev_fc.poll_task &&
-        GMC_is_pid_bigger (ack, t->prev_fc.last_ack_recv))
-    {
-      GNUNET_SCHEDULER_cancel (t->prev_fc.poll_task);
-      t->prev_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
-      t->prev_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
-    }
-    t->prev_fc.last_ack_recv = ack;
-    peer_unlock_queue (t->prev_hop);
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-  }
-  else
-    GNUNET_break_op (0);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic point-to-point ack polls.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
-                  const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Poll *msg;
-  struct MeshTunnel *t;
-  GNUNET_PEER_Id id;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n",
-              GNUNET_i2s (peer));
-
-  msg = (struct GNUNET_MESH_Poll *) message;
-
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know this tunnel (whom)? */
-    GNUNET_STATISTICS_update (stats, "# poll on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Is this a forward or backward ACK? */
-  id = GNUNET_PEER_search(peer);
-  if (t->next_hop == id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  from FWD\n");
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
-  }
-  else if (t->prev_hop == id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  from BCK\n");
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
-  }
-  else
-    GNUNET_break (0);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh keepalives.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- *
- * TODO: Check who we got this from, to validate route.
- */
-static int
-handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelKeepAlive *msg;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
-              GNUNET_i2s (peer));
-
-  msg = (struct GNUNET_MESH_TunnelKeepAlive *) message;
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know that tunnel */
-    GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1,
-                              GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  tunnel_reset_timeout (t);
-
-  GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
-  send_prebuilt_message (message, t->next_hop, t);
-  return GNUNET_OK;
-  }
-
-
-
-/**
- * Functions to handle messages from core
- */
-static struct GNUNET_CORE_MessageHandler core_handlers[] = {
-  {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
-  {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
-   sizeof (struct GNUNET_MESH_PathBroken)},
-  {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY,
-   sizeof (struct GNUNET_MESH_TunnelDestroy)},
-  {&handle_mesh_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
-  {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE,
-    sizeof (struct GNUNET_MESH_TunnelKeepAlive)},
-  {&handle_mesh_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
-  {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
-    sizeof (struct GNUNET_MESH_ACK)},
-  {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
-    sizeof (struct GNUNET_MESH_Poll)},
-  {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
-   sizeof (struct GNUNET_MESH_PathACK)},
-  {NULL, 0, 0}
-};
-
-
-
-/******************************************************************************/
-/****************       MESH LOCAL HANDLER HELPERS      
***********************/
-/******************************************************************************/
-
-
-#if LATER
-/**
- * notify_client_connection_failure: notify a client that the connection to the
- * requested remote peer is not possible (for instance, no route found)
- * Function called when the socket is ready to queue more data. "buf" will be
- * NULL and "size" zero if the socket was closed for writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-notify_client_connection_failure (void *cls, size_t size, void *buf)
-{
-  int size_needed;
-  struct MeshPeerInfo *peer_info;
-  struct GNUNET_MESH_PeerControl *msg;
-  struct GNUNET_PeerIdentity id;
-
-  if (0 == size && NULL == buf)
-  {
-    // TODO retry? cancel?
-    return 0;
-  }
-
-  size_needed = sizeof (struct GNUNET_MESH_PeerControl);
-  peer_info = (struct MeshPeerInfo *) cls;
-  msg = (struct GNUNET_MESH_PeerControl *) buf;
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
-//     msg->tunnel_id = htonl(peer_info->t->tid);
-  GNUNET_PEER_resolve (peer_info->id, &id);
-  memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
-
-  return size_needed;
-}
-#endif
-
-
-/**
- * Send keepalive packets for a tunnel.
- *
- * @param cls Closure (tunnel for which to send the keepalive).
- * @param tc Notification context.
- * 
- * FIXME: add a refresh reset in case of normal unicast traffic is doing the 
job
- */
-static void
-path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshTunnel *t = cls;
-  struct GNUNET_MESH_TunnelKeepAlive *msg;
-  size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive);
-  char cbuf[size];
-
-  t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) ||
-      NULL == t->owner || 0 == t->local_tid)
-  {
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "sending keepalive for tunnel %d\n", t->id.tid);
-
-  msg = (struct GNUNET_MESH_TunnelKeepAlive *) cbuf;
-  msg->header.size = htons (size);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
-  msg->oid = my_full_id;
-  msg->tid = htonl (t->id.tid);
-  send_prebuilt_message (&msg->header, t->next_hop, t);
-
-  t->maintenance_task =
-      GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
-}
-
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param exp when will this value expire
- * @param key key of the result
- * @param get_path path of the get request
- * @param get_path_length lenght of get_path
- * @param put_path path of the put request
- * @param put_path_length length of the put_path
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- */
-static void
-dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
-                    const struct GNUNET_HashCode * key,
-                    const struct GNUNET_PeerIdentity *get_path,
-                    unsigned int get_path_length,
-                    const struct GNUNET_PeerIdentity *put_path,
-                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
-                    size_t size, const void *data)
-{
-  struct MeshPeerInfo *peer = cls;
-  struct MeshPeerPath *p;
-  struct GNUNET_PeerIdentity pi;
-  int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
-  GNUNET_PEER_resolve (peer->id, &pi);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for %s\n", GNUNET_i2s (&pi));
-
-  p = path_build_from_dht (get_path, get_path_length,
-                           put_path, put_path_length);
-  path_add_to_peers (p, GNUNET_NO);
-  path_destroy (p);
-  for (i = 0; i < peer->ntunnels; i++)
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (peer->tunnels[i]->id.oid, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... tunnel %s:%X (%X / %X)\n",
-                GNUNET_i2s (&id), peer->tunnels[i]->id.tid,
-                peer->tunnels[i]->local_tid, 
-                peer->tunnels[i]->local_tid_dest);
-    if (peer->tunnels[i]->state == MESH_TUNNEL_SEARCHING)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
-      peer_connect (peer, peer->tunnels[i]);
-    }
-  }
-
-  return;
-}
-
-
-/******************************************************************************/
-/*********************       MESH LOCAL HANDLES      
**************************/
-/******************************************************************************/
-
-
-/**
- * Handler for client disconnection
- *
- * @param cls closure
- * @param client identification of the client; NULL
- *        for the last call when the server is destroyed
- */
-static void
-handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  struct MeshClient *c;
-  struct MeshClient *next;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
-  if (client == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
-    return;
-  }
-
-  c = clients_head;
-  while (NULL != c)
-  {
-    if (c->handle != client)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "   ... searching %p (%u)\n",
-                  c->handle, c->id);
-      c = c->next;
-      continue;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u)\n",
-                c->id);
-    GNUNET_SERVER_client_drop (c->handle);
-    c->shutting_down = GNUNET_YES;
-    GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
-                                           &tunnel_destroy_iterator, c);
-    GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
-                                           &tunnel_destroy_iterator, c);
-    GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
-    GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
-
-    if (NULL != c->ports)
-      GNUNET_CONTAINER_multihashmap_destroy (c->ports);
-    next = c->next;
-    GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  CLIENT FREE at %p\n", c);
-    GNUNET_free (c);
-    GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
-    c = next;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
-  return;
-}
-
-
-/**
- * Handler for new clients
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message, which includes messages the client wants
- */
-static void
-handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
-                         const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ClientConnect *cc_msg;
-  struct MeshClient *c;
-  unsigned int size;
-  uint32_t *p;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
-
-  /* Check data sanity */
-  size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
-  cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
-  if (0 != (size % sizeof (uint32_t)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  size /= sizeof (uint32_t);
-
-  /* Create new client structure */
-  c = GNUNET_malloc (sizeof (struct MeshClient));
-  c->id = next_client_id++; /* overflow not important: just for debug */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  client id %u\n", c->id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  client has %u ports\n", size);
-  c->handle = client;
-  GNUNET_SERVER_client_keep (client);
-  if (size > 0)
-  {
-    uint32_t u32;
-    struct GNUNET_HashCode hc;
-
-    p = (uint32_t *) &cc_msg[1];
-    c->ports = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO);
-    for (i = 0; i < size; i++)
-    {
-      u32 = ntohl (p[i]);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    port: %u\n", u32);
-      GMC_hash32 (u32, &hc);
-
-      /* store in client's hashmap */
-      GNUNET_CONTAINER_multihashmap_put (c->ports, &hc, c,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-      /* store in global hashmap */
-      /* FIXME only allow one client to have the port open,
-       *       have a backup hashmap with waiting clients */
-      GNUNET_CONTAINER_multihashmap_put (ports, &hc, c,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    }
-  }
-
-  GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
-  c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  GNUNET_SERVER_notification_context_add (nc, client);
-  GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
-}
-
-
-/**
- * Handler for requests of new tunnels
- *
- * @param cls Closure.
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *t_msg;
-  struct MeshPeerInfo *peer_info;
-  struct MeshTunnel *t;
-  struct MeshClient *c;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel requested\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message size sanity check */
-  if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  towards %s\n",
-              GNUNET_i2s (&t_msg->peer));
-  /* Sanity check for tunnel numbering */
-  tid = ntohl (t_msg->tunnel_id);
-  if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  /* Sanity check for duplicate tunnel IDs */
-  if (NULL != tunnel_get_by_local_id (c, tid))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Create tunnel */
-  while (NULL != tunnel_get_by_pi (myid, next_tid))
-    next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-  t = tunnel_new (myid, next_tid, c, tid);
-  next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  t->port = ntohl (t_msg->port);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n",
-              GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid);
-
-  peer_info = peer_get (&t_msg->peer);
-  peer_info_add_tunnel (peer_info, t);
-  peer_connect (peer_info, t);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for requests of deleting tunnels
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a DESTROY TUNNEL from client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message sanity check */
-  if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-
-  /* Retrieve tunnel */
-  tid = ntohl (tunnel_msg->tunnel_id);
-  t = tunnel_get_by_local_id(c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Cleanup after the tunnel */
-  client_delete_tunnel (c, t);
-  if (c == t->client)
-  {
-    t->client = NULL;
-  }
-  else if (c == t->owner)
-  {
-    peer_info_remove_tunnel (peer_get_short (t->dest), t);
-    t->owner = NULL;
-  }
-
-  /* The tunnel will be destroyed when the last message is transmitted. */
-  tunnel_destroy_empty (t);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for requests of seeting tunnel's buffering policy.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_tunnel_buffer (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a BUFFER request from client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-
-  /* Retrieve tunnel */
-  tid = ntohl (tunnel_msg->tunnel_id);
-  t = tunnel_get_by_local_id(c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  switch (ntohs(message->type))
-  {
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER:
-          t->nobuffer = GNUNET_NO;
-          break;
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER:
-          t->nobuffer = GNUNET_YES;
-          break;
-      default:
-          GNUNET_break (0);
-  }
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for client traffic directed to one peer
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
-{
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  struct GNUNET_MESH_Data *data_msg;
-  MESH_TunnelNumber tid;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a unicast request from a client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  data_msg = (struct GNUNET_MESH_Data *) message;
-
-  /* Sanity check for message size */
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_MESH_Data) +
-      sizeof (struct GNUNET_MessageHeader) > size)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (data_msg->tid);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /*  Is it a local tunnel? Then, does client own the tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* PID should be as expected: client<->service communication */
-  if (ntohl (data_msg->pid) != t->prev_fc.last_pid_recv + 1)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Unicast PID, expected %u, got %u\n",
-              t->prev_fc.last_pid_recv + 1, ntohl (data_msg->pid));
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Ok, everything is correct, send the message
-   * (pretend we got it from a mesh peer)
-   */
-  {
-    /* Work around const limitation */
-    char buf[ntohs (message->size)] GNUNET_ALIGN;
-    struct GNUNET_MESH_Data *copy;
-
-    copy = (struct GNUNET_MESH_Data *) buf;
-    memcpy (buf, data_msg, size);
-    copy->oid = my_full_id;
-    copy->tid = htonl (t->id.tid);
-    copy->ttl = htonl (default_ttl);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  calling generic handler...\n");
-        handle_mesh_unicast (NULL, &my_full_id, &copy->header);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-/**
- * Handler for client traffic directed to the origin
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Data *data_msg;
-  struct MeshFlowControl *fc;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a ToOrigin request from a client!\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  data_msg = (struct GNUNET_MESH_Data *) message;
-
-  /* Sanity check for message size */
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_MESH_Data) +
-      sizeof (struct GNUNET_MessageHeader) > size)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (data_msg->tid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", tid);
-  if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /*  It should be sent by someone who has this as incoming tunnel. */
-  if (t->client != c)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* PID should be as expected */
-  fc = &t->next_fc;
-  if (ntohl (data_msg->pid) != fc->last_pid_recv + 1)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "To Origin PID, expected %u, got %u\n",
-                fc->last_pid_recv + 1,
-                ntohl (data_msg->pid));
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Ok, everything is correct, send the message
-   * (pretend we got it from a mesh peer)
-   */
-  {
-    char buf[ntohs (message->size)] GNUNET_ALIGN;
-    struct GNUNET_MESH_Data *copy;
-
-    /* Work around 'const' limitation */
-    memcpy (buf, data_msg, size);
-    copy = (struct GNUNET_MESH_Data *) buf;
-    GNUNET_PEER_resolve (t->id.oid, &copy->oid);
-    copy->tid = htonl (t->id.tid);
-    copy->ttl = htonl (default_ttl);
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  calling generic handler...\n");
-        handle_mesh_to_orig (NULL, &my_full_id, &copy->header);
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-/**
- * Handler for client's ACKs for payload traffic.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
-                  const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalAck *msg;
-  struct MeshTunnel *t;
-  struct MeshClient *c;
-  MESH_TunnelNumber tid;
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  msg = (struct GNUNET_MESH_LocalAck *) message;
-
-  /* Tunnel exists? */
-  tid = ntohl (msg->tunnel_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", tid);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  ack = ntohl (msg->ack);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ack %u\n", ack);
-
-  /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */
-  if (t->owner == c)
-  {
-    /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */
-    t->prev_fc.last_ack_recv = ack;
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  }
-  else
-  {
-    /* The client doesn't own the tunnel, this ACK is for FWD traffic. */
-    t->next_fc.last_ack_recv = ack;
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  }
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-
-/**
- * Iterator over all tunnels to send a monitoring client info about each 
tunnel.
- *
- * @param cls Closure (client handle).
- * @param key Key (hashed tunnel ID, unused).
- * @param value Tunnel info.
- *
- * @return GNUNET_YES, to keep iterating.
- */
-static int
-monitor_all_tunnels_iterator (void *cls,
-                              const struct GNUNET_HashCode * key,
-                              void *value)
-{
-  struct GNUNET_SERVER_Client *client = cls;
-  struct MeshTunnel *t = value;
-  struct GNUNET_MESH_LocalMonitor *msg;
-
-  msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
-  GNUNET_PEER_resolve(t->id.oid, &msg->owner);
-  msg->tunnel_id = htonl (t->id.tid);
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
-  GNUNET_PEER_resolve (t->dest, &msg->destination);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "*  sending info about tunnel %s [%u]\n",
-              GNUNET_i2s (&msg->owner), t->id.tid);
-
-  GNUNET_SERVER_notification_context_unicast (nc, client,
-                                              &msg->header, GNUNET_NO);
-  return GNUNET_YES;
-}
-
-
-/**
- * Handler for client's MONITOR request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct MeshClient *c;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Received get tunnels request from client %u\n",
-              c->id);
-  GNUNET_CONTAINER_multihashmap_iterate (tunnels,
-                                         monitor_all_tunnels_iterator,
-                                         client);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Get tunnels request from client %u completed\n",
-              c->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for client's MONITOR_TUNNEL request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_MESH_LocalMonitor *msg;
-  struct GNUNET_MESH_LocalMonitor *resp;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  msg = (struct GNUNET_MESH_LocalMonitor *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Received tunnel info request from client %u for tunnel 
%s[%X]\n",
-              c->id,
-              &msg->owner,
-              ntohl (msg->tunnel_id));
-  t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id));
-  if (NULL == t)
-  {
-    /* We don't know the tunnel FIXME */
-    struct GNUNET_MESH_LocalMonitor warn;
-
-    warn = *msg;
-    GNUNET_SERVER_notification_context_unicast (nc, client,
-                                                &warn.header,
-                                                GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  /* Initialize context */
-  resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
-  *resp = *msg;
-  GNUNET_PEER_resolve (t->dest, &resp->destination);
-  resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
-  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                              &resp->header, GNUNET_NO);
-  GNUNET_free (resp);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Monitor tunnel request from client %u completed\n",
-              c->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Functions to handle messages from clients
- */
-static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
-  {&handle_local_new_client, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
-  {&handle_local_tunnel_create, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_destroy, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_buffer, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_buffer, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_unicast, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
-  {&handle_local_to_origin, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
-  {&handle_local_ack, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
-   sizeof (struct GNUNET_MESH_LocalAck)},
-  {&handle_local_get_tunnels, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
-   sizeof (struct GNUNET_MessageHeader)},
-  {&handle_local_show_tunnel, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
-     sizeof (struct GNUNET_MESH_LocalMonitor)},
-  {NULL, NULL, 0, 0}
-};
-
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerPath *path;
-
-  DEBUG_CONN ("Peer connected\n");
-  DEBUG_CONN ("     %s\n", GNUNET_i2s (&my_full_id));
-  peer_info = peer_get (peer);
-  if (myid == peer_info->id)
-  {
-    DEBUG_CONN ("     (self)\n");
-    path = path_new (1);
-  }
-  else
-  {
-    DEBUG_CONN ("     %s\n", GNUNET_i2s (peer));
-    path = path_new (2);
-    path->peers[1] = peer_info->id;
-    GNUNET_PEER_change_rc (peer_info->id, 1);
-    GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
-  }
-  path->peers[0] = myid;
-  GNUNET_PEER_change_rc (myid, 1);
-  peer_info_add_path (peer_info, path, GNUNET_YES);
-  return;
-}
-
-
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeerInfo *pi;
-  struct MeshPeerQueue *q;
-  struct MeshPeerQueue *n;
-
-  DEBUG_CONN ("Peer disconnected\n");
-  pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
-  if (NULL == pi)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  q = pi->queue_head;
-  while (NULL != q)
-  {
-      n = q->next;
-      /* TODO try to reroute this traffic instead */
-      queue_destroy(q, GNUNET_YES);
-      q = n;
-  }
-  if (NULL != pi->core_transmit)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit);
-    pi->core_transmit = NULL;
-  }
-    peer_remove_path (pi, pi->id, myid);
-  if (myid == pi->id)
-  {
-    DEBUG_CONN ("     (self)\n");
-  }
-  GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
-  return;
-}
-
-
-/**
- * Install server (service) handlers and start listening to clients.
- */
-static void
-server_init (void)
-{
-  GNUNET_SERVER_add_handlers (server_handle, client_handlers);
-  GNUNET_SERVER_disconnect_notify (server_handle,
-                                   &handle_local_client_disconnect, NULL);
-  nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
-
-  clients_head = NULL;
-  clients_tail = NULL;
-  next_client_id = 0;
-  GNUNET_SERVER_resume (server_handle);
-}
-
-
-/**
- * To be called on core init/fail.
- *
- * @param cls Closure (config)
- * @param server handle to the server for this service
- * @param identity the public identity of this peer
- */
-static void
-core_init (void *cls, struct GNUNET_CORE_Handle *server,
-           const struct GNUNET_PeerIdentity *identity)
-{
-  const struct GNUNET_CONFIGURATION_Handle *c = cls;
-  static int i = 0;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
-  GNUNET_break (core_handle == server);
-  if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
-    NULL == server)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                " core id %s\n",
-                GNUNET_i2s (identity));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                " my id %s\n",
-                GNUNET_i2s (&my_full_id));
-    GNUNET_CORE_disconnect (core_handle);
-    core_handle = GNUNET_CORE_connect (c, /* Main configuration */
-                                       NULL,      /* Closure passed to MESH 
functions */
-                                       &core_init,        /* Call core_init 
once connected */
-                                       &core_connect,     /* Handle connects */
-                                       &core_disconnect,  /* remove peers on 
disconnects */
-                                       NULL,      /* Don't notify about all 
incoming messages */
-                                       GNUNET_NO, /* For header only in 
notification */
-                                       NULL,      /* Don't notify about all 
outbound messages */
-                                       GNUNET_NO, /* For header-only out 
notification */
-                                       core_handlers);    /* Register these 
handlers */
-    if (10 < i++)
-      GNUNET_abort();
-  }
-  server_init ();
-  return;
-}
-
-
-/******************************************************************************/
-/************************      MAIN FUNCTIONS      
****************************/
-/******************************************************************************/
-
-/**
- * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
- */
-static int
-shutdown_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct MeshTunnel *t = value;
-
-  tunnel_destroy (t);
-  return GNUNET_YES;
-}
-
-/**
- * Iterator over peer hash map entries to destroy the tunnel during shutdown.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
- */
-static int
-shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct MeshPeerInfo *p = value;
-  struct MeshPeerQueue *q;
-  struct MeshPeerQueue *n;
-
-  q = p->queue_head;
-  while (NULL != q)
-  {
-      n = q->next;
-      if (q->peer == p)
-      {
-        queue_destroy(q, GNUNET_YES);
-      }
-      q = n;
-  }
-  peer_info_destroy (p);
-  return GNUNET_YES;
-}
-
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- * @param tc unused
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
-
-  if (core_handle != NULL)
-  {
-    GNUNET_CORE_disconnect (core_handle);
-    core_handle = NULL;
-  }
-  if (NULL != keygen)
-  {
-    GNUNET_CRYPTO_ecc_key_create_stop (keygen);
-    keygen = NULL;
-  }
-  GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL);
-  GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL);
-  if (dht_handle != NULL)
-  {
-    GNUNET_DHT_disconnect (dht_handle);
-    dht_handle = NULL;
-  }
-  if (nc != NULL)
-  {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
-  {
-    GNUNET_SCHEDULER_cancel (announce_id_task);
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
-}
-
-
-/**
- * Callback for hostkey read/generation.
- *
- * @param cls Closure (Configuration handle).
- * @param pk The ECC private key.
- * @param emsg Error message, if any.
- */
-static void
-key_generation_cb (void *cls,
-                   struct GNUNET_CRYPTO_EccPrivateKey *pk,
-                   const char *emsg)
-{
-  const struct GNUNET_CONFIGURATION_Handle *c = cls;
-
-  keygen = NULL;
-  if (NULL == pk)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("Could not access hostkey: %s. Exiting.\n"),
-                emsg);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  my_private_key = pk;
-  GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key);
-  GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
-                      &my_full_id.hashPubKey);
-  myid = GNUNET_PEER_intern (&my_full_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Mesh for peer [%s] starting\n",
-              GNUNET_i2s(&my_full_id));
-
-  core_handle = GNUNET_CORE_connect (c, /* Main configuration */
-                                     NULL,      /* Closure passed to MESH 
functions */
-                                     &core_init,        /* Call core_init once 
connected */
-                                     &core_connect,     /* Handle connects */
-                                     &core_disconnect,  /* remove peers on 
disconnects */
-                                     NULL,      /* Don't notify about all 
incoming messages */
-                                     GNUNET_NO, /* For header only in 
notification */
-                                     NULL,      /* Don't notify about all 
outbound messages */
-                                     GNUNET_NO, /* For header-only out 
notification */
-                                     core_handlers);    /* Register these 
handlers */
-  if (core_handle == NULL)
-  {
-    GNUNET_break (0);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  next_tid = 0;
-  next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-
-  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
-}
-
-
-/**
- * Process mesh requests.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  char *keyfile;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
-  server_handle = server;
-  GNUNET_SERVER_suspend (server_handle);
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY",
-                                               &keyfile))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "peer/privatekey");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_PATH_TIME",
-                                           &refresh_path_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "refresh path time");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
-                                           &id_announce_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "id announce time");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
-                                           &connect_timeout))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "connect timeout");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
-                                             &max_msgs_queue))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "max msgs queue");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_TUNNELS",
-                                             &max_tunnels))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "max tunnels");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
-                                             &default_ttl))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _
-                ("%s service is lacking key configuration settings (%s). Using 
default (%u).\n"),
-                "mesh", "default ttl", 64);
-    default_ttl = 64;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
-                                             &max_peers))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("%s service is lacking key configuration settings (%s). 
Using default (%u).\n"),
-                "mesh", "max peers", 1000);
-    max_peers = 1000;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", 
"DHT_REPLICATION_LEVEL",
-                                             &dht_replication_level))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _
-                ("%s service is lacking key configuration settings (%s). Using 
default (%u).\n"),
-                "mesh", "dht replication level", 3);
-    dht_replication_level = 3;
-  }
-
-  tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  ports = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-
-  dht_handle = GNUNET_DHT_connect (c, 64);
-  if (NULL == dht_handle)
-  {
-    GNUNET_break (0);
-  }
-  stats = GNUNET_STATISTICS_create ("mesh", c);
-
-  /* Scheduled the task to clean up when shutdown is called */
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
-                                NULL);
-  keygen = GNUNET_CRYPTO_ecc_key_create_start (keyfile,
-                                               &key_generation_cb,
-                                               (void *) c);
-  GNUNET_free (keyfile);
-}
-
-
-/**
- * The main function for the mesh service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  int ret;
-  int r;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
-  r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
-                          NULL);
-  ret = (GNUNET_OK == r) ? 0 : 1;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");
-
-  INTERVAL_SHOW;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Mesh for peer [%s] FWD ACKs %u, BCK ACKs %u\n",
-              GNUNET_i2s(&my_full_id), debug_fwd_ack, debug_bck_ack);
-
-  return ret;
-}

Deleted: gnunet/src/mesh/gnunet-service-mesh.c
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh.c       2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/mesh/gnunet-service-mesh.c       2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,8417 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001-2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/gnunet-service-mesh.c
- * @brief GNUnet MESH service
- * @author Bartlomiej Polot
- *
- * STRUCTURE:
- * - DATA STRUCTURES
- * - GLOBAL VARIABLES
- * - GENERAL HELPERS
- * - PERIODIC FUNCTIONS
- * - MESH NETWORK HANDLER HELPERS
- * - MESH NETWORK HANDLES
- * - MESH LOCAL HANDLER HELPERS
- * - MESH LOCAL HANDLES
- * - MAIN FUNCTIONS (main & run)
- *
- * TODO:
- * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
- * - partial disconnect reporting -- same as error reporting?
- * - add ping message
- * - relay corking down to core
- * - set ttl relative to tree depth
- * - Add data ACK count in path ACK
- * - Make common GNUNET_MESH_Data header for unicast, to_orig, multicast
- * TODO END
- */
-
-#include "platform.h"
-#include "mesh.h"
-#include "mesh_protocol.h"
-#include "mesh_tunnel_tree.h"
-#include "block_mesh.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_regex_service.h"
-
-#define MESH_BLOOM_SIZE         128
-
-#define MESH_DEBUG_REGEX        GNUNET_YES
-#define MESH_DEBUG_DHT          GNUNET_NO
-#define MESH_DEBUG_CONNECTION   GNUNET_NO
-#define MESH_DEBUG_TIMING       __LINUX__ && GNUNET_NO
-
-#define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
-                                  GNUNET_TIME_UNIT_MINUTES,\
-                                  10)
-
-
-#if MESH_DEBUG_CONNECTION
-#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_CONN(...)
-#endif
-
-#if MESH_DEBUG_DHT
-#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_DHT(...)
-#endif
-
-#if MESH_DEBUG_REGEX
-#define DEBUG_REGEX(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_REGEX(...)
-#endif
-
-#if MESH_DEBUG_TIMING
-#include <time.h>
-double __sum;
-uint64_t __count;
-struct timespec __mesh_start;
-struct timespec __mesh_end;
-#define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start))
-#define INTERVAL_END \
-do {\
-  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\
-  double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\
-  if (__diff < 0) __diff += 1000000000;\
-  __sum += __diff;\
-  __count++;\
-} while (0)
-#define INTERVAL_SHOW \
-if (0 < __count)\
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", 
__sum/__count)
-#else
-#define INTERVAL_START
-#define INTERVAL_END
-#define INTERVAL_SHOW
-#endif
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/** FWD declaration */
-struct MeshPeerInfo;
-struct MeshClient;
-
-
-/**
- * Struct representing a piece of data being sent to other peers
- */
-struct MeshData
-{
-  /** Tunnel it belongs to. */
-  struct MeshTunnel *t;
-
-  /** How many remaining neighbors still hav't got it. */
-  unsigned int reference_counter;
-
-  /** How many remaining neighbors we need to send this to. */
-  unsigned int total_out;
-
-  /** Size of the data. */
-  size_t data_len;
-
-  /** Data itself */
-  void *data;
-};
-
-
-/**
- * Struct containing info about a queued transmission to this peer
- */
-struct MeshPeerQueue
-{
-    /**
-      * DLL next
-      */
-  struct MeshPeerQueue *next;
-
-    /**
-      * DLL previous
-      */
-  struct MeshPeerQueue *prev;
-
-    /**
-     * Peer this transmission is directed to.
-     */
-  struct MeshPeerInfo *peer;
-
-    /**
-     * Tunnel this message belongs to.
-     */
-  struct MeshTunnel *tunnel;
-
-    /**
-     * Pointer to info stucture used as cls.
-     */
-  void *cls;
-
-    /**
-     * Type of message
-     */
-  uint16_t type;
-
-    /**
-     * Size of the message
-     */
-  size_t size;
-};
-
-
-/**
- * Struct to store regex information announced by clients.
- */
-struct MeshRegexDescriptor
-{
-    /**
-     * Regular expression itself.
-     */
-  char *regex;
-
-    /**
-     * How many characters per edge can we squeeze?
-     */
-  uint16_t compression;
-
-    /**
-     * Handle to announce the regex.
-     */
-  struct GNUNET_REGEX_Announcement *h;
-};
-
-
-/**
- * Struct to keep information of searches of services described by a regex
- * using a user-provided string service description.
- */
-struct MeshRegexSearchInfo
-{
-    /**
-     * Which tunnel is this for
-     */
-  struct MeshTunnel *t;
-
-    /**
-     * User provided description of the searched service.
-     */
-  char *description;
-
-    /**
-     * Regex search handle.
-     */
-  struct GNUNET_REGEX_Search *search_handle;
-
-    /**
-     * Peer that is connecting via connect_by_string. When connected, free ctx.
-     */
-  GNUNET_PEER_Id peer;
-
-    /**
-     * Other peers that are found but not yet being connected to.
-     */
-  GNUNET_PEER_Id *peers;
-
-    /**
-     * Number of elements in peers.
-     */
-  unsigned int n_peers;
-
-    /**
-     * Next peer to try to connect to.
-     */
-  unsigned int i_peer;
-
-    /**
-     * Timeout for a connect attempt.
-     * When reached, try to connect to a different peer, if any. If not,
-     * try the same peer again.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier timeout;
-
-};
-
-
-/**
- * Struct containing all info possibly needed to build a package when called
- * back by core.
- */
-struct MeshTransmissionDescriptor
-{
-    /** ID of the tunnel this packet travels in */
-  struct MESH_TunnelID *origin;
-
-    /** Who was this message being sent to */
-  struct MeshPeerInfo *peer;
-
-    /** Ultimate destination of the packet */
-  GNUNET_PEER_Id destination;
-
-    /** Data descriptor */
-  struct MeshData* mesh_data;
-};
-
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct MeshPeerInfo
-{
-    /**
-     * ID of the peer
-     */
-  GNUNET_PEER_Id id;
-
-    /**
-     * Last time we heard from this peer
-     */
-  struct GNUNET_TIME_Absolute last_contact;
-
-    /**
-     * Task handler for delayed connect task;
-     */
-  GNUNET_SCHEDULER_TaskIdentifier connect_task;
-
-    /**
-     * Number of attempts to reconnect so far
-     */
-  int n_reconnect_attempts;
-
-    /**
-     * Paths to reach the peer, ordered by ascending hop count
-     */
-  struct MeshPeerPath *path_head;
-
-    /**
-     * Paths to reach the peer, ordered by ascending hop count
-     */
-  struct MeshPeerPath *path_tail;
-
-    /**
-     * Handle to stop the DHT search for a path to this peer
-     */
-  struct GNUNET_DHT_GetHandle *dhtget;
-
-    /**
-     * Closure given to the DHT GET
-     */
-  struct MeshPathInfo *dhtgetcls;
-
-    /**
-     * Array of tunnels this peer participates in
-     * (most probably a small amount, therefore not a hashmap)
-     * When the path to the peer changes, notify these tunnels to let them
-     * re-adjust their path trees.
-     */
-  struct MeshTunnel **tunnels;
-
-    /**
-     * Number of tunnels this peers participates in
-     */
-  unsigned int ntunnels;
-
-   /**
-    * Transmission queue to core DLL head
-    */
-  struct MeshPeerQueue *queue_head;
-
-   /**
-    * Transmission queue to core DLL tail
-    */
-   struct MeshPeerQueue *queue_tail;
-
-   /**
-    * How many messages are in the queue to this peer.
-    */
-   unsigned int queue_n;
-
-   /**
-    * Handle to for queued transmissions
-    */
-  struct GNUNET_CORE_TransmitHandle *core_transmit;
-};
-
-
-/**
- * Globally unique tunnel identification (owner + number)
- * DO NOT USE OVER THE NETWORK
- */
-struct MESH_TunnelID
-{
-    /**
-     * Node that owns the tunnel
-     */
-  GNUNET_PEER_Id oid;
-
-    /**
-     * Tunnel number to differentiate all the tunnels owned by the node oid
-     * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
-     */
-  MESH_TunnelNumber tid;
-};
-
-
-/**
- * Struct containing all information regarding a tunnel
- * For an intermediate node the improtant info used will be:
- * - id        Tunnel unique identification
- * - paths[0]  To know where to send it next
- * - metainfo: ready, speeds, accounting
- */
-struct MeshTunnel
-{
-    /**
-     * Tunnel ID
-     */
-  struct MESH_TunnelID id;
-
-    /**
-     * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
-     */
-  MESH_TunnelNumber local_tid;
-
-    /**
-     * Local tunnel number for local destination clients (incoming number)
-     * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same
-     * number.
-     */
-  MESH_TunnelNumber local_tid_dest;
-
-    /**
-     * Is the speed on the tunnel limited to the slowest peer?
-     */
-  int speed_min;
-
-    /**
-     * Is the tunnel bufferless (minimum latency)?
-     */
-  int nobuffer;
-
-    /**
-     * Packet ID of the last fwd packet seen (sent/retransmitted/received).
-     */
-  uint32_t fwd_pid;
-
-    /**
-     * Packet ID of the last bck packet sent (unique counter per hop).
-     */
-  uint32_t bck_pid;
-
-    /**
-     * SKIP value for this tunnel.
-     */
-  uint32_t skip;
-
-    /**
-     * Force sending ACK? Flag to allow duplicate ACK on POLL.
-     */
-  int force_ack;
-
-    /**
-     * MeshTunnelChildInfo of all children, indexed by GNUNET_PEER_Id.
-     * Contains the Flow Control info: FWD ACK value received,
-     * last BCK ACK sent, PID and SKIP values.
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *children_fc;
-
-    /**
-     * Last ACK sent towards the origin (for traffic towards leaf node).
-     */
-  uint32_t last_fwd_ack;
-
-    /**
-     * BCK ACK value received from the hop towards the owner of the tunnel,
-     * (previous node / owner): up to what message PID can we sent back to him.
-     */
-  uint32_t bck_ack;
-
-    /**
-     * How many messages are in the forward queue (towards leaves).
-     */
-  unsigned int fwd_queue_n;
-
-    /**
-     * How many messages do we accept in the forward queue.
-     */
-  unsigned int fwd_queue_max;
-
-    /**
-     * How many messages are in the backward queue (towards origin).
-     */
-  unsigned int bck_queue_n;
-
-    /**
-     * How many messages do we accept in the backward queue.
-    */
-   unsigned int bck_queue_max;
-
-    /**
-     * Task to poll peer in case of a stall.
-     */
-   GNUNET_SCHEDULER_TaskIdentifier fc_poll_bck;
-
-    /**
-     * Last time the tunnel was used
-     */
-  struct GNUNET_TIME_Absolute timestamp;
-
-    /**
-     * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo)
-     * containing peers added by id or by type, not intermediate peers.
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *peers;
-
-    /**
-     * Number of peers that are connected and potentially ready to receive data
-     */
-  unsigned int peers_ready;
-
-    /**
-     * Client owner of the tunnel, if any
-     */
-  struct MeshClient *owner;
-
-    /**
-     * Clients that have been informed about and want to stay in the tunnel.
-     */
-  struct MeshClient **clients;
-
-    /**
-     * Flow control info for each client.
-     */
-  struct MeshTunnelClientInfo *clients_fc;
-
-  /**
-     * Number of elements in clients/clients_fc
-     */
-  unsigned int nclients;
-
-    /**
-     * Clients that have been informed but requested to leave the tunnel.
-     */
-  struct MeshClient **ignore;
-
-    /**
-     * Number of elements in clients
-     */
-  unsigned int nignore;
-
-    /**
-     * Blacklisted peers
-     */
-  GNUNET_PEER_Id *blacklisted;
-
-    /**
-     * Number of elements in blacklisted
-     */
-  unsigned int nblacklisted;
-
-  /**
-   * Bloomfilter (for peer identities) to stop circular routes
-   */
-  char bloomfilter[MESH_BLOOM_SIZE];
-
-  /**
-   * Tunnel paths
-   */
-  struct MeshTunnelTree *tree;
-
-  /**
-   * Application type we are looking for in this tunnel
-   */
-  GNUNET_MESH_ApplicationType type;
-
-    /**
-     * Used to search peers offering a service
-     */
-  struct GNUNET_DHT_GetHandle *dht_get_type;
-
-    /**
-     * Handle for the regex search for a connect_by_string
-     */
-  struct MeshRegexSearchInfo *regex_search;
-
-    /**
-     * Task to keep the used paths alive
-     */
-  GNUNET_SCHEDULER_TaskIdentifier path_refresh_task;
-
-    /**
-     * Task to destroy the tunnel after timeout
-     *
-     * FIXME: merge the two? a tunnel will have either
-     * a path refresh OR a timeout, never both!
-     */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-    /**
-     * Flag to signal the destruction of the tunnel.
-     * If this is set GNUNET_YES the tunnel will be destroyed
-     * when the queue is empty.
-     */
-  int destroy;
-
-    /**
-     * Total messages pending for this tunnels, payload or not.
-     */
-  unsigned int pending_messages;
-
-  /**
-   * If the tunnel is empty, destoy it.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier delayed_destroy;
-};
-
-
-/**
- * Info about a child node in a tunnel, needed to perform flow control.
- */
-struct MeshTunnelChildInfo
-{
-    /**
-     * ID of the child node.
-     */
-  GNUNET_PEER_Id id;
-
-    /**
-     * SKIP value.
-     */
-  uint32_t skip;
-
-    /**
-     * Last sent PID.
-     */
-  uint32_t fwd_pid;
-
-    /**
-     * Last received PID.
-     */
-  uint32_t bck_pid;
-
-    /**
-     * Maximum PID allowed (FWD ACK received).
-     */
-  uint32_t fwd_ack;
-
-    /**
-     * Last ACK sent to that child (BCK ACK).
-     */
-  uint32_t bck_ack;
-
-    /**
-     * Circular buffer pointing to MeshPeerQueue elements for all
-     * payload traffic going to this child.
-     * Size determined by the tunnel queue size (@c t->fwd_queue_max).
-     */
-  struct MeshPeerQueue **send_buffer;
-
-    /**
-     * Index of the oldest element in the send_buffer.
-     */
-  unsigned int send_buffer_start;
-
-    /**
-     * How many elements are already in the buffer.
-     */
-  unsigned int send_buffer_n;
-
-    /**
-     * Tunnel this info is about
-     */
-  struct MeshTunnel *t;
-
-    /**
-     * Task to poll peer in case of a stall.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier fc_poll;
-
-     /**
-      * Time to use for next polling call.
-      */
-   struct GNUNET_TIME_Relative fc_poll_time;
-};
-
-
-/**
- * Info about a leaf client of a tunnel, needed to perform flow control.
- */
-struct MeshTunnelClientInfo
-{
-  /**
-   * PID of the last packet sent to the client (FWD).
-   */
-  uint32_t fwd_pid;
-
-  /**
-   * PID of the last packet received from the client (BCK).
-   */
-  uint32_t bck_pid;
-
-  /**
-   * Maximum PID allowed (FWD ACK received).
-   */
-  uint32_t fwd_ack;
-  
-  /**
-   * Last ACK sent to that child (BCK ACK).
-   */
-  uint32_t bck_ack;
-};
-
-
-
-/**
- * Info collected during iteration of child nodes in order to get the ACK value
- * for a tunnel.
- */
-struct MeshTunnelChildIteratorContext
-{
-    /**
-     * Tunnel whose info is being collected.
-     */
-  struct MeshTunnel *t;
-
-    /**
-     * Is this context initialized? Is the value in max_child_ack valid?
-     */
-  int init;
-
-    /**
-     * Maximum child ACK so far.
-     */
-  uint32_t max_child_ack;
-
-    /**
-     * Number of children nodes
-     */
-  unsigned int nchildren;
-};
-
-
-/**
- * Info needed to work with tunnel paths and peers
- */
-struct MeshPathInfo
-{
-  /**
-   * Tunnel
-   */
-  struct MeshTunnel *t;
-
-  /**
-   * Neighbouring peer to whom we send the packet to
-   */
-  struct MeshPeerInfo *peer;
-
-  /**
-   * Path itself
-   */
-  struct MeshPeerPath *path;
-};
-
-
-/**
- * Struct containing information about a client of the service
- */
-struct MeshClient
-{
-    /**
-     * Linked list next
-     */
-  struct MeshClient *next;
-
-    /**
-     * Linked list prev
-     */
-  struct MeshClient *prev;
-
-    /**
-     * Tunnels that belong to this client, indexed by local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *own_tunnels;
-
-   /**
-     * Tunnels this client has accepted, indexed by incoming local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
-
-   /**
-     * Tunnels this client has rejected, indexed by incoming local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *ignore_tunnels;
-    /**
-     * Handle to communicate with the client
-     */
-  struct GNUNET_SERVER_Client *handle;
-
-    /**
-     * Applications that this client has claimed to provide: H(app) = app.
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *apps;
-
-    /**
-     * Messages that this client has declared interest in
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *types;
-
-    /**
-     * Whether the client is active or shutting down (don't send confirmations
-     * to a client that is shutting down.
-     */
-  int shutting_down;
-
-    /**
-     * ID of the client, mainly for debug messages
-     */
-  unsigned int id;
-  
-    /**
-     * Regular expressions describing the services offered by this client.
-     */
-  struct MeshRegexDescriptor *regexes; // FIXME regex add timeout? API to 
remove a regex?
-
-    /**
-     * Number of regular expressions in regexes.
-     */
-  unsigned int n_regex;
-
-    /**
-     * Task to refresh all regular expresions in the DHT.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier regex_announce_task;
-
-    /**
-     * Tmp store for partially retrieved regex.
-     */
-  char *partial_regex;
-
-};
-
-
-/******************************************************************************/
-/************************      DEBUG FUNCTIONS     
****************************/
-/******************************************************************************/
-
-#if MESH_DEBUG
-/**
- * GNUNET_SCHEDULER_Task for printing a message after some operation is done
- * @param cls string to print
- * @param success  GNUNET_OK if the PUT was transmitted,
- *                GNUNET_NO on timeout,
- *                GNUNET_SYSERR on disconnect from service
- *                after the PUT message was transmitted
- *                (so we don't know if it was received or not)
- */
-
-#if 0
-static void
-mesh_debug (void *cls, int success)
-{
-  char *s = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
-}
-#endif
-
-unsigned int debug_fwd_ack;
-unsigned int debug_bck_ack;
-
-#endif
-
-/******************************************************************************/
-/***********************      GLOBAL VARIABLES     
****************************/
-/******************************************************************************/
-
-/************************** Configuration parameters 
**************************/
-
-/**
- * How often to send tunnel keepalives. Tunnels timeout after 4 missed.
- */
-static struct GNUNET_TIME_Relative refresh_path_time;
-
-/**
- * How often to PUT local application numbers in the DHT.
- */
-static struct GNUNET_TIME_Relative app_announce_time;
-
-/**
- * How often to PUT own ID in the DHT.
- */
-static struct GNUNET_TIME_Relative id_announce_time;
-
-/**
- * Maximum time allowed to connect to a peer found by string.
- */
-static struct GNUNET_TIME_Relative connect_timeout;
-
-/**
- * Default TTL for payload packets.
- */
-static unsigned long long default_ttl;
-
-/**
- * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
- */
-static unsigned long long dht_replication_level;
-
-/**
- * How many tunnels are we willing to maintain.
- * Local tunnels are always allowed, even if there are more tunnels than max.
- */
-static unsigned long long max_tunnels;
-
-/**
- * How many messages *in total* are we willing to queue, divided by number of 
- * tunnels to get tunnel queue size.
- */
-static unsigned long long max_msgs_queue;
-
-/**
- * How many peers do we want to remember?
- */
-static unsigned long long max_peers;
-
-
-/*************************** Static global variables 
**************************/
-
-/**
- * Hostkey generation context
- */
-static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen;
-
-/**
- * DLL with all the clients, head.
- */
-static struct MeshClient *clients;
-
-/**
- * DLL with all the clients, tail.
- */
-static struct MeshClient *clients_tail;
-
-/**
- * Tunnels known, indexed by MESH_TunnelID (MeshTunnel).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
-
-/**
- * Number of tunnels known.
- */
-static unsigned long long n_tunnels;
-
-/**
- * Tunnels incoming, indexed by MESH_TunnelNumber
- * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
-
-/**
- * Peers known, indexed by PeerIdentity (MeshPeerInfo).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *peers;
-
-/**
- * Configuration handle
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Handle to communicate with core.
- */
-static struct GNUNET_CORE_Handle *core_handle;
-
-/**
- * Handle to use DHT.
- */
-static struct GNUNET_DHT_Handle *dht_handle;
-
-/**
- * Handle to server.
- */
-static struct GNUNET_SERVER_Handle *server_handle;
-
-/**
- * Handle to the statistics service.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Notification context, to send messages to local clients.
- */
-static struct GNUNET_SERVER_NotificationContext *nc;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-static GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-static struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Own private key.
- */
-static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
-
-/**
- * Own public key.
- */
-static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key;
-
-/**
- * Tunnel ID for the next created tunnel (global tunnel number).
- */
-static MESH_TunnelNumber next_tid;
-
-/**
- * Tunnel ID for the next incoming tunnel (local tunnel number).
- */
-static MESH_TunnelNumber next_local_tid;
-
-/**
- * All application types provided by this peer: H(app) = *Client.
- */
-static struct GNUNET_CONTAINER_MultiHashMap *applications;
-
-/**
- * All message types clients of this peer are interested in.
- */
-static struct GNUNET_CONTAINER_MultiHashMap *types;
-
-/**
- * Task to periodically announce provided applications.
- */
-GNUNET_SCHEDULER_TaskIdentifier announce_applications_task;
-
-/**
- * Task to periodically announce itself in the network.
- */
-GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
-
-/**
- * Next ID to assign to a client.
- */
-unsigned int next_client_id;
-
-
-/******************************************************************************/
-/***********************         DECLARATIONS        
**************************/
-/******************************************************************************/
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param exp when will this value expire
- * @param key key of the result
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- */
-static void
-dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
-                    const struct GNUNET_HashCode * key,
-                    const struct GNUNET_PeerIdentity *get_path,
-                    unsigned int get_path_length,
-                    const struct GNUNET_PeerIdentity *put_path,
-                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
-                    size_t size, const void *data);
-
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropiate structures if the peer is not known yet.
- *
- * @param peer Full identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_info_get (const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropiate structures if the peer is not known yet.
- *
- * @param peer Short identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_info_get_short (const GNUNET_PEER_Id peer);
-
-
-/**
- * Try to establish a new connection to this peer.
- * Use the best path for the given tunnel.
- * If the peer doesn't have any path to it yet, try to get one.
- * If the peer already has some path, send a CREATE PATH towards it.
- *
- * @param peer PeerInfo of the peer.
- * @param t Tunnel for which to create the path, if possible.
- */
-static void
-peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t);
-
-
-/**
- * Build a PeerPath from the paths returned from the DHT, reversing the paths
- * to obtain a local peer -> destination path and interning the peer ids.
- *
- * @return Newly allocated and created path
- */
-static struct MeshPeerPath *
-path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
-                     unsigned int get_path_length,
-                     const struct GNUNET_PeerIdentity *put_path,
-                     unsigned int put_path_length);
-
-
-/**
- * Adds a path to the peer_infos of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-static void
-path_add_to_peers (struct MeshPeerPath *p, int confirmed);
-
-
-/**
- * Add a peer to a tunnel, accomodating paths accordingly and initializing all
- * needed rescources.
- * If peer already exists, reevaluate shortest path and change if different.
- *
- * @param t Tunnel we want to add a new peer to
- * @param peer PeerInfo of the peer being added
- *
- */
-static void
-tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer);
-
-
-/**
- * Removes an explicit path from a tunnel, freeing all intermediate nodes
- * that are no longer needed, as well as nodes of no longer reachable peers.
- * The tunnel itself is also destoyed if results in a remote empty tunnel.
- *
- * @param t Tunnel from which to remove the path.
- * @param peer Short id of the peer which should be removed.
- */
-static void
-tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer);
-
-
-/**
- * Search for a tunnel by global ID using full PeerIdentities.
- *
- * @param oid owner of the tunnel.
- * @param tid global tunnel number.
- *
- * @return tunnel handler, NULL if doesn't exist.
- */
-static struct MeshTunnel *
-tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
-
-
-/**
- * Delete an active client from the tunnel.
- *
- * @param t Tunnel.
- * @param c Client.
- */
-static void
-tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c);
-
-/**
- * Notify a tunnel that a connection has broken that affects at least
- * some of its peers.
- *
- * @param t Tunnel affected.
- * @param p1 Peer that got disconnected from p2.
- * @param p2 Peer that got disconnected from p1.
- *
- * @return Short ID of the peer disconnected (either p1 or p2).
- *         0 if the tunnel remained unaffected.
- */
-static GNUNET_PEER_Id
-tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
-                                 GNUNET_PEER_Id p2);
-
-
-/**
- * Get the current ack value for a tunnel, for data going from root to leaves,
- * taking in account the tunnel mode and the status of all children and 
clients.
- *
- * @param t Tunnel.
- *
- * @return Maximum PID allowed.
- */
-static uint32_t
-tunnel_get_fwd_ack (struct MeshTunnel *t);
-
-
-/**
- * Add a client to a tunnel, initializing all needed data structures.
- * 
- * @param t Tunnel to which add the client.
- * @param c Client which to add to the tunnel.
- */
-static void
-tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c);
-
-
-/**
- * @brief Queue and pass message to core when possible.
- * 
- * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status
- * and accounts for it. In case the queue is full, the message is dropped and
- * a break issued.
- * 
- * Otherwise, message is treated as internal and allowed to go regardless of 
- * queue status.
- *
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- *            build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @param dst Neighbor to send message to.
- * @param t Tunnel this message belongs to.
- */
-static void
-queue_add (void *cls, uint16_t type, size_t size,
-           struct MeshPeerInfo *dst, struct MeshTunnel *t);
-
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- */
-static void
-queue_destroy (struct MeshPeerQueue *queue, int clear_cls);
-
-
-/**
- * @brief Get the next transmittable message from the queue.
- *
- * This will be the head, except in the case of being a data packet
- * not allowed by the destination peer.
- *
- * @param peer Destination peer.
- *
- * @return The next viable MeshPeerQueue element to send to that peer.
- *         NULL when there are no transmittable messages.
- */
-struct MeshPeerQueue *
-queue_get_next (const struct MeshPeerInfo *peer);
-
-
-/**
- * Core callback to write a queued packet to core buffer
- *
- * @param cls Closure (peer info).
- * @param size Number of bytes available in buf.
- * @param buf Where the to write the message.
- *
- * @return number of bytes written to buf
- */
-static size_t
-queue_send (void *cls, size_t size, void *buf);
-
-/******************************************************************************/
-/************************    REGEX INTEGRATION     
****************************/
-/******************************************************************************/
-
-/**
- * Cancel a mesh regex search and free resources.
- */
-static void
-regex_cancel_search (struct MeshRegexSearchInfo *regex_search)
-{
-  DEBUG_REGEX ("Search for %s canelled.\n", regex_search->description);
-  GNUNET_REGEX_search_cancel (regex_search->search_handle);
-  if (0 < regex_search->n_peers)
-    GNUNET_free (regex_search->peers);
-  if (GNUNET_SCHEDULER_NO_TASK != regex_search->timeout)
-  {
-    GNUNET_SCHEDULER_cancel(regex_search->timeout);
-  }
-  GNUNET_free (regex_search);
-}
-
-
-/**
- * Function called if the connect attempt to a peer found via
- * connect_by_string times out. Try to connect to another peer, if any.
- * Otherwise try to reconnect to the same peer.
- *
- * @param cls Closure (info about regex search).
- * @param tc TaskContext.
- */
-static void
-regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
-{
-  struct MeshRegexSearchInfo *info = cls;
-  struct MeshPeerInfo *peer_info;
-  GNUNET_PEER_Id id;
-  GNUNET_PEER_Id old;
-
-  DEBUG_REGEX ("Regex connect timeout\n");
-  info->timeout = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    DEBUG_REGEX (" due to shutdown\n");
-    return;
-  }
-
-  old = info->peer;
-  DEBUG_REGEX ("  timed out: %u\n", old);
-
-  if (0 < info->n_peers)
-  {
-    // Select next peer, put current in that spot.
-    id = info->peers[info->i_peer];
-    info->peers[info->i_peer] = info->peer;
-    info->i_peer = (info->i_peer + 1) % info->n_peers;
-  }
-  else
-  {
-    // Try to connect to same peer again.
-    id = info->peer;
-  }
-  DEBUG_REGEX ("  trying: %u\n", id);
-
-  peer_info = peer_info_get_short(id);
-  tunnel_add_peer (info->t, peer_info);
-  if (old != id)
-    tunnel_delete_peer (info->t, old);
-  peer_info_connect (peer_info, info->t);
-  info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout,
-                                                &regex_connect_timeout,
-                                                info);
-  DEBUG_REGEX ("Regex connect timeout END\n");
-}
-
-
-/**
- * Function to process DHT string to regex matching.
- * Called on each result obtained for the DHT search.
- *
- * @param cls Closure provided in GNUNET_REGEX_search.
- * @param id Peer providing a regex that matches the string.
- * @param get_path Path of the get request.
- * @param get_path_length Lenght of get_path.
- * @param put_path Path of the put request.
- * @param put_path_length Length of the put_path.
- */
-static void
-regex_found_handler (void *cls,
-                     const struct GNUNET_PeerIdentity *id,
-                     const struct GNUNET_PeerIdentity *get_path,
-                     unsigned int get_path_length,
-                     const struct GNUNET_PeerIdentity *put_path,
-                     unsigned int put_path_length)
-{
-  struct MeshRegexSearchInfo *info = cls;
-  struct MeshPeerPath *p;
-  struct MeshPeerInfo *peer_info;
-
-  DEBUG_REGEX ("Got regex results from DHT!\n");
-  DEBUG_REGEX ("  for %s\n", info->description);
-
-  peer_info = peer_info_get (id);
-  p = path_build_from_dht (get_path, get_path_length,
-                           put_path, put_path_length);
-  path_add_to_peers (p, GNUNET_NO);
-  path_destroy(p);
-
-  tunnel_add_peer (info->t, peer_info);
-  peer_info_connect (peer_info, info->t);
-  if (0 == info->peer)
-  {
-    info->peer = peer_info->id;
-  }
-  else
-  {
-    GNUNET_array_append (info->peers, info->n_peers, peer_info->id);
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != info->timeout)
-    return;
-
-  info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout,
-                                                &regex_connect_timeout,
-                                                info);
-
-  return;
-}
-
-
-/**
- * Store the regular expression describing a local service into the DHT.
- *
- * @param regex The regular expresion.
- */
-static void
-regex_put (struct MeshRegexDescriptor *regex)
-{
-  DEBUG_REGEX ("  regex_put (%s) start\n", regex->regex);
-  if (NULL == regex->h)
-  {
-    DEBUG_REGEX ("  first put, creating DFA\n");
-    regex->h = GNUNET_REGEX_announce (cfg,
-                                      regex->regex,
-                                     app_announce_time,
-                                      regex->compression);
-  }
-  DEBUG_REGEX ("  regex_put (%s) end\n", regex->regex);
-}
-
-
-/**
- * Periodically announce what applications are provided by local clients
- * (by regex)
- *
- * @param cls closure
- * @param tc task context
- */
-static void
-regex_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshClient *c = cls;
-  unsigned int i;
-
-  c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  DEBUG_REGEX ("Starting announce for regex\n");
-  for (i = 0; i < c->n_regex; i++)
-    regex_put (&c->regexes[i]);
-  c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time,
-                                                         &regex_announce,
-                                                         cls);
-  DEBUG_REGEX ("Finished announce for regex\n");
-}
-
-
-/******************************************************************************/
-/************************    PERIODIC FUNCTIONS    
****************************/
-/******************************************************************************/
-
-/**
- * Announce iterator over for each application provided by the peer
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-announce_application (void *cls, const struct GNUNET_HashCode * key, void 
*value)
-{
-  struct PBlock block;
-  struct MeshClient *c;
-
-  block.id = my_full_id;
-  c =  GNUNET_CONTAINER_multihashmap_get (applications, key);
-  GNUNET_assert(NULL != c);
-  block.type = (long) GNUNET_CONTAINER_multihashmap_get (c->apps, key);
-  if (0 == block.type)
-  {
-    GNUNET_break(0);
-    return GNUNET_YES;
-  }
-  block.type = htonl (block.type);
-  DEBUG_DHT ("Putting APP key: %s\n", GNUNET_h2s (key));
-  GNUNET_break (NULL != 
-                GNUNET_DHT_put (dht_handle, key,
-                               dht_replication_level,
-                               GNUNET_DHT_RO_RECORD_ROUTE |
-                               GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                               GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
-                               sizeof (block),
-                               (const char *) &block,
-                               GNUNET_TIME_relative_to_absolute 
(GNUNET_TIME_UNIT_HOURS), /* FIXME: this should be an option */
-                               app_announce_time, NULL, NULL));
-  return GNUNET_OK;
-}
-
-
-/**
- * Periodically announce what applications are provided by local clients
- * (by type)
- *
- * @param cls closure
- * @param tc task context
- */
-static void
-announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
-{
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
-    return;
-  }
- 
-  DEBUG_DHT ("Starting PUT for apps\n");
-
-  GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application,
-                                         NULL);
-  announce_applications_task =
-      GNUNET_SCHEDULER_add_delayed (app_announce_time, &announce_applications,
-                                    cls);
-  DEBUG_DHT ("Finished PUT for apps\n");
-}
-
-
-/**
- * Periodically announce self id in the DHT
- *
- * @param cls closure
- * @param tc task context
- */
-static void
-announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PBlock block;
-
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-    return;
-  }
-  /* TODO
-   * - Set data expiration in function of X
-   * - Adapt X to churn
-   */
-  DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
-
-  block.id = my_full_id;
-  block.type = htonl (0);
-  GNUNET_DHT_put (dht_handle,   /* DHT handle */
-                  &my_full_id.hashPubKey,       /* Key to use */
-                  dht_replication_level,     /* Replication level */
-                  GNUNET_DHT_RO_RECORD_ROUTE | 
GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
-                  GNUNET_BLOCK_TYPE_MESH_PEER,       /* Block type */
-                  sizeof (block),  /* Size of the data */
-                  (const char *) &block, /* Data itself */
-                  GNUNET_TIME_UNIT_FOREVER_ABS,  /* Data expiration */
-                  GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
-                  NULL,         /* Continuation */
-                  NULL);        /* Continuation closure */
-  announce_id_task =
-      GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
-}
-
-
-/******************************************************************************/
-/******************      GENERAL HELPER FUNCTIONS      
************************/
-/******************************************************************************/
-
-/**
- * Decrements the reference counter and frees all resources if needed
- *
- * @param mesh_data Data Descriptor used in a multicast message.
- *                  Freed no longer needed (last message).
- */
-static void
-data_descriptor_decrement_rc (struct MeshData *mesh_data)
-{
-  if (0 == --(mesh_data->reference_counter))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last copy!\n");
-    GNUNET_free (mesh_data->data);
-    GNUNET_free (mesh_data);
-  }
-}
-
-
-/**
- * Check if client has registered with the service and has not disconnected
- *
- * @param client the client to check
- *
- * @return non-NULL if client exists in the global DLL
- */
-static struct MeshClient *
-client_get (struct GNUNET_SERVER_Client *client)
-{
-  struct MeshClient *c;
-
-  c = clients;
-  while (NULL != c)
-  {
-    if (c->handle == client)
-      return c;
-    c = c->next;
-  }
-  return NULL;
-}
-
-
-/**
- * Checks if a given client has subscribed to certain message type
- *
- * @param message_type Type of message to check
- * @param c Client to check
- *
- * @return GNUNET_YES or GNUNET_NO, depending on subscription status
- * 
- * FIXME: use of crypto_hash slows it down
- *  The hash function alone takes 8-10us out of the ~55us for the whole
- * process of retransmitting the message from one local client to another.
- * Find faster implementation!
- */
-static int
-client_is_subscribed (uint16_t message_type, struct MeshClient *c)
-{
-  struct GNUNET_HashCode hc;
-
-  if (NULL == c->types)
-    return GNUNET_NO;
-
-  GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc);
-  return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc);
-}
-
-
-/**
- * Check whether client wants traffic from a tunnel.
- *
- * @param c Client to check.
- * @param t Tunnel to be found.
- *
- * @return GNUNET_YES if client knows tunnel.
- * 
- * TODO look in client hashmap
- */
-static int
-client_wants_tunnel (struct MeshClient *c, struct MeshTunnel *t)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->nclients; i++)
-    if (t->clients[i] == c)
-      return GNUNET_YES;
-  return GNUNET_NO;
-}
-
-
-/**
- * Check whether client has been informed about a tunnel.
- *
- * @param c Client to check.
- * @param t Tunnel to be found.
- *
- * @return GNUNET_YES if client knows tunnel.
- * 
- * TODO look in client hashmap
- */
-static int
-client_knows_tunnel (struct MeshClient *c, struct MeshTunnel *t)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->nignore; i++)
-    if (t->ignore[i] == c)
-      return GNUNET_YES;
-  return client_wants_tunnel(c, t);
-}
-
-
-/**
- * Marks a client as uninterested in traffic from the tunnel, updating both
- * client and tunnel to reflect this.
- *
- * @param c Client that doesn't want traffic anymore.
- * @param t Tunnel which should be ignored.
- *
- * FIXME when to delete an incoming tunnel?
- */
-static void
-client_ignore_tunnel (struct MeshClient *c, struct MeshTunnel *t)
-{
-  struct GNUNET_HashCode hash;
-
-  GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
-  GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
-                                                      &hash, t));
-  GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_put (c->ignore_tunnels, &hash, t,
-                                                   
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
-  tunnel_delete_active_client (t, c);
-  GNUNET_array_append (t->ignore, t->nignore, c);
-}
-
-
-/**
- * Deletes a tunnel from a client (either owner or destination). To be used on
- * tunnel destroy, otherwise, use client_ignore_tunnel.
- *
- * @param c Client whose tunnel to delete.
- * @param t Tunnel which should be deleted.
- */
-static void
-client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
-{
-  struct GNUNET_HashCode hash;
-
-  if (c == t->owner)
-  {
-    GNUNET_CRYPTO_hash(&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
-                                                         &hash,
-                                                         t));
-  }
-  else
-  {
-    GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
-    // FIXME XOR?
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
-                                                         &hash,
-                                                         t) ||
-                   GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels,
-                                                         &hash,
-                                                         t));
-  }
-}
-
-
-/**
- * Notify the owner of a tunnel that a peer has disconnected.
- * 
- * @param c Client (owner of tunnel).
- * @param t Tunnel this message is about.
- * @param peer_id Short ID of the disconnected peer.
- */
-void
-client_notify_peer_disconnected (struct MeshClient *c,
-                                 struct MeshTunnel *t,
-                                 GNUNET_PEER_Id peer_id)
-{
-  struct GNUNET_MESH_PeerControl msg;
-
-  if (NULL == t->owner || NULL == nc)
-    return;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
-  msg.tunnel_id = htonl (t->local_tid);
-  GNUNET_PEER_resolve (peer_id, &msg.peer);
-  GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
-                                              &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Send the message to all clients that have subscribed to its type
- *
- * @param msg Pointer to the message itself
- * @param payload Pointer to the payload of the message.
- * @param t The tunnel to whose clients this message goes.
- * 
- * @return number of clients this message was sent to
- */
-static unsigned int
-send_subscribed_clients (const struct GNUNET_MessageHeader *msg,
-                         const struct GNUNET_MessageHeader *payload,
-                         struct MeshTunnel *t)
-{
-  struct MeshClient *c;
-  MESH_TunnelNumber *tid;
-  unsigned int count;
-  uint16_t type;
-  char cbuf[htons (msg->size)];
-
-  type = ntohs (payload->type);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending to clients...\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "message of type %s\n",
-              GNUNET_MESH_DEBUG_M2S (type));
-
-  memcpy (cbuf, msg, sizeof (cbuf));
-  switch (htons (msg->type))
-  {
-    struct GNUNET_MESH_Unicast *uc;
-    struct GNUNET_MESH_Multicast *mc;
-    struct GNUNET_MESH_ToOrigin *to;
-
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      uc = (struct GNUNET_MESH_Unicast *) cbuf;
-      tid = &uc->tid;
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-      mc = (struct GNUNET_MESH_Multicast *) cbuf;
-      tid = &mc->tid;
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      to = (struct GNUNET_MESH_ToOrigin *) cbuf;
-      tid = &to->tid;
-      break;
-    default:
-      GNUNET_break (0);
-      return 0;
-  }
-
-  for (count = 0, c = clients; c != NULL; c = c->next)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   client %u\n", c->id);
-    if (client_is_subscribed (type, c))
-    {
-      if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN)
-      {
-        if (c != t->owner)
-          continue;
-        *tid = htonl (t->local_tid);
-      }
-      else
-      {
-        if (GNUNET_NO == client_knows_tunnel (c, t))
-        {
-          /* This client doesn't know the tunnel */
-          struct GNUNET_MESH_TunnelNotification tmsg;
-          struct GNUNET_HashCode hash;
-
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "     sending tunnel create\n");
-          tmsg.header.size = htons (sizeof (tmsg));
-          tmsg.header.type = htons 
(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
-          GNUNET_PEER_resolve (t->id.oid, &tmsg.peer);
-          tmsg.tunnel_id = htonl (t->local_tid_dest);
-          tmsg.opt = 0;
-          if (GNUNET_YES == t->speed_min)
-            tmsg.opt |= MESH_TUNNEL_OPT_SPEED_MIN;
-          if (GNUNET_YES == t->nobuffer)
-            tmsg.opt |= MESH_TUNNEL_OPT_NOBUFFER;
-          GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                                      &tmsg.header, GNUNET_NO);
-          tunnel_add_client (t, c);
-          GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
-                              &hash);
-          GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
-                                       c->incoming_tunnels, &hash, t,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
-        }
-        *tid = htonl (t->local_tid_dest);
-      }
-
-      /* Check if the client wants to get traffic from the tunnel */
-      if (GNUNET_NO == client_wants_tunnel(c, t))
-        continue;
-      count++;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "     sending\n");
-      GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                                  (struct GNUNET_MessageHeader
-                                                   *) cbuf, GNUNET_NO);
-    }
-  }
-
-  return count;
-}
-
-
-/**
- * Notify the client that owns the tunnel that a peer has connected to it
- * (the requested path to it has been confirmed).
- *
- * @param t Tunnel whose owner to notify
- * @param id Short id of the peer that has connected
- */
-static void
-send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id 
id)
-{
-  struct GNUNET_MESH_PeerControl pc;
-
-  if (NULL == t->owner || GNUNET_YES == t->destroy)
-    return;
-
-  pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
-  pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  pc.tunnel_id = htonl (t->local_tid);
-  GNUNET_PEER_resolve (id, &pc.peer);
-  GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, &pc.header,
-                                              GNUNET_NO);
-}
-
-
-/**
- * Notify all clients (not depending on registration status) that the incoming
- * tunnel is no longer valid.
- *
- * @param t Tunnel that was destroyed.
- */
-static void
-send_clients_tunnel_destroy (struct MeshTunnel *t)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-  msg.tunnel_id = htonl (t->local_tid_dest);
-  GNUNET_SERVER_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Notify clients of tunnel disconnections, if needed.
- * In case the origin disconnects, the destination clients get a tunnel destroy
- * notification. If the last destination disconnects (only one remaining client
- * in tunnel), the origin gets a (local ID) peer disconnected.
- * Note that the function must be called BEFORE removing the client from
- * the tunnel.
- *
- * @param t Tunnel that was destroyed.
- * @param c Client that disconnected.
- */
-static void
-send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c)
-{
-  unsigned int i;
-
-  if (c == t->owner)
-  {
-    struct GNUNET_MESH_TunnelMessage msg;
-
-    msg.header.size = htons (sizeof (msg));
-    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-    msg.tunnel_id = htonl (t->local_tid_dest);
-    for (i = 0; i < t->nclients; i++)
-      GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle,
-                                                  &msg.header, GNUNET_NO);
-  }
-  // FIXME when to disconnect an incoming tunnel?
-  else if (1 == t->nclients && NULL != t->owner)
-  {
-    struct GNUNET_MESH_PeerControl msg;
-
-    msg.header.size = htons (sizeof (msg));
-    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
-    msg.tunnel_id = htonl (t->local_tid);
-    msg.peer = my_full_id;
-    GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
-                                                &msg.header, GNUNET_NO);
-  }
-}
-
-
-/**
- * Iterator over all the peers to remove the oldest not-used entry.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- *
- * FIXME implement
- */
-static int
-peer_info_timeout (void *cls,
-                   const struct GNUNET_HashCode *key,
-                   void *value)
-{
-  return GNUNET_YES;
-}
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropiate structures if the peer is not known yet.
- *
- * @param peer Full identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_info_get (const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeerInfo *peer_info;
-
-  peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
-  if (NULL == peer_info)
-  {
-    peer_info =
-        (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
-    if (GNUNET_CONTAINER_multihashmap_size (peers) > max_peers)
-    {
-      GNUNET_CONTAINER_multihashmap_iterate (peers,
-                                             &peer_info_timeout,
-                                             NULL);
-    }
-    GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-    peer_info->id = GNUNET_PEER_intern (peer);
-  }
-  peer_info->last_contact = GNUNET_TIME_absolute_get();
-
-  return peer_info;
-}
-
-
-/**
- * Retrieve the MeshPeerInfo stucture associated with the peer, create one
- * and insert it in the appropiate structures if the peer is not known yet.
- *
- * @param peer Short identity of the peer.
- *
- * @return Existing or newly created peer info.
- */
-static struct MeshPeerInfo *
-peer_info_get_short (const GNUNET_PEER_Id peer)
-{
-  struct GNUNET_PeerIdentity id;
-
-  GNUNET_PEER_resolve (peer, &id);
-  return peer_info_get (&id);
-}
-
-
-/**
- * Iterator to remove the tunnel from the list of tunnels a peer participates
- * in.
- *
- * @param cls Closure (tunnel info)
- * @param key GNUNET_PeerIdentity of the peer (unused)
- * @param value PeerInfo of the peer
- *
- * @return always GNUNET_YES, to keep iterating
- */
-static int
-peer_info_delete_tunnel (void *cls, const struct GNUNET_HashCode * key, void 
*value)
-{
-  struct MeshTunnel *t = cls;
-  struct MeshPeerInfo *peer = value;
-  unsigned int i;
-
-  for (i = 0; i < peer->ntunnels; i++)
-  {
-    if (0 ==
-        memcmp (&peer->tunnels[i]->id, &t->id, sizeof (struct MESH_TunnelID)))
-    {
-      peer->ntunnels--;
-      peer->tunnels[i] = peer->tunnels[peer->ntunnels];
-      peer->tunnels = 
-        GNUNET_realloc (peer->tunnels, 
-                        peer->ntunnels * sizeof(struct MeshTunnel *));
-      return GNUNET_YES;
-    }
-  }
-  return GNUNET_YES;
-}
-
-
-/**
-  * Core callback to write a pre-constructed data packet to core buffer
-  *
-  * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
-  * @param size Number of bytes available in buf.
-  * @param buf Where the to write the message.
-  *
-  * @return number of bytes written to buf
-  */
-static size_t
-send_core_data_raw (void *cls, size_t size, void *buf)
-{
-  struct MeshTransmissionDescriptor *info = cls;
-  struct GNUNET_MessageHeader *msg;
-  size_t total_size;
-
-  GNUNET_assert (NULL != info);
-  GNUNET_assert (NULL != info->mesh_data);
-  msg = (struct GNUNET_MessageHeader *) info->mesh_data->data;
-  total_size = ntohs (msg->size);
-
-  if (total_size > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  memcpy (buf, msg, total_size);
-  data_descriptor_decrement_rc (info->mesh_data);
-  GNUNET_free (info);
-  return total_size;
-}
-
-
-/**
- * Sends an already built non-multicast message to a peer,
- * properly registrating all used resources.
- *
- * @param message Message to send. Function makes a copy of it.
- * @param peer Short ID of the neighbor whom to send the message.
- * @param t Tunnel on which this message is transmitted.
- */
-static void
-send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                       const struct GNUNET_PeerIdentity *peer,
-                       struct MeshTunnel *t)
-{
-  struct MeshTransmissionDescriptor *info;
-  struct MeshPeerInfo *neighbor;
-  struct MeshPeerPath *p;
-  size_t size;
-  uint16_t type;
-
-//   GNUNET_TRANSPORT_try_connect(); FIXME use?
-
-  size = ntohs (message->size);
-  info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
-  info->mesh_data = GNUNET_malloc (sizeof (struct MeshData));
-  info->mesh_data->data = GNUNET_malloc (size);
-  memcpy (info->mesh_data->data, message, size);
-  type = ntohs(message->type);
-  switch (type)
-  {
-    struct GNUNET_MESH_Unicast *m;
-    struct GNUNET_MESH_ToOrigin *to;
-
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      m = (struct GNUNET_MESH_Unicast *) info->mesh_data->data;
-      m->ttl = htonl (ntohl (m->ttl) - 1);
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      to = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data;
-      t->bck_pid++;
-      to->pid = htonl(t->bck_pid);
-  }
-  info->mesh_data->data_len = size;
-  info->mesh_data->reference_counter = 1;
-  info->mesh_data->total_out = 1;
-  neighbor = peer_info_get (peer);
-  for (p = neighbor->path_head; NULL != p; p = p->next)
-  {
-    if (2 >= p->length)
-    {
-      break;
-    }
-  }
-  if (NULL == p)
-  {
-#if MESH_DEBUG
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  %s IS NOT DIRECTLY CONNECTED\n",
-                GNUNET_i2s(peer));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  PATHS TO %s:\n",
-                GNUNET_i2s(peer));
-    for (p = neighbor->path_head; NULL != p; p = p->next)
-    {
-      struct GNUNET_PeerIdentity debug_id;
-      unsigned int i;
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "    path with %u hops through:\n",
-                  p->length);
-      for (i = 0; i < p->length; i++)
-      {
-        GNUNET_PEER_resolve(p->peers[i], &debug_id);
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "      hop %u: %s\n",
-                    i, GNUNET_i2s(&debug_id));
-      }
-    }
-#endif
-    GNUNET_break (0); // FIXME sometimes fails (testing disconnect?)
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    " no direct connection to %s\n",
-                    GNUNET_i2s (peer));
-    GNUNET_free (info->mesh_data->data);
-    GNUNET_free (info->mesh_data);
-    GNUNET_free (info);
-    return;
-  }
-  info->peer = neighbor;
-  if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type)
-    type = 0;
-  queue_add (info,
-             type,
-             size,
-             neighbor,
-             t);
-}
-
-
-/**
- * Sends a CREATE PATH message for a path to a peer, properly registrating
- * all used resources.
- *
- * @param peer PeerInfo of the final peer for whom this path is being created.
- * @param p Path itself.
- * @param t Tunnel for which the path is created.
- */
-static void
-send_create_path (struct MeshPeerInfo *peer, struct MeshPeerPath *p,
-                  struct MeshTunnel *t)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPathInfo *path_info;
-  struct MeshPeerInfo *neighbor;
-
-  unsigned int i;
-
-  if (NULL == p)
-  {
-    p = tree_get_path_to_peer (t->tree, peer->id);
-    if (NULL == p)
-    {
-      GNUNET_break (0);
-      return;
-    }
-  }
-  for (i = 0; i < p->length; i++)
-  {
-    if (p->peers[i] == myid)
-      break;
-  }
-  if (i >= p->length - 1)
-  {
-    path_destroy (p);
-    GNUNET_break (0);
-    return;
-  }
-  GNUNET_PEER_resolve (p->peers[i + 1], &id);
-
-  path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
-  path_info->path = p;
-  path_info->t = t;
-  neighbor = peer_info_get (&id);
-  path_info->peer = neighbor;
-  queue_add (path_info,
-             GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE,
-             sizeof (struct GNUNET_MESH_ManipulatePath) +
-                (p->length * sizeof (struct GNUNET_PeerIdentity)),
-             neighbor,
-             t);
-}
-
-
-/**
- * Sends a DESTROY PATH message to free resources for a path in a tunnel
- *
- * @param t Tunnel whose path to destroy.
- * @param destination Short ID of the peer to whom the path to destroy.
- */
-static void
-send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination)
-{
-  struct MeshPeerPath *p;
-  size_t size;
-
-  p = tree_get_path_to_peer (t->tree, destination);
-  if (NULL == p)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  size = sizeof (struct GNUNET_MESH_ManipulatePath);
-  size += p->length * sizeof (struct GNUNET_PeerIdentity);
-  {
-    struct GNUNET_MESH_ManipulatePath *msg;
-    struct GNUNET_PeerIdentity *pi;
-    char cbuf[size];
-    unsigned int i;
-
-    msg = (struct GNUNET_MESH_ManipulatePath *) cbuf;
-    msg->header.size = htons (size);
-    msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY);
-    msg->tid = htonl (t->id.tid);
-    pi = (struct GNUNET_PeerIdentity *) &msg[1];
-    for (i = 0; i < p->length; i++)
-    {
-      GNUNET_PEER_resolve (p->peers[i], &pi[i]);
-    }
-    send_prebuilt_message (&msg->header, tree_get_first_hop (t->tree, 
destination), t);
-  }
-  path_destroy (p);
-}
-
-
-/**
- * Sends a PATH ACK message in reponse to a received PATH_CREATE directed to 
us.
- *
- * @param t Tunnel which to confirm.
- */
-static void
-send_path_ack (struct MeshTunnel *t) 
-{
-  struct MeshTransmissionDescriptor *info;
-  struct GNUNET_PeerIdentity id;
-  GNUNET_PEER_Id peer;
-
-  peer = tree_get_predecessor (t->tree);
-  GNUNET_PEER_resolve (peer, &id);
-  info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
-  info->origin = &t->id;
-  info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
-  GNUNET_assert (NULL != info->peer);
-
-  queue_add (info,
-             GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
-             sizeof (struct GNUNET_MESH_PathACK),
-             info->peer,
-             t);
-}
-
-
-/**
- * Try to establish a new connection to this peer.
- * Use the best path for the given tunnel.
- * If the peer doesn't have any path to it yet, try to get one.
- * If the peer already has some path, send a CREATE PATH towards it.
- *
- * @param peer PeerInfo of the peer.
- * @param t Tunnel for which to create the path, if possible.
- */
-static void
-peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
-{
-  struct MeshPeerPath *p;
-  struct MeshPathInfo *path_info;
-
-  if (NULL != peer->path_head)
-  {
-    p = tree_get_path_to_peer (t->tree, peer->id);
-    if (NULL == p)
-    {
-      GNUNET_break (0);
-      return;
-    }
-
-    // FIXME always send create path to self
-    if (p->length > 1)
-    {
-      send_create_path (peer, p, t);
-    }
-    else
-    {
-      struct GNUNET_HashCode hash;
-
-      path_destroy (p);
-      send_client_peer_connected (t, myid);
-      t->local_tid_dest = next_local_tid++;
-      GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
-                          &hash);
-      if (GNUNET_OK !=
-          GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
-                                             
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-      {
-        GNUNET_break (0);
-        return;
-      }
-    }
-  }
-  else if (NULL == peer->dhtget)
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (peer->id, &id);
-    path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
-    path_info->peer = peer;
-    path_info->t = t;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
-    peer->dhtgetcls = path_info;
-    peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
-                                         GNUNET_BLOCK_TYPE_MESH_PEER, /* type 
*/
-                                         &id.hashPubKey,     /* key to search 
*/
-                                         dht_replication_level, /* replication 
level */
-                                         GNUNET_DHT_RO_RECORD_ROUTE |
-                                         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                                         NULL,       /* xquery */ // FIXME 
BLOOMFILTER
-                                         0,     /* xquery bits */ // FIXME 
BLOOMFILTER SIZE
-                                         &dht_get_id_handler, path_info);
-  }
-  /* Otherwise, there is no path but the DHT get is already started. */
-}
-
-
-/**
- * Task to delay the connection of a peer
- *
- * @param cls Closure (path info with tunnel and peer to connect).
- *            Will be free'd on exection.
- * @param tc TaskContext
- */
-static void
-peer_info_connect_task (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshPathInfo *path_info = cls;
-
-  path_info->peer->connect_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-  {
-    GNUNET_free (cls);
-    return;
-  }
-  peer_info_connect (path_info->peer, path_info->t);
-  GNUNET_free (cls);
-}
-
-
-/**
- * Destroy the peer_info and free any allocated resources linked to it
- *
- * @param pi The peer_info to destroy.
- *
- * @return GNUNET_OK on success
- */
-static int
-peer_info_destroy (struct MeshPeerInfo *pi)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerPath *p;
-  struct MeshPeerPath *nextp;
-
-  GNUNET_PEER_resolve (pi->id, &id);
-  GNUNET_PEER_change_rc (pi->id, -1);
-
-  if (GNUNET_YES !=
-      GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi))
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "removing peer %s, not in hashmap\n", GNUNET_i2s (&id));
-  }
-  if (NULL != pi->dhtget)
-  {
-    GNUNET_DHT_get_stop (pi->dhtget);
-    GNUNET_free (pi->dhtgetcls);
-  }
-  p = pi->path_head;
-  while (NULL != p)
-  {
-    nextp = p->next;
-    GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p);
-    path_destroy (p);
-    p = nextp;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != pi->connect_task)
-  {
-    GNUNET_free (GNUNET_SCHEDULER_cancel (pi->connect_task));
-  }
-  GNUNET_free (pi);
-  return GNUNET_OK;
-}
-
-
-/**
- * Remove all paths that rely on a direct connection between p1 and p2
- * from the peer itself and notify all tunnels about it.
- *
- * @param peer PeerInfo of affected peer.
- * @param p1 GNUNET_PEER_Id of one peer.
- * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
- *           no longer is.
- *
- * TODO: optimize (see below)
- */
-static void
-peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
-                       GNUNET_PEER_Id p2)
-{
-  struct MeshPeerPath *p;
-  struct MeshPeerPath *aux;
-  struct MeshPeerInfo *peer_d;
-  GNUNET_PEER_Id d;
-  unsigned int destroyed;
-  unsigned int best;
-  unsigned int cost;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n");
-  destroyed = 0;
-  p = peer->path_head;
-  while (NULL != p)
-  {
-    aux = p->next;
-    for (i = 0; i < (p->length - 1); i++)
-    {
-      if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
-          (p->peers[i] == p2 && p->peers[i + 1] == p1))
-      {
-        GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
-        path_destroy (p);
-        destroyed++;
-        break;
-      }
-    }
-    p = aux;
-  }
-  if (0 == destroyed)
-    return;
-
-  for (i = 0; i < peer->ntunnels; i++)
-  {
-    d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
-    if (0 == d)
-      continue;
-    /* TODO
-     * Problem: one or more peers have been deleted from the tunnel tree.
-     * We don't know who they are to try to add them again.
-     * We need to try to find a new path for each of the disconnected peers.
-     * Some of them might already have a path to reach them that does not
-     * involve p1 and p2. Adding all anew might render in a better tree than
-     * the trivial immediate fix.
-     *
-     * Trivial immiediate fix: try to reconnect to the disconnected node. All
-     * its children will be reachable trough him.
-     */
-    peer_d = peer_info_get_short (d);
-    best = UINT_MAX;
-    aux = NULL;
-    for (p = peer_d->path_head; NULL != p; p = p->next)
-    {
-      if ((cost = tree_get_path_cost (peer->tunnels[i]->tree, p)) < best)
-      {
-        best = cost;
-        aux = p;
-      }
-    }
-    if (NULL != aux)
-    {
-      /* No callback, as peer will be already disconnected and a connection
-       * scheduled by tunnel_notify_connection_broken.
-       */
-      tree_add_path (peer->tunnels[i]->tree, aux, NULL, NULL);
-    }
-    else
-    {
-      peer_info_connect (peer_d, peer->tunnels[i]);
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n");
-}
-
-
-/**
- * Add the path to the peer and update the path used to reach it in case this
- * is the shortest.
- *
- * @param peer_info Destination peer to add the path to.
- * @param path New path to add. Last peer must be the peer in arg 1.
- *             Path will be either used of freed if already known.
- * @param trusted Do we trust that this path is real?
- */
-void
-peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
-                    int trusted)
-{
-  struct MeshPeerPath *aux;
-  unsigned int l;
-  unsigned int l2;
-
-  if ((NULL == peer_info) || (NULL == path))
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return;
-  }
-  if (path->peers[path->length - 1] != peer_info->id)
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return;
-  }
-  if (path->length <= 2 && GNUNET_NO == trusted)
-  {
-    /* Only allow CORE to tell us about direct paths */
-    path_destroy (path);
-    return;
-  }
-  GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
-  for (l = 1; l < path->length; l++)
-  {
-    if (path->peers[l] == myid)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
-      for (l2 = 0; l2 < path->length - l; l2++)
-      {
-        path->peers[l2] = path->peers[l + l2];
-      }
-      path->length -= l;
-      l = 1;
-      path->peers =
-          GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
-    }
-  }
-#if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (peer_info->id, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
-                path->length, GNUNET_i2s (&id));
-  }
-#endif
-  l = path_get_length (path);
-  if (0 == l)
-  {
-    GNUNET_free (path);
-    return;
-  }
-
-  GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
-  for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
-  {
-    l2 = path_get_length (aux);
-    if (l2 > l)
-    {
-      GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
-                                          peer_info->path_tail, aux, path);
-      return;
-    }
-    else
-    {
-      if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
-      {
-        path_destroy (path);
-        return;
-      }
-    }
-  }
-  GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
-                                    path);
-  return;
-}
-
-
-/**
- * Add the path to the origin peer and update the path used to reach it in case
- * this is the shortest.
- * The path is given in peer_info -> destination, therefore we turn the path
- * upside down first.
- *
- * @param peer_info Peer to add the path to, being the origin of the path.
- * @param path New path to add after being inversed.
- * @param trusted Do we trust that this path is real?
- */
-static void
-peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
-                              struct MeshPeerPath *path, int trusted)
-{
-  path_invert (path);
-  peer_info_add_path (peer_info, path, trusted);
-}
-
-
-/**
- * Function called if the connection to the peer has been stalled for a while,
- * possibly due to a missed ACK. Poll the peer about its ACK status.
- *
- * @param cls Closure (cinfo).
- * @param tc TaskContext.
- */
-static void
-tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshTunnelChildInfo *cinfo = cls;
-  struct GNUNET_MESH_Poll msg;
-  struct GNUNET_PeerIdentity id;
-  struct MeshTunnel *t;
-
-  cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    return;
-  }
-
-  t = cinfo->t;
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
-  msg.header.size = htons (sizeof (msg));
-  msg.tid = htonl (t->id.tid);
-  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-  msg.last_ack = htonl (cinfo->fwd_ack);
-
-  GNUNET_PEER_resolve (cinfo->id, &id);
-  send_prebuilt_message (&msg.header, &id, cinfo->t);
-  cinfo->fc_poll_time = GNUNET_TIME_relative_min (
-    MESH_MAX_POLL_TIME,
-    GNUNET_TIME_relative_multiply (cinfo->fc_poll_time, 2));
-  cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time,
-                                                 &tunnel_poll, cinfo);
-}
-
-
-/**
- * Build a PeerPath from the paths returned from the DHT, reversing the paths
- * to obtain a local peer -> destination path and interning the peer ids.
- *
- * @return Newly allocated and created path
- */
-static struct MeshPeerPath *
-path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
-                     unsigned int get_path_length,
-                     const struct GNUNET_PeerIdentity *put_path,
-                     unsigned int put_path_length)
-{
-  struct MeshPeerPath *p;
-  GNUNET_PEER_Id id;
-  int i;
-
-  p = path_new (1);
-  p->peers[0] = myid;
-  GNUNET_PEER_change_rc (myid, 1);
-  i = get_path_length;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   GET has %d hops.\n", i);
-  for (i--; i >= 0; i--)
-  {
-    id = GNUNET_PEER_intern (&get_path[i]);
-    if (p->length > 0 && id == p->peers[p->length - 1])
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
-      GNUNET_PEER_change_rc (id, -1);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from GET: %s.\n",
-                  GNUNET_i2s (&get_path[i]));
-      p->length++;
-      p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * 
p->length);
-      p->peers[p->length - 1] = id;
-    }
-  }
-  i = put_path_length;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   PUT has %d hops.\n", i);
-  for (i--; i >= 0; i--)
-  {
-    id = GNUNET_PEER_intern (&put_path[i]);
-    if (id == myid)
-    {
-      /* PUT path went through us, so discard the path up until now and start
-       * from here to get a much shorter (and loop-free) path.
-       */
-      path_destroy (p);
-      p = path_new (0);
-    }
-    if (p->length > 0 && id == p->peers[p->length - 1])
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
-      GNUNET_PEER_change_rc (id, -1);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from PUT: %s.\n",
-                  GNUNET_i2s (&put_path[i]));
-      p->length++;
-      p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * 
p->length);
-      p->peers[p->length - 1] = id;
-    }
-  }
-#if MESH_DEBUG
-  if (get_path_length > 0)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of GET: %s)\n",
-                GNUNET_i2s (&get_path[0]));
-  if (put_path_length > 0)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of PUT: %s)\n",
-                GNUNET_i2s (&put_path[0]));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   In total: %d hops\n",
-              p->length);
-  for (i = 0; i < p->length; i++)
-  {
-    struct GNUNET_PeerIdentity peer_id;
-
-    GNUNET_PEER_resolve (p->peers[i], &peer_id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "       %u: %s\n", p->peers[i],
-                GNUNET_i2s (&peer_id));
-  }
-#endif
-  return p;
-}
-
-
-/**
- * Adds a path to the peer_infos of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-static void
-path_add_to_peers (struct MeshPeerPath *p, int confirmed)
-{
-  unsigned int i;
-
-  /* TODO: invert and add */
-  for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
-  for (i++; i < p->length; i++)
-  {
-    struct MeshPeerInfo *aux;
-    struct MeshPeerPath *copy;
-
-    aux = peer_info_get_short (p->peers[i]);
-    copy = path_duplicate (p);
-    copy->length = i + 1;
-    peer_info_add_path (aux, copy, GNUNET_NO);
-  }
-}
-
-
-/**
- * Send keepalive packets for a peer
- *
- * @param cls Closure (tunnel for which to send the keepalive).
- * @param tc Notification context.
- *
- * TODO: implement explicit multicast keepalive?
- */
-static void
-path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Search for a tunnel among the incoming tunnels
- *
- * @param tid the local id of the tunnel
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get_incoming (MESH_TunnelNumber tid)
-{
-  struct GNUNET_HashCode hash;
-
-  GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
-  GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
-  return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
-}
-
-
-/**
- * Search for a tunnel among the tunnels for a client
- *
- * @param c the client whose tunnels to search in
- * @param tid the local id of the tunnel
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
-{
-  if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    return tunnel_get_incoming (tid);
-  }
-  else
-  {
-    struct GNUNET_HashCode hash;
-
-    GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
-    return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
-  }
-}
-
-
-/**
- * Search for a tunnel by global ID using PEER_ID
- *
- * @param pi owner of the tunnel
- * @param tid global tunnel number
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
-{
-  struct MESH_TunnelID id;
-  struct GNUNET_HashCode hash;
-
-  id.oid = pi;
-  id.tid = tid;
-
-  GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
-  return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
-}
-
-
-/**
- * Search for a tunnel by global ID using full PeerIdentities
- *
- * @param oid owner of the tunnel
- * @param tid global tunnel number
- *
- * @return tunnel handler, NULL if doesn't exist
- */
-static struct MeshTunnel *
-tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
-{
-  return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
-}
-
-
-/**
- * Delete an active client from the tunnel.
- * 
- * @param t Tunnel.
- * @param c Client.
- */
-static void
-tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->nclients; i++)
-  {
-    if (t->clients[i] == c)
-    {
-      t->clients[i] = t->clients[t->nclients - 1];
-      t->clients_fc[i] = t->clients_fc[t->nclients - 1];
-      GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1);
-      t->nclients++;
-      GNUNET_array_grow (t->clients_fc, t->nclients, t->nclients - 1);
-      break;
-    }
-  }
-}
-
-
-/**
- * Delete an ignored client from the tunnel.
- * 
- * @param t Tunnel.
- * @param c Client.
- */
-static void
-tunnel_delete_ignored_client (struct MeshTunnel *t, const struct MeshClient *c)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->nignore; i++)
-  {
-    if (t->ignore[i] == c)
-    {
-      t->ignore[i] = t->ignore[t->nignore - 1];
-      GNUNET_array_grow (t->ignore, t->nignore, t->nignore - 1);
-      break;
-    }
-  }
-}
-
-
-/**
- * Delete a client from the tunnel. It should be only done on
- * client disconnection, otherwise use client_ignore_tunnel.
- * 
- * @param t Tunnel.
- * @param c Client.
- */
-static void
-tunnel_delete_client (struct MeshTunnel *t, const struct MeshClient *c)
-{
-  tunnel_delete_ignored_client (t, c);
-  tunnel_delete_active_client (t, c);
-}
-
-
-/**
- * @brief Iterator to destroy MeshTunnelChildInfo of tunnel children.
- * 
- * Destroys queue elements of all waiting transmissions and frees all memory
- * used by the struct and its elements.
- *
- * @param cls Closure (tunnel info).
- * @param key Hash of GNUNET_PEER_Id (unused).
- * @param value MeshTunnelChildInfo of the child.
- *
- * @return always GNUNET_YES, to keep iterating
- */
-static int
-tunnel_destroy_child (void *cls,
-                      const struct GNUNET_HashCode * key,
-                      void *value)
-{
-  struct MeshTunnelChildInfo *cinfo = value;
-  struct MeshTunnel *t = cls;
-  struct MeshPeerQueue *q;
-  unsigned int c;
-  unsigned int i;
-
-  for (c = 0; c < cinfo->send_buffer_n; c++)
-  {
-    i = (cinfo->send_buffer_start + c) % t->fwd_queue_max;
-    q = cinfo->send_buffer[i];
-    cinfo->send_buffer[i] = NULL;
-    if (NULL != q)
-      queue_destroy (q, GNUNET_YES);
-    else
-      GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n);
-  }
-  GNUNET_free_non_null (cinfo->send_buffer);
-  if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll)
-  {
-    GNUNET_SCHEDULER_cancel (cinfo->fc_poll);
-    cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_free (cinfo);
-  return GNUNET_YES;
-}
-
-
-/**
- * Callback used to notify a client owner of a tunnel that a peer has
- * disconnected, most likely because of a path change.
- *
- * @param cls Closure (tunnel this notification is about).
- * @param peer_id Short ID of disconnected peer.
- */
-void
-tunnel_notify_client_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id)
-{
-  struct MeshTunnel *t = cls;
-  struct MeshPeerInfo *peer;
-  struct MeshPathInfo *path_info;
-
-  client_notify_peer_disconnected (t->owner, t, peer_id);
-
-  peer = peer_info_get_short (peer_id);
-  path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
-  path_info->peer = peer;
-  path_info->t = t;
-  peer->connect_task = GNUNET_SCHEDULER_add_now (&peer_info_connect_task,
-                                                 path_info);
-}
-
-
-/**
- * Add a peer to a tunnel, accomodating paths accordingly and initializing all
- * needed rescources.
- * If peer already exists, reevaluate shortest path and change if different.
- *
- * @param t Tunnel we want to add a new peer to
- * @param peer PeerInfo of the peer being added
- *
- */
-static void
-tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerPath *best_p;
-  struct MeshPeerPath *p;
-  unsigned int best_cost;
-  unsigned int cost;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer\n");
-  GNUNET_PEER_resolve (peer->id, &id);
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (t->peers, &id.hashPubKey))
-  {
-    GNUNET_array_append (peer->tunnels, peer->ntunnels, t);
-    GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CONTAINER_multihashmap_put (t->peers, &id.hashPubKey,
-                                                      peer,
-                                                      
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
-  }
-
-  if (NULL != (p = peer->path_head))
-  {
-    best_p = p;
-    best_cost = tree_get_path_cost (t->tree, p);
-    while (NULL != p)
-    {
-      if ((cost = tree_get_path_cost (t->tree, p)) < best_cost)
-      {
-        best_cost = cost;
-        best_p = p;
-      }
-      p = p->next;
-    }
-    tree_add_path (t->tree, best_p, &tunnel_notify_client_peer_disconnected, 
t);
-    if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task)
-      t->path_refresh_task =
-          GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
-  }
-  else
-  {
-    /* Start a DHT get */
-    peer_info_connect (peer, t);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer END\n");
-}
-
-/**
- * Add a path to a tunnel which we don't own, just to remember the next hop.
- * If destination node was already in the tunnel, the first hop information
- * will be replaced with the new path.
- *
- * @param t Tunnel we want to add a new peer to
- * @param p Path to add
- * @param own_pos Position of local node in path.
- *
- */
-static void
-tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p,
-                 unsigned int own_pos)
-{
-  struct GNUNET_PeerIdentity id;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path\n");
-  GNUNET_assert (0 != own_pos);
-  tree_add_path (t->tree, p, NULL, NULL);
-  if (own_pos < p->length - 1)
-  {
-    GNUNET_PEER_resolve (p->peers[own_pos + 1], &id);
-    tree_update_first_hops (t->tree, myid, &id);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path END\n");
-}
-
-/**
- * Add a client to a tunnel, initializing all needed data structures.
- * 
- * @param t Tunnel to which add the client.
- * @param c Client which to add to the tunnel.
- */
-static void
-tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
-{
-  struct MeshTunnelClientInfo clinfo;
-
-  GNUNET_array_append (t->clients, t->nclients, c);
-  clinfo.fwd_ack = t->fwd_pid + 1;
-  clinfo.bck_ack = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1;
-  clinfo.fwd_pid = t->fwd_pid;
-  clinfo.bck_pid = (uint32_t) -1; // Expected next: 0
-  t->nclients--;
-  GNUNET_array_append (t->clients_fc, t->nclients, clinfo);
-}
-
-
-/**
- * Notifies a tunnel that a connection has broken that affects at least
- * some of its peers. Sends a notification towards the root of the tree.
- * In case the peer is the owner of the tree, notifies the client that owns
- * the tunnel and tries to reconnect.
- *
- * @param t Tunnel affected.
- * @param p1 Peer that got disconnected from p2.
- * @param p2 Peer that got disconnected from p1.
- *
- * @return Short ID of the peer disconnected (either p1 or p2).
- *         0 if the tunnel remained unaffected.
- */
-static GNUNET_PEER_Id
-tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
-                                 GNUNET_PEER_Id p2)
-{
-  GNUNET_PEER_Id pid;
-
-  pid =
-      tree_notify_connection_broken (t->tree, p1, p2,
-                                     &tunnel_notify_client_peer_disconnected,
-                                     t);
-  if (myid != p1 && myid != p2)
-  {
-    return pid;
-  }
-  if (pid != myid)
-  {
-    if (tree_get_predecessor (t->tree) != 0)
-    {
-      /* We are the peer still connected, notify owner of the disconnection. */
-      struct GNUNET_MESH_PathBroken msg;
-      struct GNUNET_PeerIdentity neighbor;
-
-      msg.header.size = htons (sizeof (msg));
-      msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
-      GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-      msg.tid = htonl (t->id.tid);
-      msg.peer1 = my_full_id;
-      GNUNET_PEER_resolve (pid, &msg.peer2);
-      GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
-      send_prebuilt_message (&msg.header, &neighbor, t);
-    }
-  }
-  return pid;
-}
-
-
-/**
- * Send a multicast packet to a neighbor.
- *
- * @param cls Closure (Info about the multicast packet)
- * @param neighbor_id Short ID of the neighbor to send the packet to.
- */
-static void
-tunnel_send_multicast_iterator (void *cls, GNUNET_PEER_Id neighbor_id)
-{
-  struct MeshData *mdata = cls;
-  struct MeshTransmissionDescriptor *info;
-  struct GNUNET_PeerIdentity neighbor;
-  struct GNUNET_MessageHeader *msg;
-
-  info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
-
-  info->mesh_data = mdata;
-  (mdata->reference_counter) ++;
-  info->destination = neighbor_id;
-  GNUNET_PEER_resolve (neighbor_id, &neighbor);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   sending to %s...\n",
-              GNUNET_i2s (&neighbor));
-  info->peer = peer_info_get (&neighbor);
-  GNUNET_assert (NULL != info->peer);
-  msg = (struct GNUNET_MessageHeader *) mdata->data;
-  queue_add(info,
-            ntohs (msg->type),
-            info->mesh_data->data_len,
-            info->peer,
-            mdata->t);
-}
-
-
-/**
- * Queue a message in a tunnel in multicast, sending a copy to each child node
- * down the local one in the tunnel tree.
- *
- * @param t Tunnel in which to send the data.
- * @param msg Message to be sent.
- */
-static void
-tunnel_send_multicast (struct MeshTunnel *t,
-                       const struct GNUNET_MessageHeader *msg)
-{
-  struct MeshData *mdata;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " sending a multicast packet...\n");
-
-  mdata = GNUNET_malloc (sizeof (struct MeshData));
-  mdata->data_len = ntohs (msg->size);
-  mdata->t = t;
-  mdata->data = GNUNET_malloc (mdata->data_len);
-  memcpy (mdata->data, msg, mdata->data_len);
-  if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
-  {
-    struct GNUNET_MESH_Multicast *mcast;
-
-    mcast = (struct GNUNET_MESH_Multicast *) mdata->data;
-    if (t->fwd_queue_n >= t->fwd_queue_max)
-    {
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  queue full!\n");
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "  message from %s!\n",
-                  GNUNET_i2s(&mcast->oid));
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "  message at %s!\n",
-                  GNUNET_i2s(&my_full_id));
-      GNUNET_free (mdata->data);
-      GNUNET_free (mdata);
-      return;
-    }
-    t->fwd_queue_n++;
-    mcast->ttl = htonl (ntohl (mcast->ttl) - 1);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  data packet, ttl: %u\n",
-                ntohl (mcast->ttl));
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  not a data packet, no ttl\n");
-  }
-
-  tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
-  if (mdata->reference_counter == 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  no one to send data to\n");
-    GNUNET_free (mdata->data);
-    GNUNET_free (mdata);
-    if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
-      t->fwd_queue_n--;
-  }
-  else
-  {
-    mdata->total_out = mdata->reference_counter;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " sending a multicast packet done\n");
-  return;
-}
-
-
-/**
- * Increase the SKIP value of all peers that
- * have not received a unicast message.
- *
- * @param cls Closure (ID of the peer that HAS received the message).
- * @param key ID of the neighbor.
- * @param value Information about the neighbor.
- *
- * @return GNUNET_YES to keep iterating.
- */
-static int
-tunnel_add_skip (void *cls,
-                 const struct GNUNET_HashCode * key,
-                 void *value)
-{
-  struct GNUNET_PeerIdentity *neighbor = cls;
-  struct MeshTunnelChildInfo *cinfo = value;
-
-  /* TODO compare only pointers? key == neighbor? */
-  if (0 == memcmp (&neighbor->hashPubKey, key, sizeof (struct 
GNUNET_HashCode)))
-  {
-    return GNUNET_YES;
-  }
-  cinfo->skip++;
-  return GNUNET_YES;
-}
-
-
-/**
- * @brief Get neighbor's Flow Control information.
- *
- * Retrieves the MeshTunnelChildInfo containing Flow Control data about a 
direct
- * descendant of the local node in a certain tunnel.
- * If the info is not yet there (recently created path), creates the data 
struct
- * and inserts it into the tunnel info, initialized to the current tunnel ACK
- * values.
- *
- * @param t Tunnel related.
- * @param peer Neighbor whose Flow Control info is needed.
- *
- * @return Neighbor's Flow Control info.
- */
-static struct MeshTunnelChildInfo *
-tunnel_get_neighbor_fc (struct MeshTunnel *t,
-                        const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshTunnelChildInfo *cinfo;
-
-  if (NULL == t->children_fc)
-    return NULL;
-
-  cinfo = GNUNET_CONTAINER_multihashmap_get (t->children_fc,
-                                             &peer->hashPubKey);
-  if (NULL == cinfo)
-  {
-    uint32_t delta;
-
-    cinfo = GNUNET_malloc (sizeof (struct MeshTunnelChildInfo));
-    cinfo->id = GNUNET_PEER_intern (peer);
-    cinfo->skip = t->fwd_pid;
-    cinfo->t = t;
-
-    delta = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE;
-    cinfo->fwd_ack = t->fwd_pid + delta;
-    cinfo->bck_ack = delta;
-    cinfo->bck_pid = -1;
-
-    cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK;
-    cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS;
-
-    cinfo->send_buffer =
-        GNUNET_malloc (sizeof(struct MeshPeerQueue *) * t->fwd_queue_max);
-
-    GNUNET_assert (GNUNET_OK ==
-      GNUNET_CONTAINER_multihashmap_put (t->children_fc,
-                                         &peer->hashPubKey,
-                                         cinfo,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
-  }
-  return cinfo;
-}
-
-
-/**
- * Get the Flow Control info of a client.
- * 
- * @param t Tunnel on which to look.
- * @param c Client whose ACK to get.
- * 
- * @return ACK value.
- */
-static struct MeshTunnelClientInfo *
-tunnel_get_client_fc (struct MeshTunnel *t,
-                      struct MeshClient *c)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->nclients; i++)
-  {
-    if (t->clients[i] != c)
-      continue;
-    return &t->clients_fc[i];
-  }
-  GNUNET_assert (0);
-  return NULL; // avoid compiler / coverity complaints
-}
-
-
-/**
- * Iterator to get the appropiate ACK value from all children nodes.
- *
- * @param cls Closue (tunnel).
- * @param id Id of the child node.
- */
-static void
-tunnel_get_child_fwd_ack (void *cls,
-                          GNUNET_PEER_Id id)
-{
-  struct GNUNET_PeerIdentity peer_id;
-  struct MeshTunnelChildInfo *cinfo;
-  struct MeshTunnelChildIteratorContext *ctx = cls;
-  struct MeshTunnel *t = ctx->t;
-  uint32_t ack;
-
-  GNUNET_PEER_resolve (id, &peer_id);
-  cinfo = tunnel_get_neighbor_fc (t, &peer_id);
-  ack = cinfo->fwd_ack;
-
-  ctx->nchildren++;
-  if (GNUNET_NO == ctx->init)
-  {
-    ctx->max_child_ack = ack;
-    ctx->init = GNUNET_YES;
-  }
-
-  if (GNUNET_YES == t->speed_min)
-  {
-    ctx->max_child_ack = ctx->max_child_ack > ack ? ack : ctx->max_child_ack;
-  }
-  else
-  {
-    ctx->max_child_ack = ctx->max_child_ack > ack ? ctx->max_child_ack : ack;
-  }
-
-}
-
-
-/**
- * Get the maximum PID allowed to transmit to any
- * tunnel child of the local peer, depending on the tunnel
- * buffering/speed settings.
- *
- * @param t Tunnel.
- *
- * @return Maximum PID allowed (uint32 MAX), -1LL if node has no children.
- */
-static int64_t
-tunnel_get_children_fwd_ack (struct MeshTunnel *t)
-{
-  struct MeshTunnelChildIteratorContext ctx;
-  ctx.t = t;
-  ctx.max_child_ack = 0;
-  ctx.nchildren = 0;
-  ctx.init = GNUNET_NO;
-  tree_iterate_children (t->tree, tunnel_get_child_fwd_ack, &ctx);
-
-  if (0 == ctx.nchildren)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-            "  tunnel has no children, no FWD ACK\n");
-    return -1LL;
-  }
-
-  if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ctx.max_child_ack, 
t->fwd_pid))
-    ctx.max_child_ack = t->fwd_pid + 1; // Might overflow, it's ok.
-
-  return (int64_t) ctx.max_child_ack;
-}
-
-
-/**
- * Set the FWD ACK value of a client in a particular tunnel.
- * 
- * @param t Tunnel affected.
- * @param c Client whose ACK to set.
- * @param ack ACK value.
- */
-static void
-tunnel_set_client_fwd_ack (struct MeshTunnel *t,
-                           struct MeshClient *c, 
-                           uint32_t ack)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->nclients; i++)
-  {
-    if (t->clients[i] != c)
-      continue;
-    t->clients_fc[i].fwd_ack = ack;
-    return;
-  }
-  GNUNET_break (0);
-}
-
-
-/**
- * Get the highest ACK value of all clients in a particular tunnel,
- * according to the buffering/speed settings.
- * 
- * @param t Tunnel on which to look.
- * 
- * @return Corresponding ACK value (max uint32_t).
- *         If no clients are suscribed, -1LL.
- */
-static int64_t
-tunnel_get_clients_fwd_ack (struct MeshTunnel *t)
-{
-  unsigned int i;
-  int64_t ack;
-
-  if (0 == t->nclients)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  tunnel has no clients, no FWD ACK\n");
-    return -1LL;
-  }
-
-  for (ack = -1LL, i = 0; i < t->nclients; i++)
-  {
-    if (-1LL == ack ||
-        (GNUNET_YES == t->speed_min &&
-         GNUNET_YES == GMC_is_pid_bigger (ack, t->clients_fc[i].fwd_ack)) ||
-        (GNUNET_NO == t->speed_min &&
-         GNUNET_YES == GMC_is_pid_bigger (t->clients_fc[i].fwd_ack, ack)))
-    {
-      ack = t->clients_fc[i].fwd_ack;
-    }
-  }
-
-  if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ack, t->fwd_pid))
-    ack = (uint32_t) t->fwd_pid + 1; // Might overflow, it's ok.
-
-  return (uint32_t) ack;
-}
-
-
-/**
- * Get the current fwd ack value for a tunnel, taking in account the tunnel
- * mode and the status of all children nodes.
- *
- * @param t Tunnel.
- *
- * @return Maximum PID allowed.
- */
-static uint32_t
-tunnel_get_fwd_ack (struct MeshTunnel *t)
-{
-  uint32_t ack;
-  uint32_t count;
-  uint32_t buffer_free;
-  int64_t child_ack;
-  int64_t client_ack;
-
-  count = t->fwd_pid - t->skip;
-  buffer_free = t->fwd_queue_max - t->fwd_queue_n;
-  child_ack = tunnel_get_children_fwd_ack (t);
-  client_ack = tunnel_get_clients_fwd_ack (t);
-  if (GNUNET_YES == t->nobuffer)
-  {
-    ack = count;
-    if (-1LL == child_ack)
-      child_ack = client_ack;
-    if (-1LL == child_ack)
-    {
-      GNUNET_break (0);
-      client_ack = child_ack = ack;
-    }
-  }
-  else
-  {
-    ack = count + buffer_free; // Overflow? OK!
-  }
-  if (-1LL == child_ack)
-  {
-    // Node has no children, child_ack AND core buffer are irrelevant.
-    if (-1LL == client_ack) // No children AND no clients? Not good!
-    {
-      GNUNET_STATISTICS_update (stats, "# mesh acks with no target",
-                                1, GNUNET_NO);
-
-    }
-    return (uint32_t) client_ack;
-  }
-  if (-1LL == client_ack)
-  {
-    client_ack = ack;
-  }
-  if (GNUNET_YES == t->speed_min)
-  {
-    ack = GMC_min_pid ((uint32_t) child_ack, ack);
-    ack = GMC_min_pid ((uint32_t) client_ack, ack);
-  }
-  else
-  {
-    ack = GMC_max_pid ((uint32_t) child_ack, ack);
-    ack = GMC_max_pid ((uint32_t) client_ack, ack);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "c %u, bf %u, ch %lld, cl %lld, ACK: %u\n",
-              count, buffer_free, child_ack, client_ack, ack);
-  return ack;
-}
-
-
-/**
- * Build a local ACK message and send it to a local client.
- * 
- * @param t Tunnel on which to send the ACK.
- * @param c Client to whom send the ACK.
- * @param ack Value of the ACK.
- */
-static void
-send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack)
-{
-  struct GNUNET_MESH_LocalAck msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest);
-  msg.max_pid = htonl (ack); 
-  GNUNET_SERVER_notification_context_unicast(nc,
-                                              c->handle,
-                                              &msg.header,
-                                              GNUNET_NO);
-}
-
-/**
- * Build an ACK message and queue it to send to the given peer.
- * 
- * @param t Tunnel on which to send the ACK.
- * @param peer Peer to whom send the ACK.
- * @param ack Value of the ACK.
- */
-static void
-send_ack (struct MeshTunnel *t, struct GNUNET_PeerIdentity *peer,  uint32_t 
ack)
-{
-  struct GNUNET_MESH_ACK msg;
-
-  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
-  msg.pid = htonl (ack);
-  msg.tid = htonl (t->id.tid);
-
-  send_prebuilt_message (&msg.header, peer, t);
-}
-
-
-/**
- * Notify a the owner of a tunnel about how many more
- * payload packages will we accept on a given tunnel.
- *
- * @param t Tunnel on which to send the ACK.
- */
-static void
-tunnel_send_client_fwd_ack (struct MeshTunnel *t)
-{
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending client FWD ACK on tunnel %X\n",
-              t->local_tid);
-
-  ack = tunnel_get_fwd_ack (t);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack);
-  if (t->last_fwd_ack == ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " same as last, not sending!\n");
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending!\n");
-  t->last_fwd_ack = ack;
-  send_local_ack (t, t->owner, ack);
-}
-
-
-/**
- * Send an ACK informing the predecessor about the available buffer space.
- * In case there is no predecessor, inform the owning client.
- * If buffering is off, send only on behalf of children or self if endpoint.
- * If buffering is on, send when sent to children and buffer space is free.
- * Note that although the name is fwd_ack, the FWD mean forward *traffic*,
- * the ACK itself goes "back" (towards root).
- * 
- * @param t Tunnel on which to send the ACK.
- * @param type Type of message that triggered the ACK transmission.
- */
-static void
-tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
-{
-  struct GNUNET_PeerIdentity id;
-  uint32_t ack;
-
-  if (NULL != t->owner)
-  {
-    tunnel_send_client_fwd_ack (t);
-    return;
-  }
-  /* Is it after unicast / multicast retransmission? */
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-    case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "ACK due to FWD DATA retransmission\n");
-      if (GNUNET_YES == t->nobuffer)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
-        return;
-      }
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      t->force_ack = GNUNET_YES;
-      break;
-    default:
-      GNUNET_break (0);
-  }
-
-  /* Check if we need to transmit the ACK */
-  if (t->fwd_queue_max > t->fwd_queue_n * 4 &&
-      GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid) &&
-      GNUNET_NO == t->force_ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  t->qmax: %u, t->qn: %u\n",
-                t->fwd_queue_max, t->fwd_queue_n);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  t->pid: %u, t->ack: %u\n",
-                t->fwd_pid, t->last_fwd_ack);
-    return;
-  }
-
-  /* Ok, ACK might be necessary, what PID to ACK? */
-  ack = tunnel_get_fwd_ack (t);
-
-  /* If speed_min and not all children have ack'd, dont send yet */
-  if (ack == t->last_fwd_ack && GNUNET_NO == t->force_ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not ready\n");
-    return;
-  }
-
-  t->last_fwd_ack = ack;
-  GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
-  send_ack (t, &id, ack);
-  debug_fwd_ack++;
-  t->force_ack = GNUNET_NO;
-}
-
-
-/**
- * Iterator to send a child node a BCK ACK to allow him to send more
- * to_origin data.
- *
- * @param cls Closure (tunnel).
- * @param id Id of the child node.
- */
-static void
-tunnel_send_child_bck_ack (void *cls,
-                           GNUNET_PEER_Id id)
-{
-  struct MeshTunnel *t = cls;
-  struct MeshTunnelChildInfo *cinfo;
-  struct GNUNET_PeerIdentity peer;
-  uint32_t ack;
-
-  GNUNET_PEER_resolve (id, &peer);
-  cinfo = tunnel_get_neighbor_fc (t, &peer);
-  ack = cinfo->bck_pid + t->bck_queue_max - t->bck_queue_n;
-
-  if (cinfo->bck_ack == ack && GNUNET_NO == t->force_ack)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "    Not sending ACK, not needed\n");
-    return;
-  }
-  cinfo->bck_ack = ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "    Sending BCK ACK %u (last sent: %u)\n",
-              ack, cinfo->bck_ack);
-  send_ack (t, &peer, ack);
-}
-
-
-/**
- * @brief Send BCK ACKs to clients to allow them more to_origin traffic
- * 
- * Iterates over all clients and sends BCK ACKs to the ones that need it.
- *
- * FIXME fc: what happens if we have 2 clients but q_size is 1?
- *           - implement a size 1 buffer in each client_fc AND children_fc
- *           to hold at least 1 message per "child".
- *             problem: violates no buffer policy
- *           - ack 0 and make "children" poll for transmission slots
- *             problem: big overhead, extra latency even in low traffic
- *                      settings
- * 
- * @param t Tunnel on which to send the BCK ACKs.
- */
-static void
-tunnel_send_clients_bck_ack (struct MeshTunnel *t)
-{
-  unsigned int i;
-  unsigned int tunnel_delta;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Sending BCK ACK to clients\n");
-
-  tunnel_delta = t->bck_queue_max - t->bck_queue_n;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   tunnel delta: %u\n", tunnel_delta);
-
-  /* Find client whom to allow to send to origin (with lowest buffer space) */
-  for (i = 0; i < t->nclients; i++)
-  {
-    struct MeshTunnelClientInfo *clinfo;
-    unsigned int delta;
-
-    clinfo = &t->clients_fc[i];
-    delta = clinfo->bck_ack - clinfo->bck_pid;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    client %u delta: %u\n",
-         t->clients[i]->id, delta);
-
-    if ((GNUNET_NO == t->nobuffer && tunnel_delta > delta) ||
-        (GNUNET_YES == t->nobuffer && 0 == delta))
-    {
-      uint32_t ack;
-
-      ack = clinfo->bck_pid;
-      ack += t->nobuffer ? 1 : tunnel_delta;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "    sending ack to client %u: %u\n",
-                  t->clients[i]->id, ack);
-      send_local_ack (t, t->clients[i], ack);
-      clinfo->bck_ack = ack;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "    not sending ack to client %u (td %u, d %u)\n",
-                  t->clients[i]->id, tunnel_delta, delta);
-    }
-  }
-}
-
-
-/**
- * Send an ACK informing the children nodes and destination clients about
- * the available buffer space.
- * If buffering is off, send only on behalf of root (can be self).
- * If buffering is on, send when sent to predecessor and buffer space is free.
- * Note that although the name is bck_ack, the BCK mean backwards *traffic*,
- * the ACK itself goes "forward" (towards children/clients).
- * 
- * @param t Tunnel on which to send the ACK.
- * @param type Type of message that triggered the ACK transmission.
- */
-static void
-tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending BCK ACK on tunnel %u [%u] due to %s\n",
-              t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type));
-  /* Is it after data to_origin retransmission? */
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      if (GNUNET_YES == t->nobuffer)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "    Not sending ACK, nobuffer\n");
-        return;
-      }
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_ACK:
-    case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
-      break;
-    case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      t->force_ack = GNUNET_YES;
-      break;
-    default:
-      GNUNET_break (0);
-  }
-
-  tunnel_send_clients_bck_ack (t);
-  tree_iterate_children (t->tree, &tunnel_send_child_bck_ack, t);
-  t->force_ack = GNUNET_NO;
-}
-
-
-/**
- * @brief Re-initiate traffic to this peer if necessary.
- *
- * Check if there is traffic queued towards this peer
- * and the core transmit handle is NULL (traffic was stalled).
- * If so, call core tmt rdy.
- *
- * @param cls Closure (unused)
- * @param peer_id Short ID of peer to which initiate traffic.
- */
-static void
-peer_unlock_queue(void *cls, GNUNET_PEER_Id peer_id)
-{
-  struct MeshPeerInfo *peer;
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerQueue *q;
-  size_t size;
-
-  peer = peer_info_get_short(peer_id);
-  if (NULL != peer->core_transmit)
-    return;
-
-  q = queue_get_next(peer);
-  if (NULL == q)
-  {
-    /* Might br multicast traffic already sent to this particular peer but
-     * not to other children in this tunnel.
-     * This way t->queue_n would be > 0 but the queue of this particular peer
-     * would be empty.
-     */
-    return;
-  }
-  size = q->size;
-  GNUNET_PEER_resolve (peer->id, &id);
-  peer->core_transmit =
-        GNUNET_CORE_notify_transmit_ready(core_handle,
-                                          0,
-                                          0,
-                                          GNUNET_TIME_UNIT_FOREVER_REL,
-                                          &id,
-                                          size,
-                                          &queue_send,
-                                          peer);
-        return;
-}
-
-
-/**
- * @brief Allow transmission of FWD traffic on this tunnel
- *
- * Check if there is traffic queued towards any children
- * and the core transmit handle is NULL, and if so, call core tmt rdy.
- *
- * @param t Tunnel on which to unlock FWD traffic.
- */
-static void
-tunnel_unlock_fwd_queues (struct MeshTunnel *t)
-{
-  if (0 == t->fwd_queue_n)
-    return;
-
-  tree_iterate_children (t->tree, &peer_unlock_queue, NULL);
-}
-
-
-/**
- * @brief Allow transmission of BCK traffic on this tunnel
- *
- * Check if there is traffic queued towards the root of the tree
- * and the core transmit handle is NULL, and if so, call core tmt rdy.
- *
- * @param t Tunnel on which to unlock BCK traffic.
- */
-static void
-tunnel_unlock_bck_queue (struct MeshTunnel *t)
-{
-  if (0 == t->bck_queue_n)
-    return;
-
-  peer_unlock_queue(NULL, tree_get_predecessor(t->tree));
-}
-
-
-/**
- * Send a message to all peers in this tunnel that the tunnel is no longer
- * valid.
- *
- * @param t The tunnel whose peers to notify.
- * @param parent ID of the parent, in case the tree is already destroyed.
- */
-static void
-tunnel_send_destroy (struct MeshTunnel *t, GNUNET_PEER_Id parent)
-{
-  struct GNUNET_MESH_TunnelDestroy msg;
-  struct GNUNET_PeerIdentity id;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);
-  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
-  msg.tid = htonl (t->id.tid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  sending tunnel destroy for tunnel: %s [%X]\n",
-              GNUNET_i2s (&msg.oid), t->id.tid);
-  if (tree_count_children(t->tree) > 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  sending multicast to children\n");
-    tunnel_send_multicast (t, &msg.header);
-  }
-  if (0 == parent)
-    parent = tree_get_predecessor (t->tree);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  parent: %u\n", parent);
-  if (0 == parent)
-    return;
-
-  GNUNET_PEER_resolve (parent, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  sending back to %s\n",
-              GNUNET_i2s (&id));
-  send_prebuilt_message (&msg.header, &id, t);
-}
-
-
-/**
- * Cancel all transmissions towards a neighbor that belong to a certain tunnel.
- *
- * @param cls Closure (Tunnel which to cancel).
- * @param neighbor_id Short ID of the neighbor to whom cancel the 
transmissions.
- */
-static void
-tunnel_cancel_queues (void *cls, GNUNET_PEER_Id neighbor_id)
-{
-  struct MeshTunnel *t = cls;
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerQueue *pq;
-  struct MeshPeerQueue *next;
-
-  peer_info = peer_info_get_short (neighbor_id);
-  for (pq = peer_info->queue_head; NULL != pq; pq = next)
-  {
-    next = pq->next;
-    if (pq->tunnel == t)
-    {
-      if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST == pq->type ||
-          GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
-          GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type)
-      {
-        // Should have been removed on destroy children
-        GNUNET_break (0);
-      }
-      queue_destroy (pq, GNUNET_YES);
-    }
-  }
-  if (NULL == peer_info->queue_head && NULL != peer_info->core_transmit)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel(peer_info->core_transmit);
-    peer_info->core_transmit = NULL;
-  }
-}
-
-/**
- * Destroy the tunnel and free any allocated resources linked to it.
- *
- * @param t the tunnel to destroy
- *
- * @return GNUNET_OK on success
- */
-static int
-tunnel_destroy (struct MeshTunnel *t)
-{
-  struct MeshClient *c;
-  struct GNUNET_HashCode hash;
-  unsigned int i;
-  int r;
-
-  if (NULL == t)
-    return GNUNET_OK;
-
-  r = GNUNET_OK;
-  c = t->owner;
-#if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (t->id.oid, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s [%x]\n",
-                GNUNET_i2s (&id), t->id.tid);
-    if (NULL != c)
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-  }
-#endif
-
-  GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
-  if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
-  {
-    GNUNET_break (0);
-    r = GNUNET_SYSERR;
-  }
-
-  if (NULL != c)
-  {
-    GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
-    if (GNUNET_YES !=
-        GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
-    {
-      GNUNET_break (0);
-      r = GNUNET_SYSERR;
-    }
-  }
-
-  GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
-  for (i = 0; i < t->nclients; i++)
-  {
-    c = t->clients[i];
-    if (GNUNET_YES !=
-          GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
-    {
-      GNUNET_break (0);
-      r = GNUNET_SYSERR;
-    }
-  }
-  for (i = 0; i < t->nignore; i++)
-  {
-    c = t->ignore[i];
-    if (GNUNET_YES !=
-          GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, &hash, t))
-    {
-      GNUNET_break (0);
-      r = GNUNET_SYSERR;
-    }
-  }
-
-  (void) GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t);
-  GNUNET_free_non_null (t->clients);
-  GNUNET_free_non_null (t->ignore);
-  GNUNET_free_non_null (t->clients_fc);
-
-  if (NULL != t->peers)
-  {
-    GNUNET_CONTAINER_multihashmap_iterate (t->peers, &peer_info_delete_tunnel,
-                                           t);
-    GNUNET_CONTAINER_multihashmap_destroy (t->peers);
-  }
-
-  GNUNET_CONTAINER_multihashmap_iterate (t->children_fc,
-                                         &tunnel_destroy_child,
-                                         t);
-  GNUNET_CONTAINER_multihashmap_destroy (t->children_fc);
-  t->children_fc = NULL;
-
-  tree_iterate_children (t->tree, &tunnel_cancel_queues, t);
-  tree_destroy (t->tree);
-
-  if (NULL != t->regex_search)
-    GNUNET_REGEX_search_cancel (t->regex_search->search_handle);
-  if (NULL != t->dht_get_type)
-    GNUNET_DHT_get_stop (t->dht_get_type);
-  if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
-    GNUNET_SCHEDULER_cancel (t->timeout_task);
-  if (GNUNET_SCHEDULER_NO_TASK != t->path_refresh_task)
-    GNUNET_SCHEDULER_cancel (t->path_refresh_task);
-
-  n_tunnels--;
-  GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
-  GNUNET_free (t);
-  return r;
-}
-
-#define TUNNEL_DESTROY_EMPTY_TIME GNUNET_TIME_UNIT_MILLISECONDS
-
-/**
- * Tunnel is empty: destroy it.
- * 
- * @param cls Closure (Tunnel).
- * @param tc TaskContext. 
- */
-static void
-tunnel_destroy_empty_delayed (void *cls,
-                              const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshTunnel *t = cls;
-
-  t->delayed_destroy = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  if (0 != t->nclients ||
-      0 != tree_count_children (t->tree))
-    return;
-
-  #if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (t->id.oid, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "executing destruction of empty tunnel %s [%X]\n",
-                GNUNET_i2s (&id), t->id.tid);
-  }
-  #endif
-
-  tunnel_send_destroy (t, 0);
-  if (0 == t->pending_messages)
-    tunnel_destroy (t);
-  else
-    t->destroy = GNUNET_YES;
-}
-
-
-/**
- * Schedule tunnel destruction if is empty and no new traffic comes in a time.
- * 
- * @param t Tunnel to destroy if empty.
- */
-static void
-tunnel_destroy_empty (struct MeshTunnel *t)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != t->delayed_destroy || 
-      0 != t->nclients ||
-      0 != tree_count_children (t->tree))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%u %u %u\n",
-                t->delayed_destroy, t->nclients, tree_count_children(t->tree));
-    return;
-  }
-
-  #if MESH_DEBUG
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (t->id.oid, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "scheduling destruction of empty tunnel %s [%X]\n",
-                GNUNET_i2s (&id), t->id.tid);
-  }
-  #endif
-
-  t->delayed_destroy =
-      GNUNET_SCHEDULER_add_delayed (TUNNEL_DESTROY_EMPTY_TIME,
-                                    &tunnel_destroy_empty_delayed,
-                                    t);
-}
-
-
-/**
- * Create a new tunnel
- * 
- * @param owner Who is the owner of the tunnel (short ID).
- * @param tid Tunnel Number of the tunnel.
- * @param client Clients that owns the tunnel, NULL for foreign tunnels.
- * @param local Tunnel Number for the tunnel, for the client point of view.
- * 
- * @return A new initialized tunnel. NULL on error.
- */
-static struct MeshTunnel *
-tunnel_new (GNUNET_PEER_Id owner,
-            MESH_TunnelNumber tid,
-            struct MeshClient *client,
-            MESH_TunnelNumber local)
-{
-  struct MeshTunnel *t;
-  struct GNUNET_HashCode hash;
-
-  if (n_tunnels >= max_tunnels && NULL == client)
-    return NULL;
-
-  t = GNUNET_malloc (sizeof (struct MeshTunnel));
-  t->id.oid = owner;
-  t->id.tid = tid;
-  t->fwd_queue_max = (max_msgs_queue / max_tunnels) + 1;
-  t->bck_queue_max = t->fwd_queue_max;
-  t->tree = tree_new (owner);
-  t->owner = client;
-  t->fwd_pid = (uint32_t) -1; // Next (expected) = 0
-  t->bck_pid = (uint32_t) -1; // Next (expected) = 0
-  t->bck_ack = INITIAL_WINDOW_SIZE - 1;
-  t->last_fwd_ack = INITIAL_WINDOW_SIZE - 1;
-  t->local_tid = local;
-  t->children_fc = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
-  n_tunnels++;
-  GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO);
-
-  GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
-  if (GNUNET_OK !=
-      GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
-  {
-    GNUNET_break (0);
-    tunnel_destroy (t);
-    if (NULL != client)
-    {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
-    }
-    return NULL;
-  }
-
-  if (NULL != client)
-  {
-    GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
-    if (GNUNET_OK !=
-        GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t,
-                                          
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
-    {
-      tunnel_destroy (t);
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
-      return NULL;
-    }
-  }
-
-  return t;
-}
-
-/**
- * Callback when removing children from a tunnel tree. Notify owner.
- *
- * @param cls Closure (tunnel).
- * @param peer_id Short ID of the peer deleted.
- */
-void
-tunnel_child_removed (void *cls, GNUNET_PEER_Id peer_id)
-{
-  struct MeshTunnel *t = cls;
-
-  client_notify_peer_disconnected (t->owner, t, peer_id);
-}
-
-/**
- * Removes an explicit path from a tunnel, freeing all intermediate nodes
- * that are no longer needed, as well as nodes of no longer reachable peers.
- * The tunnel itself is also destoyed if results in a remote empty tunnel.
- *
- * @param t Tunnel from which to remove the path.
- * @param peer Short id of the peer which should be removed.
- */
-static void
-tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer)
-{
-  int r;
-
-  r = tree_del_peer (t->tree, peer, &tunnel_child_removed, t);
-  if (GNUNET_NO == r)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Tunnel %u [%u] has no more nodes\n",
-                t->id.oid, t->id.tid);
-  }
-}
-
-
-/**
- * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
- * client when the client disconnects. If the client is not the owner, the
- * owner will get notified if no more clients are in the tunnel and the client
- * get removed from the tunnel's list.
- *
- * @param cls closure (client that is disconnecting)
- * @param key the hash of the local tunnel id (used to access the hashmap)
- * @param value the value stored at the key (tunnel to destroy)
- *
- * @return GNUNET_OK, keep iterating.
- */
-static int
-tunnel_destroy_iterator (void *cls,
-                         const struct GNUNET_HashCode * key,
-                         void *value)
-{
-  struct MeshTunnel *t = value;
-  struct MeshClient *c = cls;
-
-  send_client_tunnel_disconnect (t, c);
-  if (c != t->owner)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %u is destination.\n", c->id);
-    tunnel_delete_client (t, c);
-    client_delete_tunnel (c, t);
-    tunnel_destroy_empty (t);
-    return GNUNET_OK;
-  }
-  tunnel_send_destroy (t, 0);
-  t->owner = NULL;
-  t->destroy = GNUNET_YES;
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Timeout function, destroys tunnel if called
- *
- * @param cls Closure (tunnel to destroy).
- * @param tc TaskContext
- */
-static void
-tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshTunnel *t = cls;
-  struct GNUNET_PeerIdentity id;
-
-  t->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  GNUNET_PEER_resolve(t->id.oid, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Tunnel %s [%X] timed out. Destroying.\n",
-              GNUNET_i2s(&id), t->id.tid);
-  send_clients_tunnel_destroy (t);
-  tunnel_destroy (t);
-}
-
-/**
- * Resets the tunnel timeout. Starts it if no timeout was running.
- *
- * @param t Tunnel whose timeout to reset.
- *
- * TODO use heap to improve efficiency of scheduler.
- */
-static void
-tunnel_reset_timeout (struct MeshTunnel *t)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
-    GNUNET_SCHEDULER_cancel (t->timeout_task);
-  t->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (refresh_path_time, 4), &tunnel_timeout, 
t);
-}
-
-
-/******************************************************************************/
-/****************      MESH NETWORK HANDLER HELPERS     
***********************/
-/******************************************************************************/
-
-/**
- * Function to send a create path packet to a peer.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-send_core_path_create (void *cls, size_t size, void *buf)
-{
-  struct MeshPathInfo *info = cls;
-  struct GNUNET_MESH_ManipulatePath *msg;
-  struct GNUNET_PeerIdentity *peer_ptr;
-  struct MeshTunnel *t = info->t;
-  struct MeshPeerPath *p = info->path;
-  size_t size_needed;
-  uint32_t opt;
-  int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n");
-  size_needed =
-      sizeof (struct GNUNET_MESH_ManipulatePath) +
-      p->length * sizeof (struct GNUNET_PeerIdentity);
-
-  if (size < size_needed || NULL == buf)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg = (struct GNUNET_MESH_ManipulatePath *) buf;
-  msg->header.size = htons (size_needed);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
-  msg->tid = ntohl (t->id.tid);
-
-  opt = 0;
-  if (GNUNET_YES == t->speed_min)
-    opt |= MESH_TUNNEL_OPT_SPEED_MIN;
-  if (GNUNET_YES == t->nobuffer)
-    opt |= MESH_TUNNEL_OPT_NOBUFFER;
-  msg->opt = htonl(opt);
-  msg->reserved = 0;
-
-  peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
-  for (i = 0; i < p->length; i++)
-  {
-    GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
-  }
-
-  path_destroy (p);
-  GNUNET_free (info);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "CREATE PATH (%u bytes long) sent!\n", size_needed);
-  return size_needed;
-}
-
-
-/**
- * Fill the core buffer 
- *
- * @param cls closure (data itself)
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- *
- * @return number of bytes written to buf
- */
-static size_t
-send_core_data_multicast (void *cls, size_t size, void *buf)
-{
-  struct MeshTransmissionDescriptor *info = cls;
-  size_t total_size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Multicast callback.\n");
-  GNUNET_assert (NULL != info);
-  GNUNET_assert (NULL != info->peer);
-  total_size = info->mesh_data->data_len;
-  GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
-
-  if (total_size > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " copying data...\n");
-  memcpy (buf, info->mesh_data->data, total_size);
-#if MESH_DEBUG
-  {
-    struct GNUNET_MESH_Multicast *mc;
-    struct GNUNET_MessageHeader *mh;
-
-    mh = buf;
-    if (ntohs (mh->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
-    {
-      mc = (struct GNUNET_MESH_Multicast *) mh;
-      mh = (struct GNUNET_MessageHeader *) &mc[1];
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  " multicast, payload type %s\n",
-                  GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  " multicast, payload size %u\n", ntohs (mh->size));
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type %s\n",
-                  GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-    }
-  }
-#endif
-  data_descriptor_decrement_rc (info->mesh_data);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "freeing info...\n");
-  GNUNET_free (info);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "return %u\n", total_size);
-  return total_size;
-}
-
-
-/**
- * Creates a path ack message in buf and frees all unused resources.
- *
- * @param cls closure (MeshTransmissionDescriptor)
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-send_core_path_ack (void *cls, size_t size, void *buf)
-{
-  struct MeshTransmissionDescriptor *info = cls;
-  struct GNUNET_MESH_PathACK *msg = buf;
-
-  GNUNET_assert (NULL != info);
-  if (sizeof (struct GNUNET_MESH_PathACK) > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
-  GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
-  msg->tid = htonl (info->origin->tid);
-  msg->peer_id = my_full_id;
-
-  GNUNET_free (info);
-  /* TODO add signature */
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n");
-  return sizeof (struct GNUNET_MESH_PathACK);
-}
-
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- */
-static void
-queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
-{
-  struct MeshTransmissionDescriptor *dd;
-  struct MeshPathInfo *path_info;
-  struct MeshTunnelChildInfo *cinfo;
-  struct GNUNET_PeerIdentity id;
-  unsigned int i;
-  unsigned int max;
-
-  if (GNUNET_YES == clear_cls)
-  {
-    switch (queue->type)
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO, "   cancelling TUNNEL_DESTROY\n");
-        GNUNET_break (GNUNET_YES == queue->tunnel->destroy);
-        /* fall through */
-      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      case GNUNET_MESSAGE_TYPE_MESH_ACK:
-      case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "   prebuilt message\n");
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "   type %s\n",
-                    GNUNET_MESH_DEBUG_M2S(queue->type));
-        dd = queue->cls;
-        data_descriptor_decrement_rc (dd->mesh_data);
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type create path\n");
-        path_info = queue->cls;
-        path_destroy (path_info->path);
-        break;
-      default:
-        GNUNET_break (0);
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "   type %s unknown!\n",
-                    GNUNET_MESH_DEBUG_M2S(queue->type));
-    }
-    GNUNET_free_non_null (queue->cls);
-  }
-  GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head,
-                               queue->peer->queue_tail,
-                               queue);
-
-  /* Delete from child_fc in the appropiate tunnel */
-  max = queue->tunnel->fwd_queue_max;
-  GNUNET_PEER_resolve (queue->peer->id, &id);
-  cinfo = tunnel_get_neighbor_fc (queue->tunnel, &id);
-  if (NULL != cinfo)
-  {
-    for (i = 0; i < cinfo->send_buffer_n; i++)
-    {
-      unsigned int i2;
-      i2 = (cinfo->send_buffer_start + i) % max;
-      if (cinfo->send_buffer[i2] == queue)
-      {
-        /* Found corresponding entry in the send_buffer. Move all others back. 
*/
-        unsigned int j;
-        unsigned int j2;
-        unsigned int j3;
-
-        for (j = i, j2 = 0, j3 = 0; j < cinfo->send_buffer_n - 1; j++)
-        {
-          j2 = (cinfo->send_buffer_start + j) % max;
-          j3 = (cinfo->send_buffer_start + j + 1) % max;
-          cinfo->send_buffer[j2] = cinfo->send_buffer[j3];
-        }
-
-        cinfo->send_buffer[j3] = NULL;
-        cinfo->send_buffer_n--;
-      }
-    }
-  }
-
-  GNUNET_free (queue);
-}
-
-
-/**
- * @brief Get the next transmittable message from the queue.
- *
- * This will be the head, except in the case of being a data packet
- * not allowed by the destination peer.
- *
- * @param peer Destination peer.
- *
- * @return The next viable MeshPeerQueue element to send to that peer.
- *         NULL when there are no transmittable messages.
- */
-struct MeshPeerQueue *
-queue_get_next (const struct MeshPeerInfo *peer)
-{
-  struct MeshPeerQueue *q;
-  struct MeshTunnel *t;
-  struct MeshTransmissionDescriptor *info;
-  struct MeshTunnelChildInfo *cinfo;
-  struct GNUNET_MESH_Unicast *ucast;
-  struct GNUNET_MESH_ToOrigin *to_orig;
-  struct GNUNET_MESH_Multicast *mcast;
-  struct GNUNET_PeerIdentity id;
-  uint32_t pid;
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   selecting message\n");
-  for (q = peer->queue_head; NULL != q; q = q->next)
-  {
-    t = q->tunnel;
-    info = q->cls;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "*********     %s\n",
-                GNUNET_MESH_DEBUG_M2S(q->type));
-    switch (q->type)
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-        ucast = (struct GNUNET_MESH_Unicast *) info->mesh_data->data;
-        pid = ntohl (ucast->pid);
-        GNUNET_PEER_resolve (info->peer->id, &id);
-        cinfo = tunnel_get_neighbor_fc(t, &id);
-        ack = cinfo->fwd_ack;
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-        to_orig = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data;
-        pid = ntohl (to_orig->pid);
-        ack = t->bck_ack;
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-        mcast = (struct GNUNET_MESH_Multicast *) info->mesh_data->data;
-        if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST != ntohs(mcast->header.type)) 
-        {
-          // Not a multicast payload: multicast control traffic (destroy, etc)
-          return q;
-        }
-        pid = ntohl (mcast->pid);
-        GNUNET_PEER_resolve (info->peer->id, &id);
-        cinfo = tunnel_get_neighbor_fc(t, &id);
-        ack = cinfo->fwd_ack;
-        break;
-      default:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "*********   OK!\n");
-        return q;
-    }
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "*********     ACK: %u, PID: %u\n",
-                    ack, pid);
-    if (GNUNET_NO == GMC_is_pid_bigger(pid, ack))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*********   OK!\n");
-      return q;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*********     NEXT!\n");
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "*********   nothing found\n");
-  return NULL;
-}
-
-
-/**
-  * Core callback to write a queued packet to core buffer
-  *
-  * @param cls Closure (peer info).
-  * @param size Number of bytes available in buf.
-  * @param buf Where the to write the message.
-  *
-  * @return number of bytes written to buf
-  */
-static size_t
-queue_send (void *cls, size_t size, void *buf)
-{
-    struct MeshPeerInfo *peer = cls;
-    struct GNUNET_MessageHeader *msg;
-    struct MeshPeerQueue *queue;
-    struct MeshTunnel *t;
-    struct MeshTunnelChildInfo *cinfo;
-    struct GNUNET_PeerIdentity dst_id;
-    size_t data_size;
-
-    peer->core_transmit = NULL;
-    cinfo = NULL;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* Queue send\n");
-    queue = queue_get_next (peer);
-
-    /* Queue has no internal mesh traffic nor sendable payload */
-    if (NULL == queue)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   not ready, return\n");
-      if (NULL == peer->queue_head)
-        GNUNET_break (0); // Should've been canceled
-      return 0;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   not empty\n");
-
-    GNUNET_PEER_resolve (peer->id, &dst_id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "*********   towards %s\n",
-                GNUNET_i2s(&dst_id));
-    /* Check if buffer size is enough for the message */
-    if (queue->size > size)
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "*********   not enough room, reissue\n");
-        peer->core_transmit =
-            GNUNET_CORE_notify_transmit_ready (core_handle,
-                                               0,
-                                               0,
-                                               GNUNET_TIME_UNIT_FOREVER_REL,
-                                               &dst_id,
-                                               queue->size,
-                                               &queue_send,
-                                               peer);
-        return 0;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   size ok\n");
-
-    t = queue->tunnel;
-    GNUNET_assert (0 < t->pending_messages);
-    t->pending_messages--;
-    if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type)
-    {
-      t->fwd_queue_n--;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "*********   unicast: t->q (%u/%u)\n",
-                  t->fwd_queue_n, t->fwd_queue_max);
-    }
-    else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type)
-    {
-      t->bck_queue_n--;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   to origin\n");
-    }
-
-    /* Fill buf */
-    switch (queue->type)
-    {
-      case 0:
-      case GNUNET_MESSAGE_TYPE_MESH_ACK:
-      case GNUNET_MESSAGE_TYPE_MESH_POLL:
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN:
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY:
-      case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "*********   raw: %s\n",
-                    GNUNET_MESH_DEBUG_M2S (queue->type));
-        /* Fall through */
-      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-        data_size = send_core_data_raw (queue->cls, size, buf);
-        msg = (struct GNUNET_MessageHeader *) buf;
-        switch (ntohs (msg->type)) // Type of preconstructed message
-        {
-          case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-            tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
-            break;
-          case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-            tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
-            break;
-          default:
-              break;
-        }
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   multicast\n");
-        {
-          struct MeshTransmissionDescriptor *info = queue->cls;
-
-          if ((1 == info->mesh_data->reference_counter
-              && GNUNET_YES == t->speed_min)
-              ||
-              (info->mesh_data->total_out == info->mesh_data->reference_counter
-              && GNUNET_NO == t->speed_min))
-          {
-            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                        "*********   considered sent\n");
-            t->fwd_queue_n--;
-          }
-          else
-          {
-            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                        "*********   NOT considered sent yet\n");
-            t->pending_messages++;
-          }
-        }
-        data_size = send_core_data_multicast(queue->cls, size, buf);
-        tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   path create\n");
-        data_size = send_core_path_create (queue->cls, size, buf);
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   path ack\n");
-        data_size = send_core_path_ack (queue->cls, size, buf);
-        break;
-      case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   path keepalive\n");
-        data_size = send_core_data_multicast (queue->cls, size, buf);
-        break;
-      default:
-        GNUNET_break (0);
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "*********   type unknown: %u\n",
-                    queue->type);
-        data_size = 0;
-    }
-    switch (queue->type)
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-      case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-        cinfo = tunnel_get_neighbor_fc (t, &dst_id);
-        if (cinfo->send_buffer[cinfo->send_buffer_start] != queue)
-        {
-          GNUNET_break (0);
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "at pos %u (%p) != %p\n",
-                      cinfo->send_buffer_start,
-                      cinfo->send_buffer[cinfo->send_buffer_start],
-                      queue);
-        }
-        if (cinfo->send_buffer_n > 0)
-        {
-          cinfo->send_buffer[cinfo->send_buffer_start] = NULL;
-          cinfo->send_buffer_n--;
-          cinfo->send_buffer_start++;
-          cinfo->send_buffer_start %= t->fwd_queue_max;
-        }
-        else
-        {
-          GNUNET_break (0);
-        }
-        break;
-      default:
-        break;
-    }
-
-    /* Free queue, but cls was freed by send_core_* */
-    queue_destroy (queue, GNUNET_NO);
-
-    if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********  destroying tunnel!\n");
-      tunnel_destroy (t);
-    }
-
-    /* If more data in queue, send next */
-    queue = queue_get_next(peer);
-    if (NULL != queue)
-    {
-        struct GNUNET_PeerIdentity id;
-
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   more data!\n");
-        GNUNET_PEER_resolve (peer->id, &id);
-        peer->core_transmit =
-            GNUNET_CORE_notify_transmit_ready(core_handle,
-                                              0,
-                                              0,
-                                              GNUNET_TIME_UNIT_FOREVER_REL,
-                                              &id,
-                                              queue->size,
-                                              &queue_send,
-                                              peer);
-    }
-    else
-    {
-      if (NULL != peer->queue_head)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "*********   %s stalled\n",
-                    GNUNET_i2s(&my_full_id));
-        if (NULL == cinfo)
-          cinfo = tunnel_get_neighbor_fc (t, &dst_id);
-        // FIXME unify bck/fwd structures, bck does not have cinfo right now
-        if (NULL != cinfo && GNUNET_SCHEDULER_NO_TASK == cinfo->fc_poll)
-        {
-          cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time,
-                                                         &tunnel_poll, cinfo);
-        }
-      }
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   return %d\n", data_size);
-    return data_size;
-}
-
-
-/**
- * @brief Queue and pass message to core when possible.
- * 
- * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status
- * and accounts for it. In case the queue is full, the message is dropped and
- * a break issued.
- * 
- * Otherwise, message is treated as internal and allowed to go regardless of 
- * queue status.
- *
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- *            build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @param dst Neighbor to send message to.
- * @param t Tunnel this message belongs to.
- */
-static void
-queue_add (void *cls, uint16_t type, size_t size,
-           struct MeshPeerInfo *dst, struct MeshTunnel *t)
-{
-  struct MeshPeerQueue *queue;
-  struct MeshTunnelChildInfo *cinfo;
-  struct GNUNET_PeerIdentity id;
-  unsigned int *max;
-  unsigned int *n;
-  unsigned int i;
-
-  n = NULL;
-  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type ||
-      GNUNET_MESSAGE_TYPE_MESH_MULTICAST == type)
-  {
-    n = &t->fwd_queue_n;
-    max = &t->fwd_queue_max;
-  }
-  else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
-  {
-    n = &t->bck_queue_n;
-    max = &t->bck_queue_max;
-  }
-  if (NULL != n)
-  {
-    if (*n >= *max)
-    {
-      GNUNET_break(0);
-      GNUNET_STATISTICS_update(stats,
-                               "# messages dropped (buffer full)",
-                               1, GNUNET_NO);
-      return; // Drop message
-    }
-    (*n)++;
-  }
-  queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
-  queue->cls = cls;
-  queue->type = type;
-  queue->size = size;
-  queue->peer = dst;
-  queue->tunnel = t;
-  GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
-  GNUNET_PEER_resolve (dst->id, &id);
-  if (NULL == dst->core_transmit)
-  {
-      dst->core_transmit =
-          GNUNET_CORE_notify_transmit_ready (core_handle,
-                                             0,
-                                             0,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &id,
-                                             size,
-                                             &queue_send,
-                                             dst);
-  }
-  t->pending_messages++;
-  if (NULL == n) // Is this internal mesh traffic?
-    return;
-
-  // It's payload, keep track of buffer per peer.
-  cinfo = tunnel_get_neighbor_fc(t, &id);
-  i = (cinfo->send_buffer_start + cinfo->send_buffer_n) % t->fwd_queue_max;
-  if (NULL != cinfo->send_buffer[i])
-  {
-    GNUNET_break (cinfo->send_buffer_n == t->fwd_queue_max); // aka i == start
-    queue_destroy (cinfo->send_buffer[cinfo->send_buffer_start], GNUNET_YES);
-    cinfo->send_buffer_start++;
-    cinfo->send_buffer_start %= t->fwd_queue_max;
-  }
-  else
-  {
-    cinfo->send_buffer_n++;
-  }
-  cinfo->send_buffer[i] = queue;
-  if (cinfo->send_buffer_n > t->fwd_queue_max)
-  {
-    GNUNET_break (0);
-    cinfo->send_buffer_n = t->fwd_queue_max;
-  }
-}
-
-
-/******************************************************************************/
-/********************      MESH NETWORK HANDLERS     
**************************/
-/******************************************************************************/
-
-
-/**
- * Core handler for path creation
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
-                         const struct GNUNET_MessageHeader *message)
-{
-  unsigned int own_pos;
-  uint16_t size;
-  uint16_t i;
-  MESH_TunnelNumber tid;
-  struct GNUNET_MESH_ManipulatePath *msg;
-  struct GNUNET_PeerIdentity *pi;
-  struct GNUNET_HashCode hash;
-  struct MeshPeerPath *path;
-  struct MeshPeerInfo *dest_peer_info;
-  struct MeshPeerInfo *orig_peer_info;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a path create msg [%s]\n",
-              GNUNET_i2s (&my_full_id));
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  size -= sizeof (struct GNUNET_MESH_ManipulatePath);
-  if (size % sizeof (struct GNUNET_PeerIdentity))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  size /= sizeof (struct GNUNET_PeerIdentity);
-  if (size < 2)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
-  msg = (struct GNUNET_MESH_ManipulatePath *) message;
-
-  tid = ntohl (msg->tid);
-  pi = (struct GNUNET_PeerIdentity *) &msg[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "    path is for tunnel %s [%X].\n", GNUNET_i2s (pi), tid);
-  t = tunnel_get (pi, tid);
-  if (NULL == t) // FIXME only for INCOMING tunnels?
-  {
-    uint32_t opt;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating tunnel\n");
-    t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0);
-    if (NULL == t)
-    {
-      // FIXME notify failure
-      return GNUNET_OK;
-    }
-    opt = ntohl (msg->opt);
-    t->speed_min = (0 != (opt & MESH_TUNNEL_OPT_SPEED_MIN)) ?
-                   GNUNET_YES : GNUNET_NO;
-    if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER))
-    {
-      t->nobuffer = GNUNET_YES;
-      t->last_fwd_ack = t->fwd_pid + 1;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  speed_min: %d, nobuffer:%d\n",
-                t->speed_min, t->nobuffer);
-
-    if (GNUNET_YES == t->nobuffer)
-    {
-      t->bck_queue_max = 1;
-      t->fwd_queue_max = 1;
-    }
-
-    // FIXME only assign a local tid if a local client is interested (on 
demand)
-    while (NULL != tunnel_get_incoming (next_local_tid))
-      next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-    t->local_tid_dest = next_local_tid++;
-    next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-    // FIXME end
-
-    tunnel_reset_timeout (t);
-    GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
-    if (GNUNET_OK !=
-        GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
-                                           
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-    {
-      tunnel_destroy (t);
-      GNUNET_break (0);
-      return GNUNET_OK;
-    }
-  }
-  dest_peer_info =
-      GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
-  if (NULL == dest_peer_info)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Creating PeerInfo for destination.\n");
-    dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
-    dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
-    GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
-                                       dest_peer_info,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  }
-  orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
-  if (NULL == orig_peer_info)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Creating PeerInfo for origin.\n");
-    orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
-    orig_peer_info->id = GNUNET_PEER_intern (pi);
-    GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
-  path = path_new (size);
-  own_pos = 0;
-  for (i = 0; i < size; i++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
-                GNUNET_i2s (&pi[i]));
-    path->peers[i] = GNUNET_PEER_intern (&pi[i]);
-    if (path->peers[i] == myid)
-      own_pos = i;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
-  if (own_pos == 0)
-  {
-    /* cannot be self, must be 'not found' */
-    /* create path: self not found in path through self */
-    GNUNET_break_op (0);
-    path_destroy (path);
-    tunnel_destroy (t);
-    return GNUNET_OK;
-  }
-  path_add_to_peers (path, GNUNET_NO);
-  tunnel_add_path (t, path, own_pos);
-  if (own_pos == size - 1)
-  {
-    /* It is for us! Send ack. */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
-    peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
-    if (NULL == t->peers)
-    {
-      /* New tunnel! Notify clients on first payload message. */
-      t->peers = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO);
-    }
-    GNUNET_break (GNUNET_SYSERR !=
-                  GNUNET_CONTAINER_multihashmap_put (t->peers,
-                                                     &my_full_id.hashPubKey,
-                                                     peer_info_get
-                                                     (&my_full_id),
-                                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
-    send_path_ack (t);
-  }
-  else
-  {
-    struct MeshPeerPath *path2;
-
-    /* It's for somebody else! Retransmit. */
-    path2 = path_duplicate (path);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
-    peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
-    path2 = path_duplicate (path);
-    peer_info_add_path_to_origin (orig_peer_info, path2, GNUNET_NO);
-    send_create_path (dest_peer_info, path, t);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for path destruction
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ManipulatePath *msg;
-  struct GNUNET_PeerIdentity *pi;
-  struct MeshPeerPath *path;
-  struct MeshTunnel *t;
-  unsigned int own_pos;
-  unsigned int i;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a PATH DESTROY msg from %s\n", GNUNET_i2s (peer));
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  size -= sizeof (struct GNUNET_MESH_ManipulatePath);
-  if (size % sizeof (struct GNUNET_PeerIdentity))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  size /= sizeof (struct GNUNET_PeerIdentity);
-  if (size < 2)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
-
-  msg = (struct GNUNET_MESH_ManipulatePath *) message;
-  pi = (struct GNUNET_PeerIdentity *) &msg[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "    path is for tunnel %s [%X].\n", GNUNET_i2s (pi),
-              msg->tid);
-  t = tunnel_get (pi, ntohl (msg->tid));
-  if (NULL == t)
-  {
-    /* TODO notify back: we don't know this tunnel */
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
-  path = path_new (size);
-  own_pos = 0;
-  for (i = 0; i < size; i++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
-                GNUNET_i2s (&pi[i]));
-    path->peers[i] = GNUNET_PEER_intern (&pi[i]);
-    if (path->peers[i] == myid)
-      own_pos = i;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
-  if (own_pos < path->length - 1)
-    send_prebuilt_message (message, &pi[own_pos + 1], t);
-  else
-    send_client_tunnel_disconnect(t, NULL);
-
-  tunnel_delete_peer (t, path->peers[path->length - 1]);
-  path_destroy (path);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for notifications of broken paths
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
-                         const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PathBroken *msg;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer));
-  msg = (struct GNUNET_MESH_PathBroken *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
-              GNUNET_i2s (&msg->peer1));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
-              GNUNET_i2s (&msg->peer2));
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  if (NULL == t)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1),
-                                   GNUNET_PEER_search (&msg->peer2));
-  return GNUNET_OK;
-
-}
-
-
-/**
- * Core handler for tunnel destruction
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelDestroy *msg;
-  struct MeshTunnel *t;
-  GNUNET_PEER_Id parent;
-  GNUNET_PEER_Id pid;
-
-  msg = (struct GNUNET_MESH_TunnelDestroy *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a TUNNEL DESTROY packet from %s\n",
-              GNUNET_i2s (peer));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  for tunnel %s [%u]\n",
-              GNUNET_i2s (&msg->oid), ntohl (msg->tid));
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  /* Check signature */
-  if (NULL == t)
-  {
-    /* Probably already got the message from another path,
-     * destroyed the tunnel and retransmitted to children.
-     * Safe to ignore.
-     */
-    GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
-                              1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  parent = tree_get_predecessor (t->tree);
-  pid = GNUNET_PEER_search (peer);
-  if (pid != parent)
-  {
-    unsigned int nc;
-
-    tree_del_peer (t->tree, pid, &tunnel_child_removed, t);
-    nc = tree_count_children (t->tree);
-    if (nc > 0 || NULL != t->owner || t->nclients > 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "still in use: %u cl, %u ch\n",
-                  t->nclients, nc);
-      return GNUNET_OK;
-    }
-  }
-  if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    /* Tunnel was incoming, notify clients */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n",
-                t->local_tid, t->local_tid_dest);
-    send_clients_tunnel_destroy (t);
-  }
-  tunnel_send_destroy (t, parent);
-  t->destroy = GNUNET_YES;
-  // TODO: add timeout to destroy the tunnel anyway
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic going from the origin to a peer
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- * @param message message
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Unicast *msg;
-  struct GNUNET_PeerIdentity *neighbor;
-  struct MeshTunnelChildInfo *cinfo;
-  struct MeshTunnel *t;
-  GNUNET_PEER_Id dest_id;
-  uint32_t pid;
-  uint32_t ttl;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a unicast packet from %s\n",
-              GNUNET_i2s (peer));
-  /* Check size */
-  size = ntohs (message->size);
-  if (size <
-      sizeof (struct GNUNET_MESH_Unicast) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-  msg = (struct GNUNET_MESH_Unicast *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
-              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
-  /* Check tunnel */
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  if (NULL == t)
-  {
-    /* TODO notify back: we don't know this tunnel */
-    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  pid = ntohl (msg->pid);
-  if (t->fwd_pid == pid)
-  {
-    GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                " Already seen pid %u, DROPPING!\n", pid);
-    return GNUNET_OK;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " pid %u not seen yet, forwarding\n", pid);
-  }
-
-  t->skip += (pid - t->fwd_pid) - 1;
-  t->fwd_pid = pid;
-
-  if (GMC_is_pid_bigger (pid, t->last_fwd_ack))
-  {
-    GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received PID %u, ACK %u\n",
-                pid, t->last_fwd_ack);
-    return GNUNET_OK;
-  }
-
-  tunnel_reset_timeout (t);
-  dest_id = GNUNET_PEER_search (&msg->destination);
-  if (dest_id == myid)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  it's for us! sending to clients...\n");
-    GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO);
-    send_subscribed_clients (message, &msg[1].header, t);
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
-    return GNUNET_OK;
-  }
-  ttl = ntohl (msg->ttl);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
-  if (ttl == 0)
-  {
-    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  not for us, retransmitting...\n");
-
-  neighbor = tree_get_first_hop (t->tree, dest_id);
-  cinfo = tunnel_get_neighbor_fc (t, neighbor);
-  cinfo->fwd_pid = pid;
-  GNUNET_CONTAINER_multihashmap_iterate (t->children_fc,
-                                         &tunnel_add_skip,
-                                         &neighbor);
-  if (GNUNET_YES == t->nobuffer &&
-      GNUNET_YES == GMC_is_pid_bigger (pid, cinfo->fwd_ack))
-  {
-    GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  %u > %u\n", pid, cinfo->fwd_ack);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  send_prebuilt_message (message, neighbor, t);
-  GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic going from the origin to all peers
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- *
- * TODO: Check who we got this from, to validate route.
- */
-static int
-handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Multicast *msg;
-  struct MeshTunnel *t;
-  size_t size;
-  uint32_t pid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a multicast packet from %s\n",
-              GNUNET_i2s (peer));
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_MESH_Multicast) +
-      sizeof (struct GNUNET_MessageHeader) > size)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  msg = (struct GNUNET_MESH_Multicast *) message;
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know that tunnel */
-    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  pid = ntohl (msg->pid);
-  if (t->fwd_pid == pid)
-  {
-    /* already seen this packet, drop */
-    GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " Already seen pid %u, DROPPING!\n", pid);
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " pid %u not seen yet, forwarding\n", pid);
-  }
-  t->skip += (pid - t->fwd_pid) - 1;
-  t->fwd_pid = pid;
-  tunnel_reset_timeout (t);
-
-  /* Transmit to locally interested clients */
-  if (NULL != t->peers &&
-      GNUNET_CONTAINER_multihashmap_contains (t->peers, 
&my_full_id.hashPubKey))
-  {
-    GNUNET_STATISTICS_update (stats, "# multicast received", 1, GNUNET_NO);
-    send_subscribed_clients (message, &msg[1].header, t);
-    tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ntohl (msg->ttl));
-  if (ntohl (msg->ttl) == 0)
-  {
-    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-  GNUNET_STATISTICS_update (stats, "# multicast forwarded", 1, GNUNET_NO);
-  tunnel_send_multicast (t, message);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic toward the owner of a tunnel
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ToOrigin *msg;
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerInfo *peer_info;
-  struct MeshTunnel *t;
-  struct MeshTunnelChildInfo *cinfo;
-  GNUNET_PEER_Id predecessor;
-  size_t size;
-  uint32_t pid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n",
-              GNUNET_i2s (peer));
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_MESH_ToOrigin) +     /* Payload must be */
-      sizeof (struct GNUNET_MessageHeader))     /* at least a header */
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  msg = (struct GNUNET_MESH_ToOrigin *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
-              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-  pid = ntohl (msg->pid);
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know this tunnel (whom)? */
-    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received to_origin with PID %u on unknown tunnel %s [%u]\n",
-                pid, GNUNET_i2s (&msg->oid), ntohl (msg->tid));
-    return GNUNET_OK;
-  }
-
-  cinfo = tunnel_get_neighbor_fc(t, peer);
-  if (NULL == cinfo)
-  {
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-
-  if (cinfo->bck_pid == pid)
-  {
-    /* already seen this packet, drop */
-    GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, 
GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " Already seen pid %u, DROPPING!\n", pid);
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    return GNUNET_OK;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " pid %u not seen yet, forwarding\n", pid);
-  cinfo->bck_pid = pid;
-
-  if (NULL != t->owner)
-  {
-    char cbuf[size];
-    struct GNUNET_MESH_ToOrigin *copy;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  it's for us! sending to clients...\n");
-    /* TODO signature verification */
-    memcpy (cbuf, message, size);
-    copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
-    copy->tid = htonl (t->local_tid);
-    t->bck_pid++;
-    copy->pid = htonl (t->bck_pid);
-    GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO);
-    GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
-                                                &copy->header, GNUNET_NO);
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  not for us, retransmitting...\n");
-
-  peer_info = peer_info_get (&msg->oid);
-  if (NULL == peer_info)
-  {
-    /* unknown origin of tunnel */
-    GNUNET_break (0);
-    return GNUNET_OK;
-  }
-  predecessor = tree_get_predecessor (t->tree);
-  if (0 == predecessor)
-  {
-    if (GNUNET_YES == t->destroy)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "to orig received on a dying tunnel %s [%X]\n",
-                  GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-      return GNUNET_OK;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "unknown to origin at %s\n",
-                GNUNET_i2s (&my_full_id));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "from peer %s\n",
-                GNUNET_i2s (peer));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "for tunnel %s [%X]\n",
-                GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                "current tree:\n");
-    tree_debug (t->tree);
-    return GNUNET_OK;
-  }
-  GNUNET_PEER_resolve (predecessor, &id);
-  send_prebuilt_message (message, &id, t);
-  GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic point-to-point acks.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                 const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ACK *msg;
-  struct MeshTunnel *t;
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
-              GNUNET_i2s (peer));
-  msg = (struct GNUNET_MESH_ACK *) message;
-
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know this tunnel (whom)? */
-    GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  ack = ntohl (msg->pid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u\n", ack);
-
-  /* Is this a forward or backward ACK? */
-  if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer))
-  {
-    struct MeshTunnelChildInfo *cinfo;
-
-    debug_bck_ack++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
-    cinfo = tunnel_get_neighbor_fc (t, peer);
-    cinfo->fwd_ack = ack;
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    tunnel_unlock_fwd_queues (t);
-    if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll)
-    {
-      GNUNET_SCHEDULER_cancel (cinfo->fc_poll);
-      cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK;
-      cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS;
-    }
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
-    t->bck_ack = ack;
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
-    tunnel_unlock_bck_queue (t);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic point-to-point ack polls.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
-                  const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_Poll *msg;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n",
-              GNUNET_i2s (peer));
-
-  msg = (struct GNUNET_MESH_Poll *) message;
-
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know this tunnel (whom)? */
-    GNUNET_STATISTICS_update (stats, "# poll on unknown tunnel", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Is this a forward or backward ACK? */
-  if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer))
-  {
-    struct MeshTunnelChildInfo *cinfo;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  from FWD\n");
-    cinfo = tunnel_get_neighbor_fc (t, peer);
-    cinfo->bck_ack = cinfo->fwd_pid; // mark as ready to send
-    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  from BCK\n");
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
-  }
-
-  return GNUNET_OK;
-}
-
-/**
- * Core handler for path ACKs
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PathACK *msg;
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerPath *p;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
-              GNUNET_i2s (&my_full_id));
-  msg = (struct GNUNET_MESH_PathACK *) message;
-  t = tunnel_get (&msg->oid, ntohl(msg->tid));
-  if (NULL == t)
-  {
-    /* TODO notify that we don't know the tunnel */
-    GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, 
GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  don't know the tunnel %s [%X]!\n",
-                GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %s [%X]\n",
-              GNUNET_i2s (&msg->oid), ntohl(msg->tid));
-
-  peer_info = peer_info_get (&msg->peer_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by peer %s\n",
-              GNUNET_i2s (&msg->peer_id));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
-              GNUNET_i2s (peer));
-
-  if (NULL != t->regex_search && t->regex_search->peer == peer_info->id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "connect_by_string completed, stopping search\n");
-    regex_cancel_search (t->regex_search);
-    t->regex_search = NULL;
-  }
-
-  /* Add paths to peers? */
-  p = tree_get_path_to_peer (t->tree, peer_info->id);
-  if (NULL != p)
-  {
-    path_add_to_peers (p, GNUNET_YES);
-    path_destroy (p);
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-
-  /* Message for us? */
-  if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct 
GNUNET_PeerIdentity)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
-    if (NULL == t->owner)
-    {
-      GNUNET_break_op (0);
-      return GNUNET_OK;
-    }
-    if (NULL != t->dht_get_type)
-    {
-      GNUNET_DHT_get_stop (t->dht_get_type);
-      t->dht_get_type = NULL;
-    }
-    if (tree_get_status (t->tree, peer_info->id) != MESH_PEER_READY)
-    {
-      tree_set_status (t->tree, peer_info->id, MESH_PEER_READY);
-      send_client_peer_connected (t, peer_info->id);
-    }
-    if (NULL != peer_info->dhtget)
-    {
-      GNUNET_DHT_get_stop (peer_info->dhtget);
-      peer_info->dhtget = NULL;
-    }
-    return GNUNET_OK;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  not for us, retransmitting...\n");
-  GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
-  peer_info = peer_info_get (&msg->oid);
-  send_prebuilt_message (message, &id, t);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh keepalives.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- *
- * TODO: Check who we got this from, to validate route.
- */
-static int
-handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelKeepAlive *msg;
-  struct MeshTunnel *t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
-              GNUNET_i2s (peer));
-
-  msg = (struct GNUNET_MESH_TunnelKeepAlive *) message;
-  t = tunnel_get (&msg->oid, ntohl (msg->tid));
-
-  if (NULL == t)
-  {
-    /* TODO notify that we dont know that tunnel */
-    GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1,
-                              GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  tunnel_reset_timeout (t);
-
-  GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
-  tunnel_send_multicast (t, message);
-  return GNUNET_OK;
-  }
-
-
-
-/**
- * Functions to handle messages from core
- */
-static struct GNUNET_CORE_MessageHandler core_handlers[] = {
-  {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
-  {&handle_mesh_path_destroy, GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY, 0},
-  {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
-   sizeof (struct GNUNET_MESH_PathBroken)},
-  {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY,
-   sizeof (struct GNUNET_MESH_TunnelDestroy)},
-  {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
-  {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
-  {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE,
-    sizeof (struct GNUNET_MESH_TunnelKeepAlive)},
-  {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
-  {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
-    sizeof (struct GNUNET_MESH_ACK)},
-  {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
-    sizeof (struct GNUNET_MESH_Poll)},
-  {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
-   sizeof (struct GNUNET_MESH_PathACK)},
-  {NULL, 0, 0}
-};
-
-
-
-/******************************************************************************/
-/****************       MESH LOCAL HANDLER HELPERS      
***********************/
-/******************************************************************************/
-
-/**
- * deregister_app: iterator for removing each application registered by a 
client
- *
- * @param cls closure
- * @param key the hash of the application id (used to access the hashmap)
- * @param value the value stored at the key (client)
- *
- * @return GNUNET_OK on success
- */
-static int
-deregister_app (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct MeshClient *c = cls;
-
-  GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (applications, key, c));
-  return GNUNET_OK;
-}
-
-#if LATER
-/**
- * notify_client_connection_failure: notify a client that the connection to the
- * requested remote peer is not possible (for instance, no route found)
- * Function called when the socket is ready to queue more data. "buf" will be
- * NULL and "size" zero if the socket was closed for writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-notify_client_connection_failure (void *cls, size_t size, void *buf)
-{
-  int size_needed;
-  struct MeshPeerInfo *peer_info;
-  struct GNUNET_MESH_PeerControl *msg;
-  struct GNUNET_PeerIdentity id;
-
-  if (0 == size && NULL == buf)
-  {
-    // TODO retry? cancel?
-    return 0;
-  }
-
-  size_needed = sizeof (struct GNUNET_MESH_PeerControl);
-  peer_info = (struct MeshPeerInfo *) cls;
-  msg = (struct GNUNET_MESH_PeerControl *) buf;
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
-//     msg->tunnel_id = htonl(peer_info->t->tid);
-  GNUNET_PEER_resolve (peer_info->id, &id);
-  memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
-
-  return size_needed;
-}
-#endif
-
-
-/**
- * Send keepalive packets for a peer
- *
- * @param cls Closure (tunnel for which to send the keepalive).
- * @param tc Notification context.
- */
-static void
-path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct MeshTunnel *t = cls;
-  struct GNUNET_MESH_TunnelKeepAlive *msg;
-  size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive);
-  char cbuf[size];
-
-  t->path_refresh_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "sending keepalive for tunnel %d\n", t->id.tid);
-
-  msg = (struct GNUNET_MESH_TunnelKeepAlive *) cbuf;
-  msg->header.size = htons (size);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
-  msg->oid = my_full_id;
-  msg->tid = htonl (t->id.tid);
-  tunnel_send_multicast (t, &msg->header);
-
-  t->path_refresh_task =
-      GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
-  tunnel_reset_timeout(t);
-}
-
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param exp when will this value expire
- * @param key key of the result
- * @param get_path path of the get request
- * @param get_path_length lenght of get_path
- * @param put_path path of the put request
- * @param put_path_length length of the put_path
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- *
- * TODO: re-issue the request after certain time? cancel after X results?
- */
-static void
-dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
-                    const struct GNUNET_HashCode * key,
-                    const struct GNUNET_PeerIdentity *get_path,
-                    unsigned int get_path_length,
-                    const struct GNUNET_PeerIdentity *put_path,
-                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
-                    size_t size, const void *data)
-{
-  struct MeshPathInfo *path_info = cls;
-  struct MeshPeerPath *p;
-  struct GNUNET_PeerIdentity pi;
-  int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
-  GNUNET_PEER_resolve (path_info->peer->id, &pi);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for %s\n", GNUNET_i2s (&pi));
-
-  p = path_build_from_dht (get_path, get_path_length,
-                           put_path, put_path_length);
-  path_add_to_peers (p, GNUNET_NO);
-  path_destroy (p);
-  for (i = 0; i < path_info->peer->ntunnels; i++)
-  {
-    tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer);
-    peer_info_connect (path_info->peer, path_info->t);
-  }
-
-  return;
-}
-
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param exp when will this value expire
- * @param key key of the result
- * @param get_path path of the get request
- * @param get_path_length lenght of get_path
- * @param put_path path of the put request
- * @param put_path_length length of the put_path
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- */
-static void
-dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
-                      const struct GNUNET_HashCode * key,
-                      const struct GNUNET_PeerIdentity *get_path,
-                      unsigned int get_path_length,
-                      const struct GNUNET_PeerIdentity *put_path,
-                      unsigned int put_path_length, enum GNUNET_BLOCK_Type 
type,
-                      size_t size, const void *data)
-{
-  const struct PBlock *pb = data;
-  const struct GNUNET_PeerIdentity *pi = &pb->id;
-  struct MeshTunnel *t = cls;
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerPath *p;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got type DHT result!\n");
-  if (size != sizeof (struct PBlock))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-  if (ntohl(pb->type) != t->type)
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-  GNUNET_assert (NULL != t->owner);
-  peer_info = peer_info_get (pi);
-  (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey,
-                                            peer_info,
-                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
-  p = path_build_from_dht (get_path, get_path_length, put_path,
-                           put_path_length);
-  path_add_to_peers (p, GNUNET_NO);
-  path_destroy(p);
-  tunnel_add_peer (t, peer_info);
-  peer_info_connect (peer_info, t);
-}
-
-
-/******************************************************************************/
-/*********************       MESH LOCAL HANDLES      
**************************/
-/******************************************************************************/
-
-
-/**
- * Handler for client disconnection
- *
- * @param cls closure
- * @param client identification of the client; NULL
- *        for the last call when the server is destroyed
- */
-static void
-handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  struct MeshClient *c;
-  struct MeshClient *next;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected\n");
-  if (client == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
-    return;
-  }
-
-  c = clients;
-  while (NULL != c)
-  {
-    if (c->handle != client)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ... searching\n");
-      c = c->next;
-      continue;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u)\n",
-                c->id);
-    GNUNET_SERVER_client_drop (c->handle);
-    c->shutting_down = GNUNET_YES;
-    GNUNET_assert (NULL != c->own_tunnels);
-    GNUNET_assert (NULL != c->incoming_tunnels);
-    GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
-                                           &tunnel_destroy_iterator, c);
-    GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
-                                           &tunnel_destroy_iterator, c);
-    GNUNET_CONTAINER_multihashmap_iterate (c->ignore_tunnels,
-                                           &tunnel_destroy_iterator, c);
-    GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
-    GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
-    GNUNET_CONTAINER_multihashmap_destroy (c->ignore_tunnels);
-
-    /* deregister clients applications */
-    if (NULL != c->apps)
-    {
-      GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, c);
-      GNUNET_CONTAINER_multihashmap_destroy (c->apps);
-    }
-    if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
-        GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
-    {
-      GNUNET_SCHEDULER_cancel (announce_applications_task);
-      announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-    if (NULL != c->types)
-      GNUNET_CONTAINER_multihashmap_destroy (c->types);
-    for (i = 0; i < c->n_regex; i++)
-    {
-      GNUNET_free (c->regexes[i].regex);
-      if (NULL != c->regexes[i].h)
-       GNUNET_REGEX_announce_cancel (c->regexes[i].h);
-    }
-    GNUNET_free_non_null (c->regexes);
-    if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task)
-      GNUNET_SCHEDULER_cancel (c->regex_announce_task);
-    next = c->next;
-    GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  CLIENT FREE at %p\n", c);
-    GNUNET_free (c);
-    GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
-    c = next;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   done!\n");
-}
-
-
-/**
- * Handler for new clients
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message, which includes messages the client wants
- */
-static void
-handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
-                         const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ClientConnect *cc_msg;
-  struct MeshClient *c;
-  GNUNET_MESH_ApplicationType *a;
-  unsigned int size;
-  uint16_t ntypes;
-  uint16_t *t;
-  uint16_t napps;
-  uint16_t i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
-  /* Check data sanity */
-  size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
-  cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
-  ntypes = ntohs (cc_msg->types);
-  napps = ntohs (cc_msg->applications);
-  if (size !=
-      ntypes * sizeof (uint16_t) + napps * sizeof 
(GNUNET_MESH_ApplicationType))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Create new client structure */
-  c = GNUNET_malloc (sizeof (struct MeshClient));
-  c->id = next_client_id++;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  CLIENT NEW %u\n", c->id);
-  c->handle = client;
-  GNUNET_SERVER_client_keep (client);
-  a = (GNUNET_MESH_ApplicationType *) &cc_msg[1];
-  if (napps > 0)
-  {
-    GNUNET_MESH_ApplicationType at;
-    struct GNUNET_HashCode hc;
-
-    c->apps = GNUNET_CONTAINER_multihashmap_create (napps, GNUNET_NO);
-    for (i = 0; i < napps; i++)
-    {
-      at = ntohl (a[i]);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  app type: %u\n", at);
-      GNUNET_CRYPTO_hash (&at, sizeof (at), &hc);
-      /* store in clients hashmap */
-      GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, (void *) (long) at,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-      /* store in global hashmap, for announcements */
-      GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    }
-    if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
-      announce_applications_task =
-          GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
-
-  }
-  if (ntypes > 0)
-  {
-    uint16_t u16;
-    struct GNUNET_HashCode hc;
-
-    t = (uint16_t *) & a[napps];
-    c->types = GNUNET_CONTAINER_multihashmap_create (ntypes, GNUNET_NO);
-    for (i = 0; i < ntypes; i++)
-    {
-      u16 = ntohs (t[i]);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  msg type: %u\n", u16);
-      GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
-
-      /* store in clients hashmap */
-      GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-      /* store in global hashmap */
-      GNUNET_CONTAINER_multihashmap_put (types, &hc, c,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " client has %u+%u subscriptions\n", napps, ntypes);
-
-  GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
-  c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  c->ignore_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  GNUNET_SERVER_notification_context_add (nc, client);
-  GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
-}
-
-
-/**
- * Handler for clients announcing available services by a regular expression.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message, which includes messages the client wants
- */
-static void
-handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_MESH_RegexAnnounce *msg;
-  struct MeshRegexDescriptor rd;
-  struct MeshClient *c;
-  char *regex;
-  size_t len;
-  size_t offset;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex started\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  msg = (const struct GNUNET_MESH_RegexAnnounce *) message;
-
-  len = ntohs (message->size) - sizeof(struct GNUNET_MESH_RegexAnnounce);
-  if (NULL != c->partial_regex)
-  {
-    regex = c->partial_regex;
-    offset = strlen (c->partial_regex);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  continuation, already have %u bytes\n",
-                offset);
-  }
-  else
-  {
-    regex = NULL;
-    offset = 0;
-  }
-
-  regex = GNUNET_realloc (regex, offset + len + 1);
-  memcpy (&regex[offset], &msg[1], len);
-  regex[offset + len] = '\0';
-  if (0 == ntohs (msg->last))
-  {
-    c->partial_regex = regex;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  not ended, stored %u bytes for later\n",
-                len);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  rd.regex = regex;
-  rd.compression = ntohs (msg->compression_characters);
-  rd.h = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  length %u\n", len);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regex %s\n", regex);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  compr %u\n", ntohs (rd.compression));
-  GNUNET_array_append (c->regexes, c->n_regex, rd);
-  c->partial_regex = NULL;
-  if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task)
-  {
-    c->regex_announce_task = GNUNET_SCHEDULER_add_now (&regex_announce, c);
-  }
-  else
-  {
-    regex_put (&rd);
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex processed\n");
-}
-
-
-/**
- * Handler for requests of new tunnels
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *t_msg;
-  struct MeshTunnel *t;
-  struct MeshClient *c;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel requested\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message sanity check */
-  if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-  /* Sanity check for tunnel numbering */
-  tid = ntohl (t_msg->tunnel_id);
-  if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  /* Sanity check for duplicate tunnel IDs */
-  if (NULL != tunnel_get_by_local_id (c, tid))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  while (NULL != tunnel_get_by_pi (myid, next_tid))
-    next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-  t = tunnel_new (myid, next_tid++, c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tunnel creation failed.\n");
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  next_tid = next_tid & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s [%x] (%x)\n",
-              GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid);
-  t->peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel created\n");
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for requests of deleting tunnels
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a DESTROY TUNNEL from client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message sanity check */
-  if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-
-  /* Retrieve tunnel */
-  tid = ntohl (tunnel_msg->tunnel_id);
-  t = tunnel_get_by_local_id(c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    client_ignore_tunnel (c, t);
-    tunnel_destroy_empty (t);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  send_client_tunnel_disconnect (t, c);
-  client_delete_tunnel (c, t);
-
-  /* Don't try to ACK the client about the tunnel_destroy multicast packet */
-  t->owner = NULL;
-  tunnel_send_destroy (t, 0);
-  t->destroy = GNUNET_YES;
-  /* The tunnel will be destroyed when the last message is transmitted. */
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for requests of seeting tunnel's speed.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_tunnel_speed (void *cls, struct GNUNET_SERVER_Client *client,
-                           const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a SPEED request from client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-
-  /* Retrieve tunnel */
-  tid = ntohl (tunnel_msg->tunnel_id);
-  t = tunnel_get_by_local_id(c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  tunnel %X not found\n", tid);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  switch (ntohs(message->type))
-  {
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN:
-          t->speed_min = GNUNET_YES;
-          break;
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX:
-          t->speed_min = GNUNET_NO;
-          break;
-      default:
-          GNUNET_break (0);
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for requests of seeting tunnel's buffering policy.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_tunnel_buffer (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a BUFFER request from client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
-
-  /* Retrieve tunnel */
-  tid = ntohl (tunnel_msg->tunnel_id);
-  t = tunnel_get_by_local_id(c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  switch (ntohs(message->type))
-  {
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER:
-          t->nobuffer = GNUNET_NO;
-          break;
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER:
-          t->nobuffer = GNUNET_YES;
-          break;
-      default:
-          GNUNET_break (0);
-  }
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for connection requests to new peers
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message (PeerControl)
- */
-static void
-handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PeerControl *peer_msg;
-  struct MeshPeerInfo *peer_info;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got connection request\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  peer_msg = (struct GNUNET_MESH_PeerControl *) message;
-
-  /* Sanity check for message size */
-  if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (peer_msg->tunnel_id);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Does client own tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "     for %s\n",
-              GNUNET_i2s (&peer_msg->peer));
-  peer_info = peer_info_get (&peer_msg->peer);
-
-  tunnel_add_peer (t, peer_info);
-  peer_info_connect (peer_info, t);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for disconnection requests of peers in a tunnel
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message (PeerControl)
- */
-static void
-handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PeerControl *peer_msg;
-  struct MeshPeerInfo *peer_info;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER DEL request\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  peer_msg = (struct GNUNET_MESH_PeerControl *) message;
-
-  /* Sanity check for message size */
-  if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (peer_msg->tunnel_id);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", t->id.tid);
-
-  /* Does client own tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for peer %s\n",
-              GNUNET_i2s (&peer_msg->peer));
-  /* Is the peer in the tunnel? */
-  peer_info =
-      GNUNET_CONTAINER_multihashmap_get (t->peers, &peer_msg->peer.hashPubKey);
-  if (NULL == peer_info)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Ok, delete peer from tunnel */
-  GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
-                                            &peer_msg->peer.hashPubKey);
-
-  send_destroy_path (t, peer_info->id);
-  tunnel_delete_peer (t, peer_info->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-/**
- * Handler for blacklist requests of peers in a tunnel
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message (PeerControl)
- * 
- * FIXME implement DHT block bloomfilter
- */
-static void
-handle_local_blacklist (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PeerControl *peer_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER BLACKLIST request\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  peer_msg = (struct GNUNET_MESH_PeerControl *) message;
-
-  /* Sanity check for message size */
-  if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (peer_msg->tunnel_id);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", t->id.tid);
-
-  GNUNET_array_append(t->blacklisted, t->nblacklisted,
-                      GNUNET_PEER_intern(&peer_msg->peer));
-}
-
-
-/**
- * Handler for unblacklist requests of peers in a tunnel
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message (PeerControl)
- */
-static void
-handle_local_unblacklist (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_PeerControl *peer_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-  GNUNET_PEER_Id pid;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER UNBLACKLIST request\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  peer_msg = (struct GNUNET_MESH_PeerControl *) message;
-
-  /* Sanity check for message size */
-  if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (peer_msg->tunnel_id);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", t->id.tid);
-
-  /* if peer is not known, complain */
-  pid = GNUNET_PEER_search (&peer_msg->peer);
-  if (0 == pid)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* search and remove from list */
-  for (i = 0; i < t->nblacklisted; i++)
-  {
-    if (t->blacklisted[i] == pid)
-    {
-      t->blacklisted[i] = t->blacklisted[t->nblacklisted - 1];
-      GNUNET_array_grow (t->blacklisted, t->nblacklisted, t->nblacklisted - 1);
-      return;
-    }
-  }
-
-  /* if peer hasn't been blacklisted, complain */
-  GNUNET_break (0);
-}
-
-
-/**
- * Handler for connection requests to new peers by type
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message (ConnectPeerByType)
- */
-static void
-handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
-                              const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectPeerByType *connect_msg;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  struct GNUNET_HashCode hash;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got connect by type request\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
-
-  /* Sanity check for message size */
-  if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
-      ntohs (connect_msg->header.size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (connect_msg->tunnel_id);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Does client own tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Do WE have the service? */
-  t->type = ntohl (connect_msg->type);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type requested: %u\n", t->type);
-  GNUNET_CRYPTO_hash (&t->type, sizeof (GNUNET_MESH_ApplicationType), &hash);
-  if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
-      GNUNET_YES)
-  {
-    /* Yes! Fast forward, add ourselves to the tunnel and send the
-     * good news to the client, and alert the destination client of
-     * an incoming tunnel.
-     *
-     * FIXME send a path create to self, avoid code duplication
-     */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " available locally\n");
-    GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey,
-                                       peer_info_get (&my_full_id),
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " notifying client\n");
-    send_client_peer_connected (t, myid);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Done\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-    t->local_tid_dest = next_local_tid++;
-    GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
-    GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-
-    return;
-  }
-  /* Ok, lets find a peer offering the service */
-  if (NULL != t->dht_get_type)
-  {
-    GNUNET_DHT_get_stop (t->dht_get_type);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking in DHT for %s\n",
-              GNUNET_h2s (&hash));
-  t->dht_get_type =
-      GNUNET_DHT_get_start (dht_handle, 
-                            GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
-                            &hash,
-                            dht_replication_level,
-                            GNUNET_DHT_RO_RECORD_ROUTE |
-                            GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
-                            NULL, 0,
-                            &dht_get_type_handler, t);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for connection requests to new peers by a string service 
description.
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message, which includes messages the client wants
- */
-static void
-handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectPeerByString *msg;
-  struct MeshRegexSearchInfo *info;
-  struct MeshTunnel *t;
-  struct MeshClient *c;
-  MESH_TunnelNumber tid;
-  const char *string;
-  size_t size;
-  size_t len;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connect by string started\n");
-  msg = (struct GNUNET_MESH_ConnectPeerByString *) message;
-  size = htons (message->size);
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message size sanity check */
-  if (sizeof(struct GNUNET_MESH_ConnectPeerByString) >= size)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (msg->tunnel_id);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Does client own tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  on tunnel %s [%u]\n",
-              GNUNET_i2s(&my_full_id),
-              t->id.tid);
-
-  /* Only one connect_by_string allowed at the same time! */
-  /* FIXME: allow more, return handle at api level to cancel, document */
-  if (NULL != t->regex_search)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Find string itself */
-  len = size - sizeof(struct GNUNET_MESH_ConnectPeerByString);
-  string = (const char *) &msg[1];
-
-  info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo));
-  info->t = t;
-  info->description = GNUNET_strndup (string, len);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   string: %s\n", info->description);
-
-  t->regex_search = info;
-
-  info->search_handle = GNUNET_REGEX_search (cfg,
-                                             info->description,
-                                             &regex_found_handler, info);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n");
-}
-
-
-/**
- * Handler for client traffic directed to one peer
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
-{
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  struct MeshPeerInfo *pi;
-  struct GNUNET_MESH_Unicast *data_msg;
-  MESH_TunnelNumber tid;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a unicast request from a client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  data_msg = (struct GNUNET_MESH_Unicast *) message;
-
-  /* Sanity check for message size */
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_MESH_Unicast) +
-      sizeof (struct GNUNET_MessageHeader) > size)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (data_msg->tid);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /*  Is it a local tunnel? Then, does client own the tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
-                                          &data_msg->destination.hashPubKey);
-  /* Is the selected peer in the tunnel? */
-  if (NULL == pi)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* PID should be as expected */
-  if (ntohl (data_msg->pid) != t->fwd_pid + 1)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Unicast PID, expected %u, got %u\n",
-              t->fwd_pid + 1, ntohl (data_msg->pid));
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Ok, everything is correct, send the message
-   * (pretend we got it from a mesh peer)
-   */
-  {
-    /* Work around const limitation */
-    char buf[ntohs (message->size)] GNUNET_ALIGN;
-    struct GNUNET_MESH_Unicast *copy;
-
-    copy = (struct GNUNET_MESH_Unicast *) buf;
-    memcpy (buf, data_msg, size);
-    copy->oid = my_full_id;
-    copy->tid = htonl (t->id.tid);
-    copy->ttl = htonl (default_ttl);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  calling generic handler...\n");
-    handle_mesh_data_unicast (NULL, &my_full_id, &copy->header);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-/**
- * Handler for client traffic directed to the origin
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ToOrigin *data_msg;
-  struct MeshTunnelClientInfo *clinfo;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  MESH_TunnelNumber tid;
-  size_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a ToOrigin request from a client!\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  data_msg = (struct GNUNET_MESH_ToOrigin *) message;
-
-  /* Sanity check for message size */
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_MESH_ToOrigin) +
-      sizeof (struct GNUNET_MessageHeader) > size)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (data_msg->tid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", tid);
-  if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /*  It should be sent by someone who has this as incoming tunnel. */
-  if (GNUNET_NO == client_knows_tunnel (c, t))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* PID should be as expected */
-  clinfo = tunnel_get_client_fc (t, c);
-  if (ntohl (data_msg->pid) != clinfo->bck_pid + 1)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "To Origin PID, expected %u, got %u\n",
-                clinfo->bck_pid + 1,
-                ntohl (data_msg->pid));
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  clinfo->bck_pid++;
-
-  /* Ok, everything is correct, send the message
-   * (pretend we got it from a mesh peer)
-   */
-  {
-    char buf[ntohs (message->size)] GNUNET_ALIGN;
-    struct GNUNET_MESH_ToOrigin *copy;
-
-    /* Work around const limitation */
-    copy = (struct GNUNET_MESH_ToOrigin *) buf;
-    memcpy (buf, data_msg, size);
-    GNUNET_PEER_resolve (t->id.oid, &copy->oid);
-    copy->tid = htonl (t->id.tid);
-    copy->ttl = htonl (default_ttl);
-    copy->pid = htonl (t->bck_pid + 1);
-
-    copy->sender = my_full_id;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  calling generic handler...\n");
-    handle_mesh_data_to_orig (NULL, &my_full_id, &copy->header);
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-/**
- * Handler for client traffic directed to all peers in a tunnel
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-  struct GNUNET_MESH_Multicast *data_msg;
-  MESH_TunnelNumber tid;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a multicast request from a client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  data_msg = (struct GNUNET_MESH_Multicast *) message;
-
-  /* Sanity check for message size */
-  if (sizeof (struct GNUNET_MESH_Multicast) +
-      sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Tunnel exists? */
-  tid = ntohl (data_msg->tid);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Does client own tunnel? */
-  if (t->owner->handle != client)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* PID should be as expected */
-  if (ntohl (data_msg->pid) != t->fwd_pid + 1)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Multicast PID, expected %u, got %u\n",
-              t->fwd_pid + 1, ntohl (data_msg->pid));
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  {
-    char buf[ntohs (message->size)] GNUNET_ALIGN;
-    struct GNUNET_MESH_Multicast *copy;
-
-    copy = (struct GNUNET_MESH_Multicast *) buf;
-    memcpy (buf, message, ntohs (message->size));
-    copy->oid = my_full_id;
-    copy->tid = htonl (t->id.tid);
-    copy->ttl = htonl (default_ttl);
-    GNUNET_assert (ntohl (copy->pid) == (t->fwd_pid + 1));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  calling generic handler...\n");
-    handle_mesh_data_multicast (client, &my_full_id, &copy->header);
-  }
-
-  GNUNET_SERVER_receive_done (t->owner->handle, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for client's ACKs for payload traffic.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
-                  const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalAck *msg;
-  struct MeshTunnel *t;
-  struct MeshClient *c;
-  MESH_TunnelNumber tid;
-  uint32_t ack;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  msg = (struct GNUNET_MESH_LocalAck *) message;
-
-  /* Tunnel exists? */
-  tid = ntohl (msg->tunnel_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", tid);
-  t = tunnel_get_by_local_id (c, tid);
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  ack = ntohl (msg->max_pid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ack %u\n", ack);
-
-  /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */
-  if (NULL != t->owner && t->owner->handle == client)
-  {
-    /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */
-    t->bck_ack = ack;
-    tunnel_send_bck_ack(t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  }
-  else
-  {
-    /* The client doesn't own the tunnel, this ACK is for FWD traffic. */
-    tunnel_set_client_fwd_ack (t, c, ack);
-    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  }
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-/**
- * Iterator over all peers to send a monitoring client info about a tunnel.
- *
- * @param cls Closure (message being built).
- * @param key Key (hashed tunnel ID, unused).
- * @param value Peer info.
- *
- * @return GNUNET_YES, to keep iterating.
- */
-static int
-monitor_peers_iterator (void *cls,
-                        const struct GNUNET_HashCode * key,
-                        void *value)
-{
-  struct GNUNET_MESH_LocalMonitor *msg = cls;
-  struct GNUNET_PeerIdentity *id;
-  struct MeshPeerInfo *info = value;
-
-  id = (struct GNUNET_PeerIdentity *) &msg[1];
-  GNUNET_PEER_resolve (info->id, &id[msg->npeers]);
-  msg->npeers++;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "*    sending info about peer %s [%u]\n",
-              GNUNET_i2s (&id[msg->npeers - 1]), msg->npeers);
-
-  return GNUNET_YES;
-}
-
-
-
-/**
- * Iterator over all tunnels to send a monitoring client info about each 
tunnel.
- *
- * @param cls Closure (client handle).
- * @param key Key (hashed tunnel ID, unused).
- * @param value Tunnel info.
- *
- * @return GNUNET_YES, to keep iterating.
- */
-static int
-monitor_all_tunnels_iterator (void *cls,
-                              const struct GNUNET_HashCode * key,
-                              void *value)
-{
-  struct GNUNET_SERVER_Client *client = cls;
-  struct MeshTunnel *t = value;
-  struct GNUNET_MESH_LocalMonitor *msg;
-  uint32_t npeers;
-  
-  npeers = GNUNET_CONTAINER_multihashmap_size (t->peers);
-  msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor) +
-  npeers * sizeof (struct GNUNET_PeerIdentity));
-  GNUNET_PEER_resolve(t->id.oid, &msg->owner);
-  msg->tunnel_id = htonl (t->id.tid);
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor) +
-  npeers * sizeof (struct GNUNET_PeerIdentity));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
-  msg->npeers = 0;
-  (void) GNUNET_CONTAINER_multihashmap_iterate (t->peers,
-                                                monitor_peers_iterator,
-                                                msg);
-  
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "*  sending info about tunnel %s [%u] (%u peers)\n",
-              GNUNET_i2s (&msg->owner), t->id.tid, npeers);
-  
-  if (msg->npeers != npeers)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Get tunnels fail: size %u - iter %u\n",
-                npeers, msg->npeers);
-  }
-  
-    msg->npeers = htonl (npeers);
-    GNUNET_SERVER_notification_context_unicast (nc, client,
-                                                &msg->header, GNUNET_NO);
-    return GNUNET_YES;
-}
-
-
-/**
- * Handler for client's MONITOR request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct MeshClient *c;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Received get tunnels request from client %u\n",
-              c->id);
-  GNUNET_CONTAINER_multihashmap_iterate (tunnels,
-                                         monitor_all_tunnels_iterator,
-                                         client);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Get tunnels request from client %u completed\n",
-              c->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Data needed to build a Monitor_Tunnel message.
- */
-struct MeshMonitorTunnelContext
-{
-  /**
-   * Partial message, including peer count.
-   */
-  struct GNUNET_MESH_LocalMonitor *msg;
-
-  /**
-   * Hashmap with positions: peer->position.
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *lookup;
-
-  /**
-   * Index of the parent of each peer in the message, realtive to the absolute
-   * order in the array (can be in a previous message).
-   */
-  uint32_t parents[1024];
-
-  /**
-   * Peers visited so far in the tree, aka position of the current peer.
-   */
-  unsigned int npeers;
-
-  /**
-   * Client requesting the info.
-   */
-  struct MeshClient *c;
-};
-
-
-/**
- * Send a client a message about the structure of a tunnel.
- *
- * @param ctx Context of the tunnel iteration, with info regarding the state
- *            of the execution and the number of peers visited for this 
message.
- */
-static void
-send_client_tunnel_info (struct MeshMonitorTunnelContext *ctx)
-{
-  struct GNUNET_MESH_LocalMonitor *resp = ctx->msg;
-  struct GNUNET_PeerIdentity *pid;
-  unsigned int *parent;
-  size_t size;
-
-  size = sizeof (struct GNUNET_MESH_LocalMonitor);
-  size += (sizeof (struct GNUNET_PeerIdentity) + sizeof (int)) * resp->npeers;
-  resp->header.size = htons (size);
-  pid = (struct GNUNET_PeerIdentity *) &resp[1];
-  parent = (unsigned int *) &pid[resp->npeers];
-  memcpy (parent, ctx->parents, sizeof(uint32_t) * resp->npeers);
-  GNUNET_SERVER_notification_context_unicast (nc, ctx->c->handle,
-                                              &resp->header, GNUNET_NO);
-}
-
-/**
- * Iterator over a tunnel tree to build a message containing all peers
- * the in the tunnel, including relay nodes.
- *
- * @param cls Closure (pointer to pointer of message being built).
- * @param peer Short ID of a peer.
- * @param parent Short ID of the @c peer 's parent.
- */
-static void
-tunnel_tree_iterator (void *cls,
-                      GNUNET_PEER_Id peer,
-                      GNUNET_PEER_Id parent)
-{
-  struct MeshMonitorTunnelContext *ctx = cls;
-  struct GNUNET_MESH_LocalMonitor *msg;
-  struct GNUNET_PeerIdentity *pid;
-  struct GNUNET_PeerIdentity ppid;
-
-  msg = ctx->msg;
-  pid = (struct GNUNET_PeerIdentity *) &msg[1];
-  GNUNET_PEER_resolve (peer, &pid[msg->npeers]);
-  GNUNET_CONTAINER_multihashmap_put (ctx->lookup,
-                                     &pid[msg->npeers].hashPubKey,
-                                     (void *) (long) ctx->npeers,
-                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-  GNUNET_PEER_resolve (parent, &ppid);
-  ctx->parents[msg->npeers] =
-      htonl ((long) GNUNET_CONTAINER_multihashmap_get (ctx->lookup,
-                                                       &ppid.hashPubKey));
-
-  ctx->npeers++;
-  msg->npeers++;
-
-  if (sizeof (struct GNUNET_MESH_LocalMonitor) +
-      (msg->npeers + 1) *
-      (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t))
-      > USHRT_MAX)
-  {
-    send_client_tunnel_info (ctx);
-    msg->npeers = 0;
-  }
-}
-
-
-/**
- * Handler for client's MONITOR_TUNNEL request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
-                          const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_MESH_LocalMonitor *msg;
-  struct GNUNET_MESH_LocalMonitor *resp;
-  struct MeshMonitorTunnelContext ctx;
-  struct MeshClient *c;
-  struct MeshTunnel *t;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  msg = (struct GNUNET_MESH_LocalMonitor *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Received tunnel info request from client %u for tunnel 
%s[%X]\n",
-              c->id,
-              &msg->owner,
-              ntohl (msg->tunnel_id));
-  t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id));
-  if (NULL == t)
-  {
-    /* We don't know the tunnel */
-    struct GNUNET_MESH_LocalMonitor warn;
-
-    warn = *msg;
-    warn.npeers = htonl (UINT_MAX);
-    GNUNET_SERVER_notification_context_unicast (nc, client,
-                                                &warn.header,
-                                                GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  /* Initialize context */
-  resp = GNUNET_malloc (USHRT_MAX); /* avoid realloc'ing on each step */
-  *resp = *msg;
-  resp->npeers = 0;
-  ctx.msg = resp;
-  ctx.lookup = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
-  ctx.c = c;
-
-  /* Collect and send information */
-  tree_iterate_all (t->tree, &tunnel_tree_iterator, &ctx);
-  send_client_tunnel_info (&ctx);
-
-  /* Free context */
-  GNUNET_CONTAINER_multihashmap_destroy (ctx.lookup);
-  GNUNET_free (resp);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Monitor tunnel request from client %u completed\n",
-              c->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Functions to handle messages from clients
- */
-static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
-  {&handle_local_new_client, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
-  {&handle_local_announce_regex, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX, 0},
-  {&handle_local_tunnel_create, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_destroy, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_speed, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_speed, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_buffer, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_tunnel_buffer, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER,
-   sizeof (struct GNUNET_MESH_TunnelMessage)},
-  {&handle_local_connect_add, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
-   sizeof (struct GNUNET_MESH_PeerControl)},
-  {&handle_local_connect_del, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
-   sizeof (struct GNUNET_MESH_PeerControl)},
-  {&handle_local_blacklist, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST,
-   sizeof (struct GNUNET_MESH_PeerControl)},
-  {&handle_local_unblacklist, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST,
-   sizeof (struct GNUNET_MESH_PeerControl)},
-  {&handle_local_connect_by_type, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
-   sizeof (struct GNUNET_MESH_ConnectPeerByType)},
-  {&handle_local_connect_by_string, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING, 0},
-  {&handle_local_unicast, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
-  {&handle_local_to_origin, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
-  {&handle_local_multicast, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
-  {&handle_local_ack, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
-   sizeof (struct GNUNET_MESH_LocalAck)},
-  {&handle_local_get_tunnels, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
-   sizeof (struct GNUNET_MessageHeader)},
-  {&handle_local_show_tunnel, NULL,
-   GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
-     sizeof (struct GNUNET_MESH_LocalMonitor)},
-  {NULL, NULL, 0, 0}
-};
-
-
-/**
- * To be called on core init/fail.
- *
- * @param cls service closure
- * @param server handle to the server for this service
- * @param identity the public identity of this peer
- */
-static void
-core_init (void *cls, struct GNUNET_CORE_Handle *server,
-           const struct GNUNET_PeerIdentity *identity)
-{
-  static int i = 0;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
-  core_handle = server;
-  if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
-      NULL == server)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                " core id %s\n",
-                GNUNET_i2s (identity));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                " my id %s\n",
-                GNUNET_i2s (&my_full_id));
-    GNUNET_SCHEDULER_shutdown (); // Try gracefully
-    if (10 < i++)
-      GNUNET_abort(); // Try harder
-  }
-  return;
-}
-
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeerInfo *peer_info;
-  struct MeshPeerPath *path;
-
-  DEBUG_CONN ("Peer connected\n");
-  DEBUG_CONN ("     %s\n", GNUNET_i2s (&my_full_id));
-  peer_info = peer_info_get (peer);
-  if (myid == peer_info->id)
-  {
-    DEBUG_CONN ("     (self)\n");
-    return;
-  }
-  else
-  {
-    DEBUG_CONN ("     %s\n", GNUNET_i2s (peer));
-  }
-  path = path_new (2);
-  path->peers[0] = myid;
-  path->peers[1] = peer_info->id;
-  GNUNET_PEER_change_rc (myid, 1);
-  GNUNET_PEER_change_rc (peer_info->id, 1);
-  peer_info_add_path (peer_info, path, GNUNET_YES);
-  GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
-  return;
-}
-
-
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeerInfo *pi;
-  struct MeshPeerQueue *q;
-  struct MeshPeerQueue *n;
-
-  DEBUG_CONN ("Peer disconnected\n");
-  pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
-  if (NULL == pi)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  q = pi->queue_head;
-  while (NULL != q)
-  {
-      n = q->next;
-      /* TODO try to reroute this traffic instead */
-      queue_destroy(q, GNUNET_YES);
-      q = n;
-  }
-  if (NULL != pi->core_transmit)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit);
-    pi->core_transmit = NULL;
-  }
-  peer_info_remove_path (pi, pi->id, myid);
-  if (myid == pi->id)
-  {
-    DEBUG_CONN ("     (self)\n");
-  }
-  GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
-  return;
-}
-
-
-/******************************************************************************/
-/************************      MAIN FUNCTIONS      
****************************/
-/******************************************************************************/
-
-/**
- * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
- */
-static int
-shutdown_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct MeshTunnel *t = value;
-
-  tunnel_destroy (t);
-  return GNUNET_YES;
-}
-
-/**
- * Iterator over peer hash map entries to destroy the tunnel during shutdown.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
- */
-static int
-shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  struct MeshPeerInfo *p = value;
-  struct MeshPeerQueue *q;
-  struct MeshPeerQueue *n;
-
-  q = p->queue_head;
-  while (NULL != q)
-  {
-      n = q->next;
-      if (q->peer == p)
-      {
-        queue_destroy(q, GNUNET_YES);
-      }
-      q = n;
-  }
-  peer_info_destroy (p);
-  return GNUNET_YES;
-}
-
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- * @param tc unused
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
-
-  if (core_handle != NULL)
-  {
-    GNUNET_CORE_disconnect (core_handle);
-    core_handle = NULL;
-  }
-  if (NULL != keygen)
-  {
-    GNUNET_CRYPTO_ecc_key_create_stop (keygen);
-    keygen = NULL;
-  }
-  GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL);
-  GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL);
-  if (dht_handle != NULL)
-  {
-    GNUNET_DHT_disconnect (dht_handle);
-    dht_handle = NULL;
-  }
-  if (nc != NULL)
-  {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
-  {
-    GNUNET_SCHEDULER_cancel (announce_id_task);
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
-  {
-    GNUNET_SCHEDULER_cancel (announce_applications_task);
-    announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
-}
-
-
-/**
- * Callback for hostkey read/generation.
- *
- * @param cls Closure (Configuration handle).
- * @param pk The ECC private key.
- * @param emsg Error message, if any.
- */
-static void
-key_generation_cb (void *cls,
-                   struct GNUNET_CRYPTO_EccPrivateKey *pk,
-                   const char *emsg)
-{
-  const struct GNUNET_CONFIGURATION_Handle *c = cls;
-  struct MeshPeerInfo *peer;
-  struct MeshPeerPath *p;
-
-  keygen = NULL;  
-  if (NULL == pk)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("Could not access hostkey: %s. Exiting.\n"),
-                emsg);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  my_private_key = pk;
-  GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key);
-  GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
-                      &my_full_id.hashPubKey);
-  myid = GNUNET_PEER_intern (&my_full_id);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Mesh for peer [%s] starting\n",
-              GNUNET_i2s(&my_full_id));
-
-  core_handle = GNUNET_CORE_connect (c, /* Main configuration */
-                                     NULL,      /* Closure passed to MESH 
functions */
-                                     &core_init,        /* Call core_init once 
connected */
-                                     &core_connect,     /* Handle connects */
-                                     &core_disconnect,  /* remove peers on 
disconnects */
-                                     NULL,      /* Don't notify about all 
incoming messages */
-                                     GNUNET_NO, /* For header only in 
notification */
-                                     NULL,      /* Don't notify about all 
outbound messages */
-                                     GNUNET_NO, /* For header-only out 
notification */
-                                     core_handlers);    /* Register these 
handlers */
-  
-  if (core_handle == NULL)
-  {
-    GNUNET_break (0);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  next_tid = 0;
-  next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-
-
-  GNUNET_SERVER_add_handlers (server_handle, client_handlers);
-  nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
-  GNUNET_SERVER_disconnect_notify (server_handle,
-                                   &handle_local_client_disconnect, NULL);
-
-
-  clients = NULL;
-  clients_tail = NULL;
-  next_client_id = 0;
-
-  announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
-  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
-
-  /* Create a peer_info for the local peer */
-  peer = peer_info_get (&my_full_id);
-  p = path_new (1);
-  p->peers[0] = myid;
-  GNUNET_PEER_change_rc (myid, 1);
-  peer_info_add_path (peer, p, GNUNET_YES);
-  GNUNET_SERVER_resume (server_handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
-}
-
-
-/**
- * Process mesh requests.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  char *keyfile;
-
-  cfg = c;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
-  server_handle = server;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY",
-                                               &keyfile))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "peer/privatekey");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_PATH_TIME",
-                                           &refresh_path_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "refresh path time");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "APP_ANNOUNCE_TIME",
-                                           &app_announce_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "app announce time");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "APP_ANNOUNCE_TIME %llu ms\n", 
-             app_announce_time.rel_value);
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
-                                           &id_announce_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "id announce time");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
-                                           &connect_timeout))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "connect timeout");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
-                                             &max_msgs_queue))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "max msgs queue");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_TUNNELS",
-                                             &max_tunnels))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
-                "mesh", "max tunnels");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
-                                             &default_ttl))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _
-                ("%s service is lacking key configuration settings (%s). Using 
default (%u).\n"),
-                "mesh", "default ttl", 64);
-    default_ttl = 64;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
-                                             &max_peers))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("%s service is lacking key configuration settings (%s). 
Using default (%u).\n"),
-                "mesh", "max peers", 1000);
-    max_peers = 1000;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", 
"DHT_REPLICATION_LEVEL",
-                                             &dht_replication_level))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _
-                ("%s service is lacking key configuration settings (%s). Using 
default (%u).\n"),
-                "mesh", "dht replication level", 3);
-    dht_replication_level = 3;
-  }
-
-  tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  applications = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  types = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-
-  dht_handle = GNUNET_DHT_connect (c, 64);
-  if (NULL == dht_handle)
-  {
-    GNUNET_break (0);
-  }
-  stats = GNUNET_STATISTICS_create ("mesh", c);
-
-  GNUNET_SERVER_suspend (server_handle);
-  /* Scheduled the task to clean up when shutdown is called */
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
-                                NULL);
-  keygen = GNUNET_CRYPTO_ecc_key_create_start (keyfile,
-                                               &key_generation_cb,
-                                               (void *) c);
-  GNUNET_free (keyfile);
-}
-
-
-/**
- * The main function for the mesh service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  int ret;
-  int r;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
-  r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
-                          NULL);
-  ret = (GNUNET_OK == r) ? 0 : 1;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");
-
-  INTERVAL_SHOW;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Mesh for peer [%s] FWD ACKs %u, BCK ACKs %u\n",
-              GNUNET_i2s(&my_full_id), debug_fwd_ack, debug_bck_ack);
-
-  return ret;
-}

Copied: gnunet/src/mesh/gnunet-service-mesh.c (from rev 27675, 
gnunet/src/mesh/gnunet-service-mesh-new.c)
===================================================================
--- gnunet/src/mesh/gnunet-service-mesh.c                               (rev 0)
+++ gnunet/src/mesh/gnunet-service-mesh.c       2013-06-28 14:34:55 UTC (rev 
27681)
@@ -0,0 +1,5204 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001-2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file mesh/gnunet-service-mesh.c
+ * @brief GNUnet MESH service
+ * @author Bartlomiej Polot
+ *
+ * TODO:
+ * - relay corking down to core
+ * - set ttl relative to path length
+ * - add signatures
+ * - add encryption
+ * - keep queues until receiving ACK
+ * TODO END
+ */
+
+#include "platform.h"
+#include "mesh.h"
+#include "mesh_protocol.h"
+#include "mesh_path.h"
+#include "block_mesh.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_statistics_service.h"
+
+#define MESH_BLOOM_SIZE         128
+
+#define MESH_DEBUG_DHT          GNUNET_NO
+#define MESH_DEBUG_CONNECTION   GNUNET_NO
+#define MESH_DEBUG_TIMING       __LINUX__ && GNUNET_NO
+
+#define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
+                                  GNUNET_TIME_UNIT_MINUTES,\
+                                  10)
+
+#if MESH_DEBUG_CONNECTION
+#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+#else
+#define DEBUG_CONN(...)
+#endif
+
+#if MESH_DEBUG_DHT
+#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+#else
+#define DEBUG_DHT(...)
+#endif
+
+#if MESH_DEBUG_TIMING
+#include <time.h>
+double __sum;
+uint64_t __count;
+struct timespec __mesh_start;
+struct timespec __mesh_end;
+#define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start))
+#define INTERVAL_END \
+do {\
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\
+  double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\
+  if (__diff < 0) __diff += 1000000000;\
+  __sum += __diff;\
+  __count++;\
+} while (0)
+#define INTERVAL_SHOW \
+if (0 < __count)\
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", 
__sum/__count)
+#else
+#define INTERVAL_START
+#define INTERVAL_END
+#define INTERVAL_SHOW
+#endif
+
+/******************************************************************************/
+/************************      DATA STRUCTURES     
****************************/
+/******************************************************************************/
+
+/** FWD declaration */
+struct MeshPeerInfo;
+struct MeshClient;
+
+
+/**
+ * Struct containing info about a queued transmission to this peer
+ */
+struct MeshPeerQueue
+{
+    /**
+      * DLL next
+      */
+  struct MeshPeerQueue *next;
+
+    /**
+      * DLL previous
+      */
+  struct MeshPeerQueue *prev;
+
+    /**
+     * Peer this transmission is directed to.
+     */
+  struct MeshPeerInfo *peer;
+
+    /**
+     * Tunnel this message belongs to.
+     */
+  struct MeshTunnel *tunnel;
+
+    /**
+     * Pointer to info stucture used as cls.
+     */
+  void *cls;
+
+    /**
+     * Type of message
+     */
+  uint16_t type;
+
+    /**
+     * Size of the message
+     */
+  size_t size;
+};
+
+
+/**
+ * Struct containing all information regarding a given peer
+ */
+struct MeshPeerInfo
+{
+    /**
+     * ID of the peer
+     */
+  GNUNET_PEER_Id id;
+
+    /**
+     * Last time we heard from this peer
+     */
+  struct GNUNET_TIME_Absolute last_contact;
+
+    /**
+     * Number of attempts to reconnect so far
+     */
+  int n_reconnect_attempts;
+
+    /**
+     * Paths to reach the peer, ordered by ascending hop count
+     */
+  struct MeshPeerPath *path_head;
+
+    /**
+     * Paths to reach the peer, ordered by ascending hop count
+     */
+  struct MeshPeerPath *path_tail;
+
+    /**
+     * Handle to stop the DHT search for a path to this peer
+     */
+  struct GNUNET_DHT_GetHandle *dhtget;
+
+    /**
+     * Array of tunnels this peer is the target of.
+     * Most probably a small amount, therefore not a hashmap.
+     * When the path to the peer changes, notify these tunnels to let them
+     * re-adjust their path trees.
+     */
+  struct MeshTunnel **tunnels;
+
+    /**
+     * Number of tunnels this peers participates in
+     */
+  unsigned int ntunnels;
+
+   /**
+    * Transmission queue to core DLL head
+    */
+  struct MeshPeerQueue *queue_head;
+
+   /**
+    * Transmission queue to core DLL tail
+    */
+   struct MeshPeerQueue *queue_tail;
+
+   /**
+    * How many messages are in the queue to this peer.
+    */
+   unsigned int queue_n;
+
+   /**
+    * Handle for queued transmissions
+    */
+  struct GNUNET_CORE_TransmitHandle *core_transmit;
+};
+
+
+/**
+ * Struct to encapsulate all the Flow Control information to a peer in the
+ * context of a tunnel: Same peer in different tunnels will have independent
+ * flow control structures, allowing to choke/free tunnels according to its
+ * own criteria.
+ */
+struct MeshFlowControl
+{
+  /**
+   * ID of the last packet sent towards the peer.
+   */
+  uint32_t last_pid_sent;
+
+  /**
+   * ID of the last packet received from the peer.
+   */
+  uint32_t last_pid_recv;
+
+  /**
+   * Last ACK sent to the peer (peer can't send more than this PID).
+   */
+  uint32_t last_ack_sent;
+
+  /**
+   * Last ACK sent towards the origin (for traffic towards leaf node).
+   */
+  uint32_t last_ack_recv;
+
+  /**
+   * How many payload messages are in the queue towards this peer.
+   */
+  uint32_t queue_n;
+
+  /**
+   * Task to poll the peer in case of a lost ACK causes stall.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier poll_task;
+
+  /**
+   * How frequently to poll for ACKs.
+   */
+  struct GNUNET_TIME_Relative poll_time;
+
+  /**
+   * On which tunnel to poll.
+   * Using an explicit poll_ctx would not help memory wise,
+   * since the allocated context would have to be stored in the
+   * fc struct in order to free it upon cancelling poll_task.
+   */
+  struct MeshTunnel *t;
+};
+
+
+/**
+ * Globally unique tunnel identification (owner + number)
+ * DO NOT USE OVER THE NETWORK
+ */
+struct MESH_TunnelID
+{
+    /**
+     * Node that owns the tunnel
+     */
+  GNUNET_PEER_Id oid;
+
+    /**
+     * Tunnel number to differentiate all the tunnels owned by the node oid
+     * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
+     */
+  MESH_TunnelNumber tid;
+};
+
+
+/**
+ * Struct containing all information regarding a tunnel
+ * For an intermediate node the improtant info used will be:
+ * - id        Tunnel unique identification
+ * - paths[0]  To know where to send it next
+ * - metainfo: ready, speeds, accounting
+ */
+struct MeshTunnel
+{
+    /**
+     * Tunnel ID
+     */
+  struct MESH_TunnelID id;
+
+    /**
+     * Port of the tunnel.
+     */
+  uint32_t port;
+
+    /**
+     * State of the tunnel.
+     */
+  enum MeshTunnelState state;
+
+    /**
+     * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
+     */
+  MESH_TunnelNumber local_tid;
+
+    /**
+     * Local tunnel number for local destination clients (incoming number)
+     * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same
+     * number.
+     */
+  MESH_TunnelNumber local_tid_dest;
+
+    /**
+     * Is the tunnel bufferless (minimum latency)?
+     */
+  int nobuffer;
+
+    /**
+     * Force sending ACK? Flag to allow duplicate ACK on POLL.
+     */
+  int force_ack;
+
+    /**
+     * How many messages do we accept in the forward queue.
+     */
+  unsigned int queue_max;
+
+    /**
+     * Last time the tunnel was used
+     */
+  struct GNUNET_TIME_Absolute timestamp;
+
+    /**
+     * Destination of the tunnel.
+     */
+  GNUNET_PEER_Id dest;
+
+    /**
+     * Next hop in the tunnel. If 0, @c client must be set.
+     */
+  GNUNET_PEER_Id next_hop;
+
+    /**
+     * Previous hop in the tunnel. If 0, @c owner must be set.
+     */
+  GNUNET_PEER_Id prev_hop;
+
+    /**
+     * Flow control information about @c next_hop or @c client.
+     */
+  struct MeshFlowControl next_fc;
+
+  /**
+   * Flow control information about @c prev_hop or @c owner.
+   */
+  struct MeshFlowControl prev_fc;
+
+    /**
+     * Client owner of the tunnel, if any
+     */
+  struct MeshClient *owner;
+
+    /**
+     * Client destination of the tunnel, if any.
+     */
+  struct MeshClient *client;
+
+    /**
+     * Task to keep the used paths alive at the owner,
+     * time tunnel out on all the other peers.
+     */
+  GNUNET_SCHEDULER_TaskIdentifier maintenance_task;
+
+    /**
+     * Path being used for the tunnel.
+     */
+  struct MeshPeerPath *path;
+
+    /**
+     * Flag to signal the destruction of the tunnel.
+     * If this is set GNUNET_YES the tunnel will be destroyed
+     * when the queue is empty.
+     */
+  int destroy;
+
+    /**
+     * Total messages pending for this tunnels, payload or not.
+     */
+  unsigned int pending_messages;
+};
+
+
+/**
+ * Struct containing information about a client of the service
+ * 
+ * TODO: add a list of 'waiting' ports
+ */
+struct MeshClient
+{
+    /**
+     * Linked list next
+     */
+  struct MeshClient *next;
+
+    /**
+     * Linked list prev
+     */
+  struct MeshClient *prev;
+
+    /**
+     * Tunnels that belong to this client, indexed by local id
+     */
+  struct GNUNET_CONTAINER_MultiHashMap *own_tunnels;
+
+   /**
+     * Tunnels this client has accepted, indexed by incoming local id
+     */
+  struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
+
+    /**
+     * Handle to communicate with the client
+     */
+  struct GNUNET_SERVER_Client *handle;
+
+    /**
+     * Ports that this client has declared interest in.
+     * Indexed by a GMC_hash32 (type), contains *Client.
+     */
+  struct GNUNET_CONTAINER_MultiHashMap *ports;
+
+    /**
+     * Whether the client is active or shutting down (don't send confirmations
+     * to a client that is shutting down.
+     */
+  int shutting_down;
+
+    /**
+     * ID of the client, mainly for debug messages
+     */
+  unsigned int id;
+
+};
+
+
+/******************************************************************************/
+/************************      DEBUG FUNCTIONS     
****************************/
+/******************************************************************************/
+
+#if MESH_DEBUG
+/**
+ * GNUNET_SCHEDULER_Task for printing a message after some operation is done
+ * @param cls string to print
+ * @param success  GNUNET_OK if the PUT was transmitted,
+ *                GNUNET_NO on timeout,
+ *                GNUNET_SYSERR on disconnect from service
+ *                after the PUT message was transmitted
+ *                (so we don't know if it was received or not)
+ */
+
+#if 0
+static void
+mesh_debug (void *cls, int success)
+{
+  char *s = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
+}
+#endif
+
+/* FIXME */
+unsigned int debug_fwd_ack;
+unsigned int debug_bck_ack;
+
+#endif
+
+/******************************************************************************/
+/***********************      GLOBAL VARIABLES     
****************************/
+/******************************************************************************/
+
+/************************** Configuration parameters 
**************************/
+
+/**
+ * How often to send tunnel keepalives. Tunnels timeout after 4 missed.
+ */
+static struct GNUNET_TIME_Relative refresh_path_time;
+
+/**
+ * How often to PUT own ID in the DHT.
+ */
+static struct GNUNET_TIME_Relative id_announce_time;
+
+/**
+ * Maximum time allowed to connect to a peer found by string.
+ */
+static struct GNUNET_TIME_Relative connect_timeout;
+
+/**
+ * Default TTL for payload packets.
+ */
+static unsigned long long default_ttl;
+
+/**
+ * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
+ */
+static unsigned long long dht_replication_level;
+
+/**
+ * How many tunnels are we willing to maintain.
+ * Local tunnels are always allowed, even if there are more tunnels than max.
+ */
+static unsigned long long max_tunnels;
+
+/**
+ * How many messages *in total* are we willing to queue, divided by number of 
+ * tunnels to get tunnel queue size.
+ */
+static unsigned long long max_msgs_queue;
+
+/**
+ * How many peers do we want to remember?
+ */
+static unsigned long long max_peers;
+
+
+/*************************** Static global variables 
**************************/
+
+/**
+ * Hostkey generation context
+ */
+static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen;
+
+/**
+ * DLL with all the clients, head.
+ */
+static struct MeshClient *clients_head;
+
+/**
+ * DLL with all the clients, tail.
+ */
+static struct MeshClient *clients_tail;
+
+/**
+ * Tunnels known, indexed by MESH_TunnelID (MeshTunnel).
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
+
+/**
+ * Number of tunnels known.
+ */
+static unsigned long long n_tunnels;
+
+/**
+ * Tunnels incoming, indexed by MESH_TunnelNumber
+ * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV).
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
+
+/**
+ * Peers known, indexed by PeerIdentity (MeshPeerInfo).
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *peers;
+
+/*
+ * Handle to communicate with transport
+ */
+// static struct GNUNET_TRANSPORT_Handle *transport_handle;
+
+/**
+ * Handle to communicate with core.
+ */
+static struct GNUNET_CORE_Handle *core_handle;
+
+/**
+ * Handle to use DHT.
+ */
+static struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * Handle to server.
+ */
+static struct GNUNET_SERVER_Handle *server_handle;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Notification context, to send messages to local clients.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+/**
+ * Local peer own ID (memory efficient handle).
+ */
+static GNUNET_PEER_Id myid;
+
+/**
+ * Local peer own ID (full value).
+ */
+static struct GNUNET_PeerIdentity my_full_id;
+
+/**
+ * Own private key.
+ */
+static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
+
+/**
+ * Own public key.
+ */
+static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key;
+
+/**
+ * Tunnel ID for the next created tunnel (global tunnel number).
+ */
+static MESH_TunnelNumber next_tid;
+
+/**
+ * Tunnel ID for the next incoming tunnel (local tunnel number).
+ */
+static MESH_TunnelNumber next_local_tid;
+
+/**
+ * All ports clients of this peer have opened.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *ports;
+
+/**
+ * Task to periodically announce itself in the network.
+ */
+GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
+
+/**
+ * Next ID to assign to a client.
+ */
+unsigned int next_client_id;
+
+
+/******************************************************************************/
+/***********************         DECLARATIONS        
**************************/
+/******************************************************************************/
+
+/**
+ * Function to process paths received for a new peer addition. The recorded
+ * paths form the initial tunnel, which can be optimized later.
+ * Called on each result obtained for the DHT search.
+ *
+ * @param cls closure
+ * @param exp when will this value expire
+ * @param key key of the result
+ * @param type type of the result
+ * @param size number of bytes in data
+ * @param data pointer to the result data
+ */
+static void
+dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
+                    const struct GNUNET_HashCode * key,
+                    const struct GNUNET_PeerIdentity *get_path,
+                    unsigned int get_path_length,
+                    const struct GNUNET_PeerIdentity *put_path,
+                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
+                    size_t size, const void *data);
+
+
+/**
+ * Retrieve the MeshPeerInfo stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer Full identity of the peer.
+ *
+ * @return Existing or newly created peer info.
+ */
+static struct MeshPeerInfo *
+peer_get (const struct GNUNET_PeerIdentity *peer);
+
+
+/**
+ * Retrieve the MeshPeerInfo stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer Short identity of the peer.
+ *
+ * @return Existing or newly created peer info.
+ */
+static struct MeshPeerInfo *
+peer_get_short (const GNUNET_PEER_Id peer);
+
+
+/**
+ * Build a PeerPath from the paths returned from the DHT, reversing the paths
+ * to obtain a local peer -> destination path and interning the peer ids.
+ *
+ * @return Newly allocated and created path
+ */
+static struct MeshPeerPath *
+path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
+                     unsigned int get_path_length,
+                     const struct GNUNET_PeerIdentity *put_path,
+                     unsigned int put_path_length);
+
+
+/**
+ * Adds a path to the peer_infos of all the peers in the path
+ *
+ * @param p Path to process.
+ * @param confirmed Whether we know if the path works or not.
+ */
+static void
+path_add_to_peers (struct MeshPeerPath *p, int confirmed);
+
+
+
+/**
+ * Search for a tunnel by global ID using full PeerIdentities.
+ *
+ * @param oid owner of the tunnel.
+ * @param tid global tunnel number.
+ *
+ * @return tunnel handler, NULL if doesn't exist.
+ */
+static struct MeshTunnel *
+tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
+
+
+/**
+ * Notify a tunnel that a connection has broken that affects at least
+ * some of its peers.
+ *
+ * @param t Tunnel affected.
+ * @param p1 Peer that got disconnected from p2.
+ * @param p2 Peer that got disconnected from p1.
+ *
+ * @return Short ID of the peer disconnected (either p1 or p2).
+ *         0 if the tunnel remained unaffected.
+ */
+static GNUNET_PEER_Id
+tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
+                                 GNUNET_PEER_Id p2);
+
+
+/**
+ * @brief Use the given path for the tunnel.
+ * Update the next and prev hops (and RCs).
+ * (Re)start the path refresh in case the tunnel is locally owned.
+ * 
+ * @param t Tunnel to update.
+ * @param p Path to use.
+ */
+static void
+tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p);
+
+/**
+ * Tunnel is empty: destroy it.
+ * 
+ * Notifies all participants (peers, cleints) about the destruction.
+ * 
+ * @param t Tunnel to destroy. 
+ */
+static void
+tunnel_destroy_empty (struct MeshTunnel *t);
+
+/**
+ * @brief Queue and pass message to core when possible.
+ * 
+ * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status
+ * and accounts for it. In case the queue is full, the message is dropped and
+ * a break issued.
+ * 
+ * Otherwise, message is treated as internal and allowed to go regardless of 
+ * queue status.
+ *
+ * @param cls Closure (@c type dependant). It will be used by queue_send to
+ *            build the message to be sent if not already prebuilt.
+ * @param type Type of the message, 0 for a raw message.
+ * @param size Size of the message.
+ * @param dst Neighbor to send message to.
+ * @param t Tunnel this message belongs to.
+ */
+static void
+queue_add (void *cls, uint16_t type, size_t size,
+           struct MeshPeerInfo *dst, struct MeshTunnel *t);
+
+
+/**
+ * Free a transmission that was already queued with all resources
+ * associated to the request.
+ *
+ * @param queue Queue handler to cancel.
+ * @param clear_cls Is it necessary to free associated cls?
+ */
+static void
+queue_destroy (struct MeshPeerQueue *queue, int clear_cls);
+
+
+/**
+ * @brief Get the next transmittable message from the queue.
+ *
+ * This will be the head, except in the case of being a data packet
+ * not allowed by the destination peer.
+ *
+ * @param peer Destination peer.
+ *
+ * @return The next viable MeshPeerQueue element to send to that peer.
+ *         NULL when there are no transmittable messages.
+ */
+struct MeshPeerQueue *
+queue_get_next (const struct MeshPeerInfo *peer);
+
+
+/**
+ * Core callback to write a queued packet to core buffer
+ *
+ * @param cls Closure (peer info).
+ * @param size Number of bytes available in buf.
+ * @param buf Where the to write the message.
+ *
+ * @return number of bytes written to buf
+ */
+static size_t
+queue_send (void *cls, size_t size, void *buf);
+
+
+/******************************************************************************/
+/************************    PERIODIC FUNCTIONS    
****************************/
+/******************************************************************************/
+
+/**
+ * Periodically announce self id in the DHT
+ *
+ * @param cls closure
+ * @param tc task context
+ */
+static void
+announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PBlock block;
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
+    return;
+  }
+  /* TODO
+   * - Set data expiration in function of X
+   * - Adapt X to churn
+   */
+  DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
+
+  block.id = my_full_id;
+  GNUNET_DHT_put (dht_handle,   /* DHT handle */
+                  &my_full_id.hashPubKey,       /* Key to use */
+                  dht_replication_level,     /* Replication level */
+                  GNUNET_DHT_RO_RECORD_ROUTE | 
GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
+                  GNUNET_BLOCK_TYPE_MESH_PEER,       /* Block type */
+                  sizeof (block),  /* Size of the data */
+                  (const char *) &block, /* Data itself */
+                  GNUNET_TIME_UNIT_FOREVER_ABS,  /* Data expiration */
+                  GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
+                  NULL,         /* Continuation */
+                  NULL);        /* Continuation closure */
+  announce_id_task =
+      GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
+}
+
+
+/******************************************************************************/
+/******************      GENERAL HELPER FUNCTIONS      
************************/
+/******************************************************************************/
+
+
+/**
+ * Check if client has registered with the service and has not disconnected
+ *
+ * @param client the client to check
+ *
+ * @return non-NULL if client exists in the global DLL
+ */
+static struct MeshClient *
+client_get (struct GNUNET_SERVER_Client *client)
+{
+  struct MeshClient *c;
+
+  c = clients_head;
+  while (NULL != c)
+  {
+    if (c->handle == client)
+      return c;
+    c = c->next;
+  }
+  return NULL;
+}
+
+
+/**
+ * Deletes a tunnel from a client (either owner or destination). To be used on
+ * tunnel destroy.
+ *
+ * @param c Client whose tunnel to delete.
+ * @param t Tunnel which should be deleted.
+ */
+static void
+client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
+{
+  struct GNUNET_HashCode hash;
+
+  if (c == t->owner)
+  {
+    GMC_hash32 (t->local_tid, &hash);
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
+                                                         &hash,
+                                                         t));
+  }
+  else if (c == t->client)
+  {
+    GMC_hash32 (t->local_tid_dest, &hash);
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
+                                                         &hash,
+                                                         t));
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+}
+
+/**
+ * Notify the appropriate client that a new incoming tunnel was created.
+ *
+ * @param t Tunnel that was created.
+ */
+static void
+send_client_tunnel_create (struct MeshTunnel *t)
+{
+  struct GNUNET_MESH_TunnelMessage msg;
+
+  if (NULL == t->client)
+    return;
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
+  msg.tunnel_id = htonl (t->local_tid_dest);
+  msg.port = htonl (t->port);
+  GNUNET_PEER_resolve (t->id.oid, &msg.peer);
+  GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
+                                              &msg.header, GNUNET_NO);
+}
+
+
+/**
+ * Notify dest client that the incoming tunnel is no longer valid.
+ *
+ * @param c Client to notify..
+ * @param t Tunnel that is destroyed.
+ */
+static void
+send_client_tunnel_destroy (struct MeshClient *c, struct MeshTunnel *t)
+{
+  struct GNUNET_MESH_TunnelMessage msg;
+
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  if (c != t->client && c != t->owner)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
+  msg.tunnel_id = htonl (t->local_tid_dest);
+  msg.port = htonl (0);
+  memset(&msg.peer, 0, sizeof (msg.peer));
+  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
+                                              &msg.header, GNUNET_NO);
+}
+
+
+/**
+ * Iterator over all the peers to remove the oldest not-used entry.
+ *
+ * @param cls Closure (unsued).
+ * @param key ID of the peer.
+ * @param value Peer_Info of the peer.
+ *
+ * FIXME implement
+ */
+static int
+peer_info_timeout (void *cls,
+                   const struct GNUNET_HashCode *key,
+                   void *value)
+{
+  return GNUNET_YES;
+}
+
+/**
+ * Retrieve the MeshPeerInfo stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer Full identity of the peer.
+ *
+ * @return Existing or newly created peer info.
+ */
+static struct MeshPeerInfo *
+peer_get (const struct GNUNET_PeerIdentity *peer)
+{
+  struct MeshPeerInfo *peer_info;
+
+  peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
+  if (NULL == peer_info)
+  {
+    peer_info =
+        (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
+    if (GNUNET_CONTAINER_multihashmap_size (peers) > max_peers)
+    {
+      GNUNET_CONTAINER_multihashmap_iterate (peers,
+                                             &peer_info_timeout,
+                                             NULL);
+    }
+    GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+    peer_info->id = GNUNET_PEER_intern (peer);
+  }
+  peer_info->last_contact = GNUNET_TIME_absolute_get();
+
+  return peer_info;
+}
+
+
+/**
+ * Retrieve the MeshPeerInfo stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer Short identity of the peer.
+ *
+ * @return Existing or newly created peer info.
+ */
+static struct MeshPeerInfo *
+peer_get_short (const GNUNET_PEER_Id peer)
+{
+  struct GNUNET_PeerIdentity id;
+
+  GNUNET_PEER_resolve (peer, &id);
+  return peer_get (&id);
+}
+
+
+/**
+ * Choose the best path towards a peer considering the tunnel properties.
+ * 
+ * @param peer The destination peer.
+ * @param t The tunnel the path is for.
+ *
+ * @return Best current known path towards the peer, if any.
+ */
+static struct MeshPeerPath *
+peer_get_best_path (const struct MeshPeerInfo *peer, const struct MeshTunnel 
*t)
+{
+  struct MeshPeerPath *best_p;
+  struct MeshPeerPath *p;
+  unsigned int best_cost;
+  unsigned int cost;
+
+  best_p = p = peer->path_head;
+  best_cost = cost = p->length;
+  while (NULL != p)
+  {
+    if ((cost = p->length) < best_cost)
+    {
+      best_cost = cost;
+      best_p = p;
+    }
+        p = p->next;
+  }
+  return best_p;
+}
+
+/**
+  * Core callback to write a pre-constructed data packet to core buffer
+  *
+  * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
+  * @param size Number of bytes available in buf.
+  * @param buf Where the to write the message.
+  *
+  * @return number of bytes written to buf
+  */
+static size_t
+send_core_data_raw (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *msg = cls;
+  size_t total_size;
+
+  GNUNET_assert (NULL != msg);
+  total_size = ntohs (msg->size);
+
+  if (total_size > size)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  memcpy (buf, msg, total_size);
+  GNUNET_free (cls);
+  return total_size;
+}
+
+
+/**
+ * Sends an already built message to a peer, properly registrating
+ * all used resources.
+ *
+ * @param message Message to send. Function makes a copy of it.
+ * @param peer Short ID of the neighbor whom to send the message.
+ * @param t Tunnel on which this message is transmitted.
+ */
+static void
+send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                       GNUNET_PEER_Id peer,
+                       struct MeshTunnel *t)
+{
+  struct GNUNET_PeerIdentity id;
+  struct MeshPeerInfo *neighbor;
+  struct MeshPeerPath *p;
+  void *data;
+  size_t size;
+  uint16_t type;
+
+//   GNUNET_TRANSPORT_try_connect(); FIXME use?
+
+  if (0 == peer)
+    return;
+
+  size = ntohs (message->size);
+  data = GNUNET_malloc (size);
+  memcpy (data, message, size);
+  type = ntohs(message->type);
+  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type ||
+      GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
+  {
+    struct GNUNET_MESH_Data *u;
+
+    u = (struct GNUNET_MESH_Data *) data;
+    u->ttl = htonl (ntohl (u->ttl) - 1);
+  }
+  GNUNET_PEER_resolve (peer, &id);
+  neighbor = peer_get (&id);
+  for (p = neighbor->path_head; NULL != p; p = p->next)
+  {
+    if (2 >= p->length)
+    {
+      break;
+    }
+  }
+  if (NULL == p)
+  {
+#if MESH_DEBUG
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  %s IS NOT DIRECTLY CONNECTED\n",
+                GNUNET_i2s(&id));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  PATHS TO %s:\n",
+                GNUNET_i2s(&id));
+    for (p = neighbor->path_head; NULL != p; p = p->next)
+    {
+      struct GNUNET_PeerIdentity debug_id;
+      unsigned int i;
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "    path with %u hops through:\n",
+                  p->length);
+      for (i = 0; i < p->length; i++)
+      {
+        GNUNET_PEER_resolve(p->peers[i], &debug_id);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "      hop %u: %s\n",
+                    i, GNUNET_i2s(&debug_id));
+      }
+    }
+#endif
+    GNUNET_break (0); // FIXME sometimes fails (testing disconnect?)
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    " no direct connection to %s\n",
+                    GNUNET_i2s (&id));
+    GNUNET_free (data);
+    return;
+  }
+  if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type)
+    type = 0;
+  queue_add (data,
+             type,
+             size,
+             neighbor,
+             t);
+}
+
+
+/**
+ * Sends a CREATE PATH message for a path to a peer, properly registrating
+ * all used resources.
+ *
+ * @param t Tunnel for which the path is created.
+ */
+static void
+send_create_path (struct MeshTunnel *t)
+{
+  struct MeshPeerInfo *neighbor;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send create path\n");
+  neighbor = peer_get_short (t->next_hop);
+  queue_add (t,
+             GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE,
+             sizeof (struct GNUNET_MESH_CreateTunnel) +
+                (t->path->length * sizeof (struct GNUNET_PeerIdentity)),
+             neighbor,
+             t);
+  t->state = MESH_TUNNEL_WAITING;
+}
+
+
+/**
+ * Sends a PATH ACK message in reponse to a received PATH_CREATE directed to 
us.
+ *
+ * @param t Tunnel which to confirm.
+ */
+static void
+send_path_ack (struct MeshTunnel *t) 
+{
+  struct MeshPeerInfo *peer;
+
+  peer = peer_get_short (t->prev_hop);
+
+  queue_add (t,
+             GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
+             sizeof (struct GNUNET_MESH_PathACK),
+             peer,
+             t);
+}
+
+
+/**
+ * Try to establish a new connection to this peer in the given tunnel.
+ * If the peer doesn't have any path to it yet, try to get one.
+ * If the peer already has some path, send a CREATE PATH towards it.
+ *
+ * @param peer PeerInfo of the peer.
+ * @param t Tunnel for which to create the path, if possible.
+ */
+static void
+peer_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
+{
+  struct MeshPeerPath *p;
+
+  if (NULL != peer->path_head)
+  {
+    p = peer_get_best_path (peer, t);
+    tunnel_use_path (t, p);
+    send_create_path (t);
+  }
+  else if (NULL == peer->dhtget)
+  {
+    struct GNUNET_PeerIdentity id;
+
+    GNUNET_PEER_resolve (peer->id, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
+    peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
+                                         GNUNET_BLOCK_TYPE_MESH_PEER, /* type 
*/
+                                         &id.hashPubKey,     /* key to search 
*/
+                                         dht_replication_level, /* replication 
level */
+                                         GNUNET_DHT_RO_RECORD_ROUTE |
+                                         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
+                                         NULL,       /* xquery */
+                                         0,     /* xquery bits */
+                                         &dht_get_id_handler, peer);
+    t->state = MESH_TUNNEL_SEARCHING;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "There is no path but the DHT GET is already started.\n");
+  }
+}
+
+
+/**
+ * Destroy the peer_info and free any allocated resources linked to it
+ *
+ * @param pi The peer_info to destroy.
+ *
+ * @return GNUNET_OK on success
+ */
+static int
+peer_info_destroy (struct MeshPeerInfo *pi)
+{
+  struct GNUNET_PeerIdentity id;
+  struct MeshPeerPath *p;
+  struct MeshPeerPath *nextp;
+  unsigned int i;
+
+  GNUNET_PEER_resolve (pi->id, &id);
+  GNUNET_PEER_change_rc (pi->id, -1);
+
+  if (GNUNET_YES !=
+      GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "removing peer %s, not in hashmap\n", GNUNET_i2s (&id));
+  }
+  if (NULL != pi->dhtget)
+  {
+    GNUNET_DHT_get_stop (pi->dhtget);
+  }
+  p = pi->path_head;
+  while (NULL != p)
+  {
+    nextp = p->next;
+    GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p);
+    path_destroy (p);
+    p = nextp;
+  }
+  for (i = 0; i < pi->ntunnels; i++)
+    tunnel_destroy_empty (pi->tunnels[i]);
+  GNUNET_array_grow (pi->tunnels, pi->ntunnels, 0);
+  GNUNET_free (pi);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Remove all paths that rely on a direct connection between p1 and p2
+ * from the peer itself and notify all tunnels about it.
+ *
+ * @param peer PeerInfo of affected peer.
+ * @param p1 GNUNET_PEER_Id of one peer.
+ * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
+ *           no longer is.
+ *
+ * TODO: optimize (see below)
+ */
+static void
+peer_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
+                       GNUNET_PEER_Id p2)
+{
+  struct MeshPeerPath *p;
+  struct MeshPeerPath *next;
+  struct MeshPeerInfo *peer_d;
+  GNUNET_PEER_Id d;
+  unsigned int destroyed;
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n");
+  destroyed = 0;
+  for (p = peer->path_head; NULL != p; p = next)
+  {
+    next = p->next;
+    for (i = 0; i < (p->length - 1); i++)
+    {
+      if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
+          (p->peers[i] == p2 && p->peers[i + 1] == p1))
+      {
+        GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
+        path_destroy (p);
+        destroyed++;
+        break;
+      }
+    }
+  }
+  if (0 == destroyed)
+    return;
+
+  for (i = 0; i < peer->ntunnels; i++)
+  {
+    d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
+    if (0 == d)
+      continue;
+
+    peer_d = peer_get_short (d);
+    next = peer_get_best_path (peer_d, peer->tunnels[i]);
+    tunnel_use_path (peer->tunnels[i], next);
+    peer_connect (peer_d, peer->tunnels[i]);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n");
+}
+
+
+/**
+ * Add the path to the peer and update the path used to reach it in case this
+ * is the shortest.
+ *
+ * @param peer_info Destination peer to add the path to.
+ * @param path New path to add. Last peer must be the peer in arg 1.
+ *             Path will be either used of freed if already known.
+ * @param trusted Do we trust that this path is real?
+ */
+void
+peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
+                    int trusted)
+{
+  struct MeshPeerPath *aux;
+  unsigned int l;
+  unsigned int l2;
+
+  if ((NULL == peer_info) || (NULL == path))
+  {
+    GNUNET_break (0);
+    path_destroy (path);
+    return;
+  }
+  if (path->peers[path->length - 1] != peer_info->id)
+  {
+    GNUNET_break (0);
+    path_destroy (path);
+    return;
+  }
+  if (2 >= path->length && GNUNET_NO == trusted)
+  {
+    /* Only allow CORE to tell us about direct paths */
+    path_destroy (path);
+    return;
+  }
+  for (l = 1; l < path->length; l++)
+  {
+    if (path->peers[l] == myid)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
+      for (l2 = 0; l2 < path->length - l; l2++)
+      {
+        path->peers[l2] = path->peers[l + l2];
+      }
+      path->length -= l;
+      l = 1;
+      path->peers =
+          GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
+    }
+  }
+#if MESH_DEBUG
+  {
+    struct GNUNET_PeerIdentity id;
+
+    GNUNET_PEER_resolve (peer_info->id, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
+                path->length, GNUNET_i2s (&id));
+  }
+#endif
+  l = path_get_length (path);
+  if (0 == l)
+  {
+    path_destroy (path);
+    return;
+  }
+
+  GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
+  for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
+  {
+    l2 = path_get_length (aux);
+    if (l2 > l)
+    {
+      GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
+                                          peer_info->path_tail, aux, path);
+      return;
+    }
+    else
+    {
+      if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
+      {
+        path_destroy (path);
+        return;
+      }
+    }
+  }
+  GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
+                                    path);
+  return;
+}
+
+
+/**
+ * Add the path to the origin peer and update the path used to reach it in case
+ * this is the shortest.
+ * The path is given in peer_info -> destination, therefore we turn the path
+ * upside down first.
+ *
+ * @param peer_info Peer to add the path to, being the origin of the path.
+ * @param path New path to add after being inversed.
+ *             Path will be either used or freed.
+ * @param trusted Do we trust that this path is real?
+ */
+static void
+peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
+                              struct MeshPeerPath *path, int trusted)
+{
+  path_invert (path);
+  peer_info_add_path (peer_info, path, trusted);
+}
+
+
+/**
+ * Add a tunnel to the list of tunnels a peer participates in.
+ * Update the tunnel's destination.
+ * 
+ * @param p Peer to add to.
+ * @param t Tunnel to add.
+ */
+static void
+peer_info_add_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
+{
+  if (0 != t->dest)
+  {
+    GNUNET_break (t->dest == p->id);
+    return;
+  }
+  t->dest = p->id;
+  GNUNET_PEER_change_rc (t->dest, 1);
+  GNUNET_array_append (p->tunnels, p->ntunnels, t);
+}
+
+
+/**
+ * Remove a tunnel from the list of tunnels a peer participates in.
+ * Free the tunnel's destination.
+ * 
+ * @param p Peer to clean.
+ * @param t Tunnel to remove.
+ */
+static void
+peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t)
+{
+  unsigned int i;
+
+  if (t->dest == p->id)
+  {
+      GNUNET_PEER_change_rc (t->dest, -1);
+      t->dest = 0;
+  }
+  for (i = 0; i < p->ntunnels; i++)
+  {
+    if (p->tunnels[i] == t)
+    {
+      p->tunnels[i] = p->tunnels[p->ntunnels - 1];
+      GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1);
+      return;
+    }
+  }
+}
+
+
+/**
+ * Function called if the connection to the peer has been stalled for a while,
+ * possibly due to a missed ACK. Poll the peer about its ACK status.
+ *
+ * @param cls Closure (poll ctx).
+ * @param tc TaskContext.
+ */
+static void
+tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct MeshFlowControl *fc = cls;
+  struct GNUNET_MESH_Poll msg;
+  struct MeshTunnel *t = fc->t;
+  GNUNET_PEER_Id peer;
+
+  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    return;
+  }
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
+  msg.header.size = htons (sizeof (msg));
+  msg.tid = htonl (t->id.tid);
+  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
+
+  if (fc == &t->prev_fc)
+  {
+    peer = t->prev_hop;
+  }
+  else if (fc == &t->next_fc)
+  {
+    peer = t->next_hop;
+  }
+  else
+  {
+    GNUNET_break (0);
+    return;
+  }
+  send_prebuilt_message (&msg.header, peer, t);
+  fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
+  fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
+                                                &tunnel_poll, fc);
+}
+
+
+/**
+ * Build a PeerPath from the paths returned from the DHT, reversing the paths
+ * to obtain a local peer -> destination path and interning the peer ids.
+ *
+ * @return Newly allocated and created path
+ */
+static struct MeshPeerPath *
+path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
+                     unsigned int get_path_length,
+                     const struct GNUNET_PeerIdentity *put_path,
+                     unsigned int put_path_length)
+{
+  struct MeshPeerPath *p;
+  GNUNET_PEER_Id id;
+  int i;
+
+  p = path_new (1);
+  p->peers[0] = myid;
+  GNUNET_PEER_change_rc (myid, 1);
+  i = get_path_length;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   GET has %d hops.\n", i);
+  for (i--; i >= 0; i--)
+  {
+    id = GNUNET_PEER_intern (&get_path[i]);
+    if (p->length > 0 && id == p->peers[p->length - 1])
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
+      GNUNET_PEER_change_rc (id, -1);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from GET: %s.\n",
+                  GNUNET_i2s (&get_path[i]));
+      p->length++;
+      p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * 
p->length);
+      p->peers[p->length - 1] = id;
+    }
+  }
+  i = put_path_length;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   PUT has %d hops.\n", i);
+  for (i--; i >= 0; i--)
+  {
+    id = GNUNET_PEER_intern (&put_path[i]);
+    if (id == myid)
+    {
+      /* PUT path went through us, so discard the path up until now and start
+       * from here to get a much shorter (and loop-free) path.
+       */
+      path_destroy (p);
+      p = path_new (0);
+    }
+    if (p->length > 0 && id == p->peers[p->length - 1])
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
+      GNUNET_PEER_change_rc (id, -1);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from PUT: %s.\n",
+                  GNUNET_i2s (&put_path[i]));
+      p->length++;
+      p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * 
p->length);
+      p->peers[p->length - 1] = id;
+    }
+  }
+#if MESH_DEBUG
+  if (get_path_length > 0)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of GET: %s)\n",
+                GNUNET_i2s (&get_path[0]));
+  if (put_path_length > 0)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of PUT: %s)\n",
+                GNUNET_i2s (&put_path[0]));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   In total: %d hops\n",
+              p->length);
+  for (i = 0; i < p->length; i++)
+  {
+    struct GNUNET_PeerIdentity peer_id;
+
+    GNUNET_PEER_resolve (p->peers[i], &peer_id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "       %u: %s\n", p->peers[i],
+                GNUNET_i2s (&peer_id));
+  }
+#endif
+  return p;
+}
+
+
+/**
+ * Adds a path to the peer_infos of all the peers in the path
+ *
+ * @param p Path to process.
+ * @param confirmed Whether we know if the path works or not.
+ */
+static void
+path_add_to_peers (struct MeshPeerPath *p, int confirmed)
+{
+  unsigned int i;
+
+  /* TODO: invert and add */
+  for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
+  for (i++; i < p->length; i++)
+  {
+    struct MeshPeerInfo *aux;
+    struct MeshPeerPath *copy;
+
+    aux = peer_get_short (p->peers[i]);
+    copy = path_duplicate (p);
+    copy->length = i + 1;
+    peer_info_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
+  }
+}
+
+
+/**
+ * Send keepalive packets for a peer
+ *
+ * @param cls Closure (tunnel for which to send the keepalive).
+ * @param tc Notification context.
+ */
+static void
+path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Search for a tunnel among the incoming tunnels
+ *
+ * @param tid the local id of the tunnel
+ *
+ * @return tunnel handler, NULL if doesn't exist
+ */
+static struct MeshTunnel *
+tunnel_get_incoming (MESH_TunnelNumber tid)
+{
+  struct GNUNET_HashCode hash;
+
+  GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
+  GMC_hash32 (tid, &hash);
+  return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
+}
+
+
+/**
+ * Search for a tunnel among the tunnels for a client
+ *
+ * @param c the client whose tunnels to search in
+ * @param tid the local id of the tunnel
+ *
+ * @return tunnel handler, NULL if doesn't exist
+ */
+static struct MeshTunnel *
+tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
+{
+  if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+  {
+    return tunnel_get_incoming (tid);
+  }
+  else
+  {
+    struct GNUNET_HashCode hash;
+
+    GMC_hash32 (tid, &hash);
+    return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
+  }
+}
+
+
+/**
+ * Search for a tunnel by global ID using PEER_ID
+ *
+ * @param pi owner of the tunnel
+ * @param tid global tunnel number
+ *
+ * @return tunnel handler, NULL if doesn't exist
+ */
+static struct MeshTunnel *
+tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
+{
+  struct MESH_TunnelID id;
+  struct GNUNET_HashCode hash;
+
+  id.oid = pi;
+  id.tid = tid;
+
+  GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
+  return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
+}
+
+
+/**
+ * Search for a tunnel by global ID using full PeerIdentities
+ *
+ * @param oid owner of the tunnel
+ * @param tid global tunnel number
+ *
+ * @return tunnel handler, NULL if doesn't exist
+ */
+static struct MeshTunnel *
+tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
+{
+  return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
+}
+
+
+/**
+ * Add a client to a tunnel, initializing all needed data structures.
+ * 
+ * @param t Tunnel to which add the client.
+ * @param c Client which to add to the tunnel.
+ */
+static void
+tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c)
+{
+  struct GNUNET_HashCode hash;
+
+  if (NULL != t->client)
+  {
+    GNUNET_break(0);
+    return;
+  }
+  GMC_hash32 (t->local_tid_dest, &hash);
+  if (GNUNET_OK !=
+      GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+  {
+    GNUNET_break (0);
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+  {
+    GNUNET_break (0);
+    return;
+  }
+  t->client = c;
+}
+
+
+static void
+tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p)
+{
+  unsigned int own_pos;
+
+  for (own_pos = 0; own_pos < p->length; own_pos++)
+  {
+    if (p->peers[own_pos] == myid)
+      break;
+  }
+  if (own_pos > p->length - 1)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  if (own_pos < p->length - 1)
+    t->next_hop = p->peers[own_pos + 1];
+  else
+    t->next_hop = p->peers[own_pos];
+  GNUNET_PEER_change_rc (t->next_hop, 1);
+  if (0 < own_pos)
+    t->prev_hop = p->peers[own_pos - 1];
+  else
+    t->prev_hop = p->peers[0];
+  GNUNET_PEER_change_rc (t->prev_hop, 1);
+
+  if (NULL != t->path)
+    path_destroy (t->path);
+  t->path = path_duplicate (p);
+  if (0 == own_pos)
+  {
+    if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
+      GNUNET_SCHEDULER_cancel (t->maintenance_task);
+    t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time,
+                                                        &path_refresh, t);
+  }
+}
+
+
+/**
+ * Notifies a tunnel that a connection has broken that affects at least
+ * some of its peers. Sends a notification towards the root of the tree.
+ * In case the peer is the owner of the tree, notifies the client that owns
+ * the tunnel and tries to reconnect.
+ *
+ * @param t Tunnel affected.
+ * @param p1 Peer that got disconnected from p2.
+ * @param p2 Peer that got disconnected from p1.
+ *
+ * @return Short ID of the peer disconnected (either p1 or p2).
+ *         0 if the tunnel remained unaffected.
+ */
+static GNUNET_PEER_Id
+tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
+                                 GNUNET_PEER_Id p2)
+{
+//   if (myid != p1 && myid != p2) FIXME
+//   {
+//     return;
+//   }
+// 
+//   if (tree_get_predecessor (t->tree) != 0)
+//   {
+//     /* We are the peer still connected, notify owner of the disconnection. 
*/
+//     struct GNUNET_MESH_PathBroken msg;
+//     struct GNUNET_PeerIdentity neighbor;
+// 
+//     msg.header.size = htons (sizeof (msg));
+//     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
+//     GNUNET_PEER_resolve (t->id.oid, &msg.oid);
+//     msg.tid = htonl (t->id.tid);
+//     msg.peer1 = my_full_id;
+//     GNUNET_PEER_resolve (pid, &msg.peer2);
+//     GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
+//     send_prebuilt_message (&msg.header, &neighbor, t);
+//   }
+  return 0;
+}
+
+
+/**
+ * Build a local ACK message and send it to a local client.
+ * 
+ * @param t Tunnel on which to send the ACK.
+ * @param c Client to whom send the ACK.
+ * @param ack Value of the ACK.
+ */
+static void
+send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack)
+{
+  struct GNUNET_MESH_LocalAck msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
+  msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest);
+  msg.ack = htonl (ack); 
+  GNUNET_SERVER_notification_context_unicast(nc,
+                                              c->handle,
+                                              &msg.header,
+                                              GNUNET_NO);
+}
+
+/**
+ * Build an ACK message and queue it to send to the given peer.
+ * 
+ * @param t Tunnel on which to send the ACK.
+ * @param peer Peer to whom send the ACK.
+ * @param ack Value of the ACK.
+ */
+static void
+send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer,  uint32_t ack)
+{
+  struct GNUNET_MESH_ACK msg;
+
+  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
+  msg.pid = htonl (ack);
+  msg.tid = htonl (t->id.tid);
+
+  send_prebuilt_message (&msg.header, peer, t);
+}
+
+
+/**
+ * Send an ACK informing the predecessor about the available buffer space.
+ * In case there is no predecessor, inform the owning client.
+ * If buffering is off, send only on behalf of children or self if endpoint.
+ * If buffering is on, send when sent to children and buffer space is free.
+ * Note that although the name is fwd_ack, the FWD mean forward *traffic*,
+ * the ACK itself goes "back" (towards root).
+ * 
+ * @param t Tunnel on which to send the ACK.
+ * @param type Type of message that triggered the ACK transmission.
+ */
+static void
+tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
+{
+  uint32_t ack;
+
+  /* Is it after unicast retransmission? */
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "ACK due to FWD DATA retransmission\n");
+      if (GNUNET_YES == t->nobuffer)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
+        return;
+      }
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_ACK:
+    case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
+    case GNUNET_MESSAGE_TYPE_MESH_POLL:
+      t->force_ack = GNUNET_YES;
+      break;
+    default:
+      GNUNET_break (0);
+  }
+
+  /* Check if we need to transmit the ACK */
+  if (t->queue_max > t->next_fc.queue_n * 4 &&
+      GMC_is_pid_bigger(t->prev_fc.last_ack_sent, t->prev_fc.last_pid_recv) &&
+      GNUNET_NO == t->force_ack)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  t->qmax: %u, t->qn: %u\n",
+                t->queue_max, t->next_fc.queue_n);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  t->pid: %u, t->ack: %u\n",
+                t->prev_fc.last_pid_recv, t->prev_fc.last_ack_sent);
+    return;
+  }
+
+  /* Ok, ACK might be necessary, what PID to ACK? */
+  ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n;
+  if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
+    return;
+  }
+
+  t->prev_fc.last_ack_sent = ack;
+  if (NULL != t->owner)
+    send_local_ack (t, t->owner, ack);
+  else if (0 != t->prev_hop)
+    send_ack (t, t->prev_hop, ack);
+  else
+    GNUNET_break (0);
+  debug_fwd_ack++;
+  t->force_ack = GNUNET_NO;
+}
+
+
+/**
+ * Send an ACK informing the children node/client about the available
+ * buffer space.
+ * If buffering is off, send only on behalf of root (can be self).
+ * If buffering is on, send when sent to predecessor and buffer space is free.
+ * Note that although the name is bck_ack, the BCK mean backwards *traffic*,
+ * the ACK itself goes "forward" (towards children/clients).
+ * 
+ * @param t Tunnel on which to send the ACK.
+ * @param type Type of message that triggered the ACK transmission.
+ */
+static void
+tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type)
+{
+  uint32_t ack;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending BCK ACK on tunnel %u [%u] due to %s\n",
+              t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type));
+  /* Is it after data to_origin retransmission? */
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+      if (GNUNET_YES == t->nobuffer)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "    Not sending ACK, nobuffer + traffic\n");
+        return;
+      }
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_ACK:
+    case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
+    case GNUNET_MESSAGE_TYPE_MESH_POLL:
+      t->force_ack = GNUNET_YES;
+      break;
+    default:
+      GNUNET_break (0);
+  }
+
+  /* TODO: Check if we need to transmit the ACK (as in fwd) */
+
+  ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n;
+
+  if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "    Not sending ACK, not needed, last ack sent was %u\n",
+                t->next_fc.last_ack_sent);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "    Sending BCK ACK %u (last sent: %u)\n",
+              ack, t->next_fc.last_ack_sent);
+  t->next_fc.last_ack_sent = ack;
+
+  if (NULL != t->client)
+    send_local_ack (t, t->client, ack);
+  else if (0 != t->next_hop)
+    send_ack (t, t->next_hop, ack);
+  else
+    GNUNET_break (0);
+  t->force_ack = GNUNET_NO;
+}
+
+
+/**
+ * Modify the unicast message TID from global to local and send to client.
+ * 
+ * @param t Tunnel on which to send the message.
+ * @param msg Message to modify and send.
+ */
+static void
+tunnel_send_client_ucast (struct MeshTunnel *t,
+                          const struct GNUNET_MESH_Data *msg)
+{
+  struct GNUNET_MESH_Data *copy;
+  uint16_t size = ntohs (msg->header.size);
+  char cbuf[size];
+
+  if (size < sizeof (struct GNUNET_MESH_Data) +
+             sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (NULL == t->client)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  copy = (struct GNUNET_MESH_Data *) cbuf;
+  memcpy (copy, msg, size);
+  copy->tid = htonl (t->local_tid_dest);
+  GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
+                                              &copy->header, GNUNET_NO);
+}
+
+
+/**
+ * Modify the to_origin  message TID from global to local and send to client.
+ * 
+ * @param t Tunnel on which to send the message.
+ * @param msg Message to modify and send.
+ */
+static void
+tunnel_send_client_to_orig (struct MeshTunnel *t,
+                            const struct GNUNET_MESH_Data *msg)
+{
+  struct GNUNET_MESH_Data *copy;
+  uint16_t size = ntohs (msg->header.size);
+  char cbuf[size];
+
+  if (size < sizeof (struct GNUNET_MESH_Data) +
+             sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (NULL == t->owner)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  copy = (struct GNUNET_MESH_Data *) cbuf;
+  memcpy (cbuf, msg, size);
+  copy->tid = htonl (t->local_tid);
+  GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
+                                              &copy->header, GNUNET_NO);
+}
+
+
+/**
+ * @brief Re-initiate traffic to this peer if necessary.
+ *
+ * Check if there is traffic queued towards this peer
+ * and the core transmit handle is NULL (traffic was stalled).
+ * If so, call core tmt rdy.
+ *
+ * @param peer_id Short ID of peer to which initiate traffic.
+ */
+static void
+peer_unlock_queue(GNUNET_PEER_Id peer_id)
+{
+  struct MeshPeerInfo *peer;
+  struct GNUNET_PeerIdentity id;
+  struct MeshPeerQueue *q;
+  size_t size;
+
+  peer = peer_get_short (peer_id);
+  if (NULL != peer->core_transmit)
+    return;
+
+  q = queue_get_next (peer);
+  if (NULL == q)
+  {
+    /* Might br multicast traffic already sent to this particular peer but
+     * not to other children in this tunnel.
+     * This way t->queue_n would be > 0 but the queue of this particular peer
+     * would be empty.
+     */
+    return;
+  }
+  size = q->size;
+  GNUNET_PEER_resolve (peer->id, &id);
+  peer->core_transmit =
+        GNUNET_CORE_notify_transmit_ready(core_handle,
+                                          0,
+                                          0,
+                                          GNUNET_TIME_UNIT_FOREVER_REL,
+                                          &id,
+                                          size,
+                                          &queue_send,
+                                          peer);
+        return;
+}
+
+
+/**
+ * Send a message to all peers and clients in this tunnel that the tunnel
+ * is no longer valid. If some peer or client should not receive the message,
+ * should be zero'ed out before calling this function.
+ *
+ * @param t The tunnel whose peers and clients to notify.
+ */
+static void
+tunnel_send_destroy (struct MeshTunnel *t)
+{
+  struct GNUNET_MESH_TunnelDestroy msg;
+  struct GNUNET_PeerIdentity id;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);
+  GNUNET_PEER_resolve (t->id.oid, &msg.oid);
+  msg.tid = htonl (t->id.tid);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "  sending tunnel destroy for tunnel: %s [%X]\n",
+              GNUNET_i2s (&msg.oid), t->id.tid);
+
+  if (NULL == t->client && 0 != t->next_hop)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  child: %u\n", t->next_hop);
+    GNUNET_PEER_resolve (t->next_hop, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  sending forward to %s\n",
+                GNUNET_i2s (&id));
+    send_prebuilt_message (&msg.header, t->next_hop, t);
+  }
+  if (NULL == t->owner && 0 != t->prev_hop)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  parent: %u\n", t->prev_hop);
+    GNUNET_PEER_resolve (t->prev_hop, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  sending back to %s\n",
+                GNUNET_i2s (&id));
+    send_prebuilt_message (&msg.header, t->prev_hop, t);
+  }
+  if (NULL != t->owner)
+  {
+    send_client_tunnel_destroy (t->owner, t);
+  }
+  if (NULL != t->client)
+  {
+    send_client_tunnel_destroy (t->client, t);
+  }
+}
+
+
+/**
+ * Cancel all transmissions towards a neighbor that belongs to a certain 
tunnel.
+ *
+ * @param t Tunnel which to cancel.
+ * @param neighbor Short ID of the neighbor to whom cancel the transmissions.
+ */
+static void
+peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t)
+{
+  struct MeshPeerInfo *peer_info;
+  struct MeshPeerQueue *pq;
+  struct MeshPeerQueue *next;
+
+  if (0 == neighbor)
+    return; /* Was local peer, 0'ed in tunnel_destroy_iterator */
+  peer_info = peer_get_short (neighbor);
+  for (pq = peer_info->queue_head; NULL != pq; pq = next)
+  {
+    next = pq->next;
+    if (pq->tunnel == t)
+    {
+      if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type ||
+          GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type)
+      {
+        /* Should have been removed on destroy children */
+        GNUNET_break (0);
+      }
+      queue_destroy (pq, GNUNET_YES);
+    }
+  }
+  if (NULL == peer_info->queue_head && NULL != peer_info->core_transmit)
+  {
+    GNUNET_CORE_notify_transmit_ready_cancel(peer_info->core_transmit);
+    peer_info->core_transmit = NULL;
+  }
+}
+
+
+/**
+ * Destroy the tunnel.
+ * 
+ * This function does not generate any warning traffic to clients or peers.
+ * 
+ * Tasks:
+ * Remove the tunnel from peer_info's and clients' hashmaps.
+ * Cancel messages belonging to this tunnel queued to neighbors.
+ * Free any allocated resources linked to the tunnel.
+ *
+ * @param t the tunnel to destroy
+ *
+ * @return GNUNET_OK on success
+ */
+static int
+tunnel_destroy (struct MeshTunnel *t)
+{
+  struct MeshClient *c;
+  struct GNUNET_HashCode hash;
+  int r;
+
+  if (NULL == t)
+    return GNUNET_OK;
+
+  r = GNUNET_OK;
+  c = t->owner;
+#if MESH_DEBUG
+  {
+    struct GNUNET_PeerIdentity id;
+
+    GNUNET_PEER_resolve (t->id.oid, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s [%x]\n",
+                GNUNET_i2s (&id), t->id.tid);
+    if (NULL != c)
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+  }
+#endif
+
+  GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
+  if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
+  {
+    GNUNET_break (0);
+    r = GNUNET_SYSERR;
+  }
+
+  if (NULL != c)
+  {
+    GMC_hash32 (t->local_tid, &hash);
+    if (GNUNET_YES !=
+        GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
+    {
+      GNUNET_break (0);
+      r = GNUNET_SYSERR;
+    }
+  }
+
+  if (NULL != t->client)
+  {
+    c = t->client;
+    GMC_hash32 (t->local_tid_dest, &hash);
+    if (GNUNET_YES !=
+          GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
+    {
+      GNUNET_break (0);
+      r = GNUNET_SYSERR;
+    }
+    if (GNUNET_YES != 
+      GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
+    {
+      GNUNET_break (0);
+      r = GNUNET_SYSERR;
+    }
+  }
+
+  if (0 != t->prev_hop)
+  {
+    peer_cancel_queues (t->prev_hop, t);
+    GNUNET_PEER_change_rc (t->prev_hop, -1);
+  }
+  if (0 != t->next_hop)
+  {
+    peer_cancel_queues (t->next_hop, t);
+    GNUNET_PEER_change_rc (t->next_hop, -1);
+  }
+  if (0 != t->dest) {
+      peer_info_remove_tunnel (peer_get_short (t->dest), t);
+  }
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
+    GNUNET_SCHEDULER_cancel (t->maintenance_task);
+
+  n_tunnels--;
+  GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
+  path_destroy (t->path);
+  GNUNET_free (t);
+  return r;
+}
+
+/**
+ * Tunnel is empty: destroy it.
+ * 
+ * Notifies all participants (peers, cleints) about the destruction.
+ * 
+ * @param t Tunnel to destroy. 
+ */
+static void
+tunnel_destroy_empty (struct MeshTunnel *t)
+{
+  #if MESH_DEBUG
+  {
+    struct GNUNET_PeerIdentity id;
+
+    GNUNET_PEER_resolve (t->id.oid, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "executing destruction of empty tunnel %s [%X]\n",
+                GNUNET_i2s (&id), t->id.tid);
+  }
+  #endif
+
+  if (GNUNET_NO == t->destroy)
+    tunnel_send_destroy (t);
+  if (0 == t->pending_messages)
+    tunnel_destroy (t);
+  else
+    t->destroy = GNUNET_YES;
+}
+
+/**
+ * Initialize a Flow Control structure to the initial state.
+ * 
+ * @param fc Flow Control structure to initialize.
+ */
+static void
+fc_init (struct MeshFlowControl *fc)
+{
+  fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
+  fc->last_pid_recv = (uint32_t) -1;
+  fc->last_ack_sent = (uint32_t) -1; /* No traffic allowed yet */
+  fc->last_ack_recv = (uint32_t) -1;
+  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
+  fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
+  fc->queue_n = 0;
+}
+
+/**
+ * Create a new tunnel
+ * 
+ * @param owner Who is the owner of the tunnel (short ID).
+ * @param tid Tunnel Number of the tunnel.
+ * @param client Clients that owns the tunnel, NULL for foreign tunnels.
+ * @param local Tunnel Number for the tunnel, for the client point of view.
+ * 
+ * @return A new initialized tunnel. NULL on error.
+ */
+static struct MeshTunnel *
+tunnel_new (GNUNET_PEER_Id owner,
+            MESH_TunnelNumber tid,
+            struct MeshClient *client,
+            MESH_TunnelNumber local)
+{
+  struct MeshTunnel *t;
+  struct GNUNET_HashCode hash;
+
+  if (n_tunnels >= max_tunnels && NULL == client)
+    return NULL;
+
+  t = GNUNET_malloc (sizeof (struct MeshTunnel));
+  t->id.oid = owner;
+  t->id.tid = tid;
+  t->queue_max = (max_msgs_queue / max_tunnels) + 1;
+  t->owner = client;
+  fc_init (&t->next_fc);
+  fc_init (&t->prev_fc);
+  t->local_tid = local;
+  n_tunnels++;
+  GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO);
+
+  GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
+  if (GNUNET_OK !=
+      GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+  {
+    GNUNET_break (0);
+    tunnel_destroy (t);
+    if (NULL != client)
+    {
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
+    }
+    return NULL;
+  }
+
+  if (NULL != client)
+  {
+    GMC_hash32 (t->local_tid, &hash);
+    if (GNUNET_OK !=
+        GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t,
+                                          
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+    {
+      tunnel_destroy (t);
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
+      return NULL;
+    }
+  }
+
+  return t;
+}
+
+
+
+/**
+ * Iterator for deleting each tunnel whose client endpoint disconnected.
+ *
+ * @param cls Closure (client that has disconnected).
+ * @param key The hash of the local tunnel id (used to access the hashmap).
+ * @param value The value stored at the key (tunnel to destroy).
+ *
+ * @return GNUNET_OK, keep iterating.
+ */
+static int
+tunnel_destroy_iterator (void *cls,
+                         const struct GNUNET_HashCode * key,
+                         void *value)
+{
+  struct MeshTunnel *t = value;
+  struct MeshClient *c = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Tunnel %X / %X destroy, due to client %u shutdown.\n",
+              t->local_tid, t->local_tid_dest, c->id);
+  client_delete_tunnel (c, t);
+  if (c == t->client)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", 
c->id);
+    t->client = NULL;
+    if (0 != t->next_hop) { /* destroy could come before a path is used */
+        GNUNET_PEER_change_rc (t->next_hop, -1);
+        t->next_hop = 0;
+    }
+  }
+  else if (c == t->owner)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id);
+    t->owner = NULL;
+    if (0 != t->prev_hop) { /* destroy could come before a path is used */
+        GNUNET_PEER_change_rc (t->prev_hop, -1);
+        t->prev_hop = 0;
+    }
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+  tunnel_destroy_empty (t);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Timeout function, destroys tunnel if called
+ *
+ * @param cls Closure (tunnel to destroy).
+ * @param tc TaskContext
+ */
+static void
+tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct MeshTunnel *t = cls;
+  struct GNUNET_PeerIdentity id;
+
+  t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  GNUNET_PEER_resolve(t->id.oid, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Tunnel %s [%X] timed out. Destroying.\n",
+              GNUNET_i2s(&id), t->id.tid);
+  if (NULL != t->client)
+    send_client_tunnel_destroy (t->client, t);
+  tunnel_destroy (t); /* Do not notify other */
+}
+
+
+/**
+ * Resets the tunnel timeout. Starts it if no timeout was running.
+ *
+ * @param t Tunnel whose timeout to reset.
+ *
+ * TODO use heap to improve efficiency of scheduler.
+ */
+static void
+tunnel_reset_timeout (struct MeshTunnel *t)
+{
+  if (NULL != t->owner || 0 != t->local_tid || 0 == t->prev_hop)
+    return;
+  if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task)
+    GNUNET_SCHEDULER_cancel (t->maintenance_task);
+  t->maintenance_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (refresh_path_time, 4), &tunnel_timeout, 
t);
+}
+
+
+/******************************************************************************/
+/****************      MESH NETWORK HANDLER HELPERS     
***********************/
+/******************************************************************************/
+
+/**
+ * Function to send a create path packet to a peer.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+send_core_path_create (void *cls, size_t size, void *buf)
+{
+  struct MeshTunnel *t = cls;
+  struct GNUNET_MESH_CreateTunnel *msg;
+  struct GNUNET_PeerIdentity *peer_ptr;
+  struct MeshPeerPath *p = t->path;
+  size_t size_needed;
+  uint32_t opt;
+  int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n");
+  size_needed =
+      sizeof (struct GNUNET_MESH_CreateTunnel) +
+      p->length * sizeof (struct GNUNET_PeerIdentity);
+
+  if (size < size_needed || NULL == buf)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  msg = (struct GNUNET_MESH_CreateTunnel *) buf;
+  msg->header.size = htons (size_needed);
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
+  msg->tid = ntohl (t->id.tid);
+
+  opt = 0;
+  if (GNUNET_YES == t->nobuffer)
+    opt |= MESH_TUNNEL_OPT_NOBUFFER;
+  msg->opt = htonl (opt);
+  msg->port = htonl (t->port);
+
+  peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
+  for (i = 0; i < p->length; i++)
+  {
+    GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "CREATE PATH (%u bytes long) sent!\n", size_needed);
+  return size_needed;
+}
+
+
+/**
+ * Creates a path ack message in buf and frees all unused resources.
+ *
+ * @param cls closure (MeshTransmissionDescriptor)
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+send_core_path_ack (void *cls, size_t size, void *buf)
+{
+  struct MeshTunnel *t = cls;
+  struct GNUNET_MESH_PathACK *msg = buf;
+
+  GNUNET_assert (NULL != t);
+  if (sizeof (struct GNUNET_MESH_PathACK) > size)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  t->prev_fc.last_ack_sent = t->nobuffer ? 0 : t->queue_max - 1;
+  msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
+  GNUNET_PEER_resolve (t->id.oid, &msg->oid);
+  msg->tid = htonl (t->id.tid);
+  msg->peer_id = my_full_id;
+  msg->ack = htonl (t->prev_fc.last_ack_sent);
+
+  /* TODO add signature */
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n");
+  return sizeof (struct GNUNET_MESH_PathACK);
+}
+
+
+/**
+ * Free a transmission that was already queued with all resources
+ * associated to the request.
+ *
+ * @param queue Queue handler to cancel.
+ * @param clear_cls Is it necessary to free associated cls?
+ */
+static void
+queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
+{
+  struct MeshFlowControl *fc;
+
+  if (GNUNET_YES == clear_cls)
+  {
+    switch (queue->type)
+    {
+      case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO, "   cancelling TUNNEL_DESTROY\n");
+        GNUNET_break (GNUNET_YES == queue->tunnel->destroy);
+        /* fall through */
+      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+      case GNUNET_MESSAGE_TYPE_MESH_ACK:
+      case GNUNET_MESSAGE_TYPE_MESH_POLL:
+      case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "   prebuilt message\n");
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "   type %s\n",
+                    GNUNET_MESH_DEBUG_M2S (queue->type));
+        break;
+      case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type create path\n");
+        break;
+      default:
+        GNUNET_break (0);
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "   type %s unknown!\n",
+                    GNUNET_MESH_DEBUG_M2S (queue->type));
+    }
+    GNUNET_free_non_null (queue->cls);
+  }
+  GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head,
+                               queue->peer->queue_tail,
+                               queue);
+
+  /* Delete from appropriate fc in the tunnel */
+  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type ||
+      GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type )
+  {
+    if (queue->peer->id == queue->tunnel->prev_hop)
+      fc = &queue->tunnel->prev_fc;
+    else if (queue->peer->id == queue->tunnel->next_hop)
+      fc = &queue->tunnel->next_fc;
+    else
+    {
+      GNUNET_break (0);
+      return;
+    }
+    fc->queue_n--;
+  }
+  GNUNET_free (queue);
+}
+
+
+/**
+ * @brief Get the next transmittable message from the queue.
+ *
+ * This will be the head, except in the case of being a data packet
+ * not allowed by the destination peer.
+ *
+ * @param peer Destination peer.
+ *
+ * @return The next viable MeshPeerQueue element to send to that peer.
+ *         NULL when there are no transmittable messages.
+ */
+struct MeshPeerQueue *
+queue_get_next (const struct MeshPeerInfo *peer)
+{
+  struct MeshPeerQueue *q;
+
+  struct GNUNET_MESH_Data *dmsg;
+  struct MeshTunnel* t;
+  uint32_t pid;
+  uint32_t ack;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   selecting message\n");
+  for (q = peer->queue_head; NULL != q; q = q->next)
+  {
+    t = q->tunnel;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "*     %s\n",
+                GNUNET_MESH_DEBUG_M2S (q->type));
+    dmsg = (struct GNUNET_MESH_Data *) q->cls;
+    pid = ntohl (dmsg->pid);
+    switch (q->type)
+    {
+      case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+        ack = t->next_fc.last_ack_recv;
+        break;
+      case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+        ack = t->prev_fc.last_ack_recv;
+        break;
+      default:
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "*   OK!\n");
+        return q;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "*     ACK: %u, PID: %u\n",
+                ack, pid);
+    if (GNUNET_NO == GMC_is_pid_bigger (pid, ack))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "*   OK!\n");
+      return q;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "*     NEXT!\n");
+    }
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "*   nothing found\n");
+  return NULL;
+}
+
+
+static size_t
+queue_send (void *cls, size_t size, void *buf)
+{
+  struct MeshPeerInfo *peer = cls;
+  struct GNUNET_MessageHeader *msg;
+  struct MeshPeerQueue *queue;
+  struct MeshTunnel *t;
+  struct GNUNET_PeerIdentity dst_id;
+  struct MeshFlowControl *fc;
+  size_t data_size;
+  uint32_t pid;
+  uint16_t type;
+
+  peer->core_transmit = NULL;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send\n");
+  queue = queue_get_next (peer);
+
+  /* Queue has no internal mesh traffic nor sendable payload */
+  if (NULL == queue)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   not ready, return\n");
+    if (NULL == peer->queue_head)
+      GNUNET_break (0); /* Core tmt_rdy should've been canceled */
+    return 0;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   not empty\n");
+
+  GNUNET_PEER_resolve (peer->id, &dst_id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "*   towards %s\n",
+              GNUNET_i2s (&dst_id));
+  /* Check if buffer size is enough for the message */
+  if (queue->size > size)
+  {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "*   not enough room, reissue\n");
+      peer->core_transmit =
+          GNUNET_CORE_notify_transmit_ready (core_handle,
+                                             GNUNET_NO,
+                                             0,
+                                             GNUNET_TIME_UNIT_FOREVER_REL,
+                                             &dst_id,
+                                             queue->size,
+                                             &queue_send,
+                                             peer);
+      return 0;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   size ok\n");
+
+  t = queue->tunnel;
+  GNUNET_assert (0 < t->pending_messages);
+  t->pending_messages--;
+  type = 0;
+
+  /* Fill buf */
+  switch (queue->type)
+  {
+    case 0:
+    case GNUNET_MESSAGE_TYPE_MESH_ACK:
+    case GNUNET_MESSAGE_TYPE_MESH_POLL:
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN:
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY:
+    case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE:
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "*   raw: %s\n",
+                  GNUNET_MESH_DEBUG_M2S (queue->type));
+      /* Fall through */
+    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+      data_size = send_core_data_raw (queue->cls, size, buf);
+      msg = (struct GNUNET_MessageHeader *) buf;
+      type = ntohs (msg->type);
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   path create\n");
+      data_size = send_core_path_create (queue->cls, size, buf);
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   path ack\n");
+      data_size = send_core_path_ack (queue->cls, size, buf);
+      break;
+    default:
+      GNUNET_break (0);
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "*   type unknown: %u\n",
+                  queue->type);
+      data_size = 0;
+  }
+
+  /* Free queue, but cls was freed by send_core_* */
+  queue_destroy (queue, GNUNET_NO);
+
+  /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
+  pid = ((struct GNUNET_MESH_Data *) buf)->pid;
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+      t->next_fc.last_pid_sent = pid;
+      tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
+      break;
+    case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+      t->prev_fc.last_pid_sent = pid;
+      tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
+      break;
+    default:
+      break;
+  }
+
+  if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*  destroying tunnel!\n");
+    tunnel_destroy (t);
+  }
+
+  /* If more data in queue, send next */
+  queue = queue_get_next (peer);
+  if (NULL != queue)
+  {
+      struct GNUNET_PeerIdentity id;
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*   more data!\n");
+      GNUNET_PEER_resolve (peer->id, &id);
+      peer->core_transmit =
+          GNUNET_CORE_notify_transmit_ready(core_handle,
+                                            0,
+                                            0,
+                                            GNUNET_TIME_UNIT_FOREVER_REL,
+                                            &id,
+                                            queue->size,
+                                            &queue_send,
+                                            peer);
+  }
+  else if (NULL != peer->queue_head)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "*   %s stalled\n",
+                GNUNET_i2s (&my_full_id));
+    if (peer->id == t->next_hop)
+      fc = &t->next_fc;
+    else if (peer->id == t->prev_hop)
+      fc = &t->prev_fc;
+    else
+    {
+      GNUNET_break (0);
+      fc = NULL;
+    }
+    if (NULL != fc && GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
+    {
+      fc->t = t;
+      fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
+                                                    &tunnel_poll, fc);
+    }
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*  Return %d\n", data_size);
+  return data_size;
+}
+
+
+/**
+ * @brief Queue and pass message to core when possible.
+ * 
+ * If type is payload (UNICAST, TO_ORIGIN) checks for queue status and
+ * accounts for it. In case the queue is full, the message is dropped and
+ * a break issued.
+ * 
+ * Otherwise, message is treated as internal and allowed to go regardless of 
+ * queue status.
+ *
+ * @param cls Closure (@c type dependant). It will be used by queue_send to
+ *            build the message to be sent if not already prebuilt.
+ * @param type Type of the message, 0 for a raw message.
+ * @param size Size of the message.
+ * @param dst Neighbor to send message to.
+ * @param t Tunnel this message belongs to.
+ */
+static void
+queue_add (void *cls, uint16_t type, size_t size,
+           struct MeshPeerInfo *dst, struct MeshTunnel *t)
+{
+  struct MeshPeerQueue *queue;
+  struct GNUNET_PeerIdentity id;
+  unsigned int *n;
+
+  n = NULL;
+  if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type)
+  {
+    n = &t->next_fc.queue_n;
+  }
+  else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type)
+  {
+    n = &t->prev_fc.queue_n;
+  }
+  if (NULL != n)
+  {
+    if (*n >= t->queue_max)
+    {
+      GNUNET_break(0);
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "queue full: %u/%u\n",
+                  *n, t->queue_max);
+      GNUNET_STATISTICS_update(stats,
+                               "# messages dropped (buffer full)",
+                               1, GNUNET_NO);
+      return; /* Drop message */
+    }
+    (*n)++;
+  }
+  queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
+  queue->cls = cls;
+  queue->type = type;
+  queue->size = size;
+  queue->peer = dst;
+  queue->tunnel = t;
+  GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
+  if (NULL == dst->core_transmit)
+  {
+    GNUNET_PEER_resolve (dst->id, &id);
+    dst->core_transmit =
+        GNUNET_CORE_notify_transmit_ready (core_handle,
+                                           0,
+                                           0,
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           &id,
+                                           size,
+                                           &queue_send,
+                                           dst);
+  }
+  t->pending_messages++;
+}
+
+
+/******************************************************************************/
+/********************      MESH NETWORK HANDLERS     
**************************/
+/******************************************************************************/
+
+
+/**
+ * Core handler for path creation
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
+                         const struct GNUNET_MessageHeader *message)
+{
+  unsigned int own_pos;
+  uint16_t size;
+  uint16_t i;
+  MESH_TunnelNumber tid;
+  struct GNUNET_MESH_CreateTunnel *msg;
+  struct GNUNET_PeerIdentity *pi;
+  struct MeshPeerPath *path;
+  struct MeshPeerInfo *dest_peer_info;
+  struct MeshPeerInfo *orig_peer_info;
+  struct MeshTunnel *t;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received a path create msg [%s]\n",
+              GNUNET_i2s (&my_full_id));
+  size = ntohs (message->size);
+  if (size < sizeof (struct GNUNET_MESH_CreateTunnel))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+
+  size -= sizeof (struct GNUNET_MESH_CreateTunnel);
+  if (size % sizeof (struct GNUNET_PeerIdentity))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+  size /= sizeof (struct GNUNET_PeerIdentity);
+  if (size < 1)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
+  msg = (struct GNUNET_MESH_CreateTunnel *) message;
+
+  tid = ntohl (msg->tid);
+  pi = (struct GNUNET_PeerIdentity *) &msg[1];
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "    path is for tunnel %s[%X].\n", GNUNET_i2s (pi), tid);
+  t = tunnel_get (pi, tid);
+  if (NULL == t) /* might be a local tunnel */
+  {
+    uint32_t opt;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating tunnel\n");
+    t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0);
+    if (NULL == t)
+    {
+      GNUNET_break (0);
+      return GNUNET_OK;
+    }
+    t->port = ntohl (msg->port);
+    opt = ntohl (msg->opt);
+    if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER))
+    {
+      t->nobuffer = GNUNET_YES;
+      t->queue_max = 1;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  nobuffer:%d\n", t->nobuffer);
+
+    tunnel_reset_timeout (t);
+  }
+  t->state = MESH_TUNNEL_WAITING;
+  dest_peer_info =
+      GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
+  if (NULL == dest_peer_info)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  Creating PeerInfo for destination.\n");
+    dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
+    dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
+    GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
+                                       dest_peer_info,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  }
+  orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
+  if (NULL == orig_peer_info)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  Creating PeerInfo for origin.\n");
+    orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
+    orig_peer_info->id = GNUNET_PEER_intern (pi);
+    GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
+  path = path_new (size);
+  own_pos = 0;
+  for (i = 0; i < size; i++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
+                GNUNET_i2s (&pi[i]));
+    path->peers[i] = GNUNET_PEER_intern (&pi[i]);
+    if (path->peers[i] == myid)
+      own_pos = i;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
+  if (own_pos == 0 && path->peers[own_pos] != myid)
+  {
+    /* create path: self not found in path through self */
+    GNUNET_break_op (0);
+    path_destroy (path);
+    tunnel_destroy (t);
+    return GNUNET_OK;
+  }
+  path_add_to_peers (path, GNUNET_NO);
+  tunnel_use_path (t, path);
+
+  peer_info_add_tunnel (dest_peer_info, t);
+
+  if (own_pos == size - 1)
+  {
+    struct MeshClient *c;
+    struct GNUNET_HashCode hc;
+
+    /* Find target client */
+    GMC_hash32 (t->port, &hc);
+    c = GNUNET_CONTAINER_multihashmap_get (ports, &hc);
+    if (NULL == c)
+    {
+      /* TODO send reject */
+      return GNUNET_OK;
+    }
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
+    peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_YES);
+
+    /* Assign local tid */
+    while (NULL != tunnel_get_incoming (next_local_tid))
+      next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
+    t->local_tid_dest = next_local_tid++;
+    next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
+
+    tunnel_add_client (t, c);
+    send_client_tunnel_create (t);
+    send_path_ack (t);
+  }
+  else
+  {
+    struct MeshPeerPath *path2;
+
+    t->next_hop = path->peers[own_pos + 1];
+    GNUNET_PEER_change_rc(t->next_hop, 1);
+
+    /* It's for somebody else! Retransmit. */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
+    path2 = path_duplicate (path);
+    peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
+    peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
+    send_create_path (t);
+  }
+  return GNUNET_OK;
+}
+
+
+
+/**
+ * Core handler for path ACKs
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_PathACK *msg;
+  struct MeshPeerInfo *peer_info;
+  struct MeshPeerPath *p;
+  struct MeshTunnel *t;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
+              GNUNET_i2s (&my_full_id));
+  msg = (struct GNUNET_MESH_PathACK *) message;
+  t = tunnel_get (&msg->oid, ntohl(msg->tid));
+  if (NULL == t)
+  {
+    /* TODO notify that we don't know the tunnel */
+    GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, 
GNUNET_NO);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  don't know the tunnel %s [%X]!\n",
+                GNUNET_i2s (&msg->oid), ntohl(msg->tid));
+    return GNUNET_OK;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %s [%X]\n",
+              GNUNET_i2s (&msg->oid), ntohl(msg->tid));
+
+  peer_info = peer_get (&msg->peer_id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by peer %s\n",
+              GNUNET_i2s (&msg->peer_id));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
+              GNUNET_i2s (peer));
+
+  /* Add path to peers? */
+  p = t->path;
+  if (NULL != p)
+  {
+    path_add_to_peers (p, GNUNET_YES);
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+  t->state = MESH_TUNNEL_READY;
+  t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0;
+  t->prev_fc.last_ack_sent = ntohl (msg->ack);
+
+  /* Message for us? */
+  if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct 
GNUNET_PeerIdentity)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
+    if (NULL == t->owner)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_OK;
+    }
+    if (NULL != peer_info->dhtget)
+    {
+      GNUNET_DHT_get_stop (peer_info->dhtget);
+      peer_info->dhtget = NULL;
+    }
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
+    return GNUNET_OK;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "  not for us, retransmitting...\n");
+  peer_info = peer_get (&msg->oid);
+  send_prebuilt_message (message, t->prev_hop, t);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for notifications of broken paths
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
+                         const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_PathBroken *msg;
+  struct MeshTunnel *t;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer));
+  msg = (struct GNUNET_MESH_PathBroken *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
+              GNUNET_i2s (&msg->peer1));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
+              GNUNET_i2s (&msg->peer2));
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+  if (NULL == t)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+  tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1),
+                                   GNUNET_PEER_search (&msg->peer2));
+  return GNUNET_OK;
+
+}
+
+
+/**
+ * Core handler for tunnel destruction
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
+                            const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_TunnelDestroy *msg;
+  struct MeshTunnel *t;
+
+  msg = (struct GNUNET_MESH_TunnelDestroy *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got a TUNNEL DESTROY packet from %s\n",
+              GNUNET_i2s (peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "  for tunnel %s [%u]\n",
+              GNUNET_i2s (&msg->oid), ntohl (msg->tid));
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+  if (NULL == t)
+  {
+    /* Probably already got the message from another path,
+     * destroyed the tunnel and retransmitted to children.
+     * Safe to ignore.
+     */
+    GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
+                              1, GNUNET_NO);
+    return GNUNET_OK;
+  }
+  if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n",
+                t->local_tid, t->local_tid_dest);
+  }
+  if (GNUNET_PEER_search (peer) == t->prev_hop)
+  {
+    // TODO check owner's signature
+    // TODO add owner's signatue to tunnel for retransmission
+    peer_cancel_queues (t->prev_hop, t);
+    GNUNET_PEER_change_rc (t->prev_hop, -1);
+    t->prev_hop = 0;
+  }
+  else if (GNUNET_PEER_search (peer) == t->next_hop)
+  {
+    // TODO check dest's signature
+    // TODO add dest's signatue to tunnel for retransmission
+    peer_cancel_queues (t->next_hop, t);
+    GNUNET_PEER_change_rc (t->next_hop, -1);
+    t->next_hop = 0;
+  }
+  else
+  {
+    GNUNET_break_op (0);
+    // TODO check both owner AND destination's signature to see which matches
+    // TODO restransmit in appropriate direction
+    return GNUNET_OK;
+  }
+  tunnel_destroy_empty (t);
+
+  // TODO: add timeout to destroy the tunnel anyway
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for mesh network traffic going from the origin to a peer
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ * @param message message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
+                          const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_Data *msg;
+  struct MeshTunnel *t;
+  uint32_t pid;
+  uint32_t ttl;
+  size_t size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a unicast packet from %s\n",
+              GNUNET_i2s (peer));
+  /* Check size */
+  size = ntohs (message->size);
+  if (size <
+      sizeof (struct GNUNET_MESH_Data) +
+      sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+  msg = (struct GNUNET_MESH_Data *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
+              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
+  /* Check tunnel */
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+  if (NULL == t)
+  {
+    /* TODO notify back: we don't know this tunnel */
+    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+  pid = ntohl (msg->pid);
+  if (t->prev_fc.last_pid_recv == pid)
+  {
+    GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                " Already seen pid %u, DROPPING!\n", pid);
+    return GNUNET_OK;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                " pid %u not seen yet, forwarding\n", pid);
+  }
+
+  if (GMC_is_pid_bigger (pid, t->prev_fc.last_ack_sent))
+  {
+    GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO);
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received PID %u, ACK %u\n",
+                pid, t->prev_fc.last_ack_sent);
+    tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_POLL);
+    return GNUNET_OK;
+  }
+  t->prev_fc.last_pid_recv = pid;
+
+  tunnel_reset_timeout (t);
+  if (t->dest == myid)
+  {
+    /* TODO signature verification */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  it's for us! sending to clients...\n");
+    GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO);
+    tunnel_send_client_ucast (t, msg);
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST);
+    return GNUNET_OK;
+  }
+  if (0 == t->next_hop)
+  {
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+  ttl = ntohl (msg->ttl);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
+  if (ttl == 0)
+  {
+    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
+    return GNUNET_OK;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "  not for us, retransmitting...\n");
+
+  send_prebuilt_message (message, t->next_hop, t);
+  GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for mesh network traffic toward the owner of a tunnel
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
+                          const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_Data *msg;
+  struct MeshTunnel *t;
+  size_t size;
+  uint32_t pid;
+  uint32_t ttl;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n",
+              GNUNET_i2s (peer));
+  size = ntohs (message->size);
+  if (size < sizeof (struct GNUNET_MESH_Data) +     /* Payload must be */
+      sizeof (struct GNUNET_MessageHeader))     /* at least a header */
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+  msg = (struct GNUNET_MESH_Data *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n",
+              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+  pid = ntohl (msg->pid);
+
+  if (NULL == t)
+  {
+    /* TODO notify that we dont know this tunnel (whom)? */
+    GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received to_origin with PID %u on unknown tunnel %s [%u]\n",
+                pid, GNUNET_i2s (&msg->oid), ntohl (msg->tid));
+    return GNUNET_OK;
+  }
+
+  if (t->next_fc.last_pid_recv == pid)
+  {
+    /* already seen this packet, drop */
+    GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, 
GNUNET_NO);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                " Already seen pid %u, DROPPING!\n", pid);
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
+    return GNUNET_OK;
+  }
+
+  if (GMC_is_pid_bigger (pid, t->next_fc.last_ack_sent))
+  {
+    GNUNET_STATISTICS_update (stats, "# unsolicited to_orig", 1, GNUNET_NO);
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received PID %u, ACK %u\n",
+                pid, t->next_fc.last_ack_sent);
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
+    return GNUNET_OK;
+  }
+  t->next_fc.last_pid_recv = pid;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " pid %u not seen yet, forwarding\n", pid);
+
+  if (myid == t->id.oid)
+  {
+    /* TODO signature verification */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  it's for us! sending to clients...\n");
+    GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO);
+    tunnel_send_client_to_orig (t, msg);
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
+    return GNUNET_OK;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "  not for us, retransmitting...\n");
+
+  if (0 == t->prev_hop) /* No owner AND no prev hop */
+  {
+    if (GNUNET_YES == t->destroy)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "to orig received on a dying tunnel %s [%X]\n",
+                  GNUNET_i2s (&msg->oid), ntohl(msg->tid));
+      return GNUNET_OK;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "unknown to origin at %s\n",
+                GNUNET_i2s (&my_full_id));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "from peer %s\n",
+                GNUNET_i2s (peer));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                "on tunnel %s [%X]\n",
+                GNUNET_i2s (&msg->oid), ntohl(msg->tid));
+    return GNUNET_OK;
+  }
+  ttl = ntohl (msg->ttl);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
+  if (ttl == 0)
+  {
+    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
+    return GNUNET_OK;
+  }
+  send_prebuilt_message (message, t->prev_hop, t);
+  GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for mesh network traffic point-to-point acks.
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
+                 const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_ACK *msg;
+  struct MeshTunnel *t;
+  GNUNET_PEER_Id id;
+  uint32_t ack;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
+              GNUNET_i2s (peer));
+  msg = (struct GNUNET_MESH_ACK *) message;
+
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+
+  if (NULL == t)
+  {
+    /* TODO notify that we dont know this tunnel (whom)? */
+    GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO);
+    return GNUNET_OK;
+  }
+  ack = ntohl (msg->pid);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u\n", ack);
+
+  /* Is this a forward or backward ACK? */
+  id = GNUNET_PEER_search (peer);
+  if (t->next_hop == id)
+  {
+    debug_fwd_ack++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
+    if (GNUNET_SCHEDULER_NO_TASK != t->next_fc.poll_task &&
+        GMC_is_pid_bigger (ack, t->next_fc.last_ack_recv))
+    {
+      GNUNET_SCHEDULER_cancel (t->next_fc.poll_task);
+      t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
+      t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
+    }
+    t->next_fc.last_ack_recv = ack;
+    peer_unlock_queue (t->next_hop);
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
+  }
+  else if (t->prev_hop == id)
+  {
+    debug_bck_ack++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
+    if (GNUNET_SCHEDULER_NO_TASK != t->prev_fc.poll_task &&
+        GMC_is_pid_bigger (ack, t->prev_fc.last_ack_recv))
+    {
+      GNUNET_SCHEDULER_cancel (t->prev_fc.poll_task);
+      t->prev_fc.poll_task = GNUNET_SCHEDULER_NO_TASK;
+      t->prev_fc.poll_time = GNUNET_TIME_UNIT_SECONDS;
+    }
+    t->prev_fc.last_ack_recv = ack;
+    peer_unlock_queue (t->prev_hop);
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK);
+  }
+  else
+    GNUNET_break_op (0);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for mesh network traffic point-to-point ack polls.
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
+                  const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_Poll *msg;
+  struct MeshTunnel *t;
+  GNUNET_PEER_Id id;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n",
+              GNUNET_i2s (peer));
+
+  msg = (struct GNUNET_MESH_Poll *) message;
+
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+
+  if (NULL == t)
+  {
+    /* TODO notify that we dont know this tunnel (whom)? */
+    GNUNET_STATISTICS_update (stats, "# poll on unknown tunnel", 1, GNUNET_NO);
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+
+  /* Is this a forward or backward ACK? */
+  id = GNUNET_PEER_search(peer);
+  if (t->next_hop == id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  from FWD\n");
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
+  }
+  else if (t->prev_hop == id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  from BCK\n");
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL);
+  }
+  else
+    GNUNET_break (0);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for mesh keepalives.
+ *
+ * @param cls closure
+ * @param message message
+ * @param peer peer identity this notification is about
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ *
+ * TODO: Check who we got this from, to validate route.
+ */
+static int
+handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
+                       const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_TunnelKeepAlive *msg;
+  struct MeshTunnel *t;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
+              GNUNET_i2s (peer));
+
+  msg = (struct GNUNET_MESH_TunnelKeepAlive *) message;
+  t = tunnel_get (&msg->oid, ntohl (msg->tid));
+
+  if (NULL == t)
+  {
+    /* TODO notify that we dont know that tunnel */
+    GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1,
+                              GNUNET_NO);
+    return GNUNET_OK;
+  }
+
+  tunnel_reset_timeout (t);
+
+  GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
+  send_prebuilt_message (message, t->next_hop, t);
+  return GNUNET_OK;
+  }
+
+
+
+/**
+ * Functions to handle messages from core
+ */
+static struct GNUNET_CORE_MessageHandler core_handlers[] = {
+  {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
+  {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
+   sizeof (struct GNUNET_MESH_PathBroken)},
+  {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY,
+   sizeof (struct GNUNET_MESH_TunnelDestroy)},
+  {&handle_mesh_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
+  {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE,
+    sizeof (struct GNUNET_MESH_TunnelKeepAlive)},
+  {&handle_mesh_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
+  {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
+    sizeof (struct GNUNET_MESH_ACK)},
+  {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
+    sizeof (struct GNUNET_MESH_Poll)},
+  {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
+   sizeof (struct GNUNET_MESH_PathACK)},
+  {NULL, 0, 0}
+};
+
+
+
+/******************************************************************************/
+/****************       MESH LOCAL HANDLER HELPERS      
***********************/
+/******************************************************************************/
+
+
+#if LATER
+/**
+ * notify_client_connection_failure: notify a client that the connection to the
+ * requested remote peer is not possible (for instance, no route found)
+ * Function called when the socket is ready to queue more data. "buf" will be
+ * NULL and "size" zero if the socket was closed for writing in the meantime.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+notify_client_connection_failure (void *cls, size_t size, void *buf)
+{
+  int size_needed;
+  struct MeshPeerInfo *peer_info;
+  struct GNUNET_MESH_PeerControl *msg;
+  struct GNUNET_PeerIdentity id;
+
+  if (0 == size && NULL == buf)
+  {
+    // TODO retry? cancel?
+    return 0;
+  }
+
+  size_needed = sizeof (struct GNUNET_MESH_PeerControl);
+  peer_info = (struct MeshPeerInfo *) cls;
+  msg = (struct GNUNET_MESH_PeerControl *) buf;
+  msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
+//     msg->tunnel_id = htonl(peer_info->t->tid);
+  GNUNET_PEER_resolve (peer_info->id, &id);
+  memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
+
+  return size_needed;
+}
+#endif
+
+
+/**
+ * Send keepalive packets for a tunnel.
+ *
+ * @param cls Closure (tunnel for which to send the keepalive).
+ * @param tc Notification context.
+ * 
+ * FIXME: add a refresh reset in case of normal unicast traffic is doing the 
job
+ */
+static void
+path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct MeshTunnel *t = cls;
+  struct GNUNET_MESH_TunnelKeepAlive *msg;
+  size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive);
+  char cbuf[size];
+
+  t->maintenance_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) ||
+      NULL == t->owner || 0 == t->local_tid)
+  {
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "sending keepalive for tunnel %d\n", t->id.tid);
+
+  msg = (struct GNUNET_MESH_TunnelKeepAlive *) cbuf;
+  msg->header.size = htons (size);
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
+  msg->oid = my_full_id;
+  msg->tid = htonl (t->id.tid);
+  send_prebuilt_message (&msg->header, t->next_hop, t);
+
+  t->maintenance_task =
+      GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t);
+}
+
+
+/**
+ * Function to process paths received for a new peer addition. The recorded
+ * paths form the initial tunnel, which can be optimized later.
+ * Called on each result obtained for the DHT search.
+ *
+ * @param cls closure
+ * @param exp when will this value expire
+ * @param key key of the result
+ * @param get_path path of the get request
+ * @param get_path_length lenght of get_path
+ * @param put_path path of the put request
+ * @param put_path_length length of the put_path
+ * @param type type of the result
+ * @param size number of bytes in data
+ * @param data pointer to the result data
+ */
+static void
+dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
+                    const struct GNUNET_HashCode * key,
+                    const struct GNUNET_PeerIdentity *get_path,
+                    unsigned int get_path_length,
+                    const struct GNUNET_PeerIdentity *put_path,
+                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
+                    size_t size, const void *data)
+{
+  struct MeshPeerInfo *peer = cls;
+  struct MeshPeerPath *p;
+  struct GNUNET_PeerIdentity pi;
+  int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
+  GNUNET_PEER_resolve (peer->id, &pi);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for %s\n", GNUNET_i2s (&pi));
+
+  p = path_build_from_dht (get_path, get_path_length,
+                           put_path, put_path_length);
+  path_add_to_peers (p, GNUNET_NO);
+  path_destroy (p);
+  for (i = 0; i < peer->ntunnels; i++)
+  {
+    struct GNUNET_PeerIdentity id;
+
+    GNUNET_PEER_resolve (peer->tunnels[i]->id.oid, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... tunnel %s:%X (%X / %X)\n",
+                GNUNET_i2s (&id), peer->tunnels[i]->id.tid,
+                peer->tunnels[i]->local_tid, 
+                peer->tunnels[i]->local_tid_dest);
+    if (peer->tunnels[i]->state == MESH_TUNNEL_SEARCHING)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
+      peer_connect (peer, peer->tunnels[i]);
+    }
+  }
+
+  return;
+}
+
+
+/******************************************************************************/
+/*********************       MESH LOCAL HANDLES      
**************************/
+/******************************************************************************/
+
+
+/**
+ * Handler for client disconnection
+ *
+ * @param cls closure
+ * @param client identification of the client; NULL
+ *        for the last call when the server is destroyed
+ */
+static void
+handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  struct MeshClient *c;
+  struct MeshClient *next;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
+  if (client == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
+    return;
+  }
+
+  c = clients_head;
+  while (NULL != c)
+  {
+    if (c->handle != client)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "   ... searching %p (%u)\n",
+                  c->handle, c->id);
+      c = c->next;
+      continue;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u)\n",
+                c->id);
+    GNUNET_SERVER_client_drop (c->handle);
+    c->shutting_down = GNUNET_YES;
+    GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
+                                           &tunnel_destroy_iterator, c);
+    GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
+                                           &tunnel_destroy_iterator, c);
+    GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
+    GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
+
+    if (NULL != c->ports)
+      GNUNET_CONTAINER_multihashmap_destroy (c->ports);
+    next = c->next;
+    GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  CLIENT FREE at %p\n", c);
+    GNUNET_free (c);
+    GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
+    c = next;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
+  return;
+}
+
+
+/**
+ * Handler for new clients
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message, which includes messages the client wants
+ */
+static void
+handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
+                         const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_ClientConnect *cc_msg;
+  struct MeshClient *c;
+  unsigned int size;
+  uint32_t *p;
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
+
+  /* Check data sanity */
+  size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
+  cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
+  if (0 != (size % sizeof (uint32_t)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  size /= sizeof (uint32_t);
+
+  /* Create new client structure */
+  c = GNUNET_malloc (sizeof (struct MeshClient));
+  c->id = next_client_id++; /* overflow not important: just for debug */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  client id %u\n", c->id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  client has %u ports\n", size);
+  c->handle = client;
+  GNUNET_SERVER_client_keep (client);
+  if (size > 0)
+  {
+    uint32_t u32;
+    struct GNUNET_HashCode hc;
+
+    p = (uint32_t *) &cc_msg[1];
+    c->ports = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO);
+    for (i = 0; i < size; i++)
+    {
+      u32 = ntohl (p[i]);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    port: %u\n", u32);
+      GMC_hash32 (u32, &hc);
+
+      /* store in client's hashmap */
+      GNUNET_CONTAINER_multihashmap_put (c->ports, &hc, c,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+      /* store in global hashmap */
+      /* FIXME only allow one client to have the port open,
+       *       have a backup hashmap with waiting clients */
+      GNUNET_CONTAINER_multihashmap_put (ports, &hc, c,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+    }
+  }
+
+  GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
+  c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+  c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+  GNUNET_SERVER_notification_context_add (nc, client);
+  GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
+}
+
+
+/**
+ * Handler for requests of new tunnels
+ *
+ * @param cls Closure.
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
+                            const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_TunnelMessage *t_msg;
+  struct MeshPeerInfo *peer_info;
+  struct MeshTunnel *t;
+  struct MeshClient *c;
+  MESH_TunnelNumber tid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel requested\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  /* Message size sanity check */
+  if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  towards %s\n",
+              GNUNET_i2s (&t_msg->peer));
+  /* Sanity check for tunnel numbering */
+  tid = ntohl (t_msg->tunnel_id);
+  if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  /* Sanity check for duplicate tunnel IDs */
+  if (NULL != tunnel_get_by_local_id (c, tid))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Create tunnel */
+  while (NULL != tunnel_get_by_pi (myid, next_tid))
+    next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
+  t = tunnel_new (myid, next_tid, c, tid);
+  next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
+  if (NULL == t)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  t->port = ntohl (t_msg->port);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n",
+              GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid);
+
+  peer_info = peer_get (&t_msg->peer);
+  peer_info_add_tunnel (peer_info, t);
+  peer_connect (peer_info, t);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+}
+
+
+/**
+ * Handler for requests of deleting tunnels
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
+                             const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
+  struct MeshClient *c;
+  struct MeshTunnel *t;
+  MESH_TunnelNumber tid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got a DESTROY TUNNEL from client!\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  /* Message sanity check */
+  if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
+
+  /* Retrieve tunnel */
+  tid = ntohl (tunnel_msg->tunnel_id);
+  t = tunnel_get_by_local_id(c, tid);
+  if (NULL == t)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Cleanup after the tunnel */
+  client_delete_tunnel (c, t);
+  if (c == t->client)
+  {
+    t->client = NULL;
+  }
+  else if (c == t->owner)
+  {
+    peer_info_remove_tunnel (peer_get_short (t->dest), t);
+    t->owner = NULL;
+  }
+
+  /* The tunnel will be destroyed when the last message is transmitted. */
+  tunnel_destroy_empty (t);
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+}
+
+
+/**
+ * Handler for requests of seeting tunnel's buffering policy.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_local_tunnel_buffer (void *cls, struct GNUNET_SERVER_Client *client,
+                            const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_TunnelMessage *tunnel_msg;
+  struct MeshClient *c;
+  struct MeshTunnel *t;
+  MESH_TunnelNumber tid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got a BUFFER request from client!\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
+
+  /* Retrieve tunnel */
+  tid = ntohl (tunnel_msg->tunnel_id);
+  t = tunnel_get_by_local_id(c, tid);
+  if (NULL == t)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  switch (ntohs(message->type))
+  {
+      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER:
+          t->nobuffer = GNUNET_NO;
+          break;
+      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER:
+          t->nobuffer = GNUNET_YES;
+          break;
+      default:
+          GNUNET_break (0);
+  }
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Handler for client traffic directed to one peer
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
+                      const struct GNUNET_MessageHeader *message)
+{
+  struct MeshClient *c;
+  struct MeshTunnel *t;
+  struct GNUNET_MESH_Data *data_msg;
+  MESH_TunnelNumber tid;
+  size_t size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got a unicast request from a client!\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  data_msg = (struct GNUNET_MESH_Data *) message;
+
+  /* Sanity check for message size */
+  size = ntohs (message->size);
+  if (sizeof (struct GNUNET_MESH_Data) +
+      sizeof (struct GNUNET_MessageHeader) > size)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Tunnel exists? */
+  tid = ntohl (data_msg->tid);
+  t = tunnel_get_by_local_id (c, tid);
+  if (NULL == t)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /*  Is it a local tunnel? Then, does client own the tunnel? */
+  if (t->owner->handle != client)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* PID should be as expected: client<->service communication */
+  if (ntohl (data_msg->pid) != t->prev_fc.last_pid_recv + 1)
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Unicast PID, expected %u, got %u\n",
+              t->prev_fc.last_pid_recv + 1, ntohl (data_msg->pid));
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Ok, everything is correct, send the message
+   * (pretend we got it from a mesh peer)
+   */
+  {
+    /* Work around const limitation */
+    char buf[ntohs (message->size)] GNUNET_ALIGN;
+    struct GNUNET_MESH_Data *copy;
+
+    copy = (struct GNUNET_MESH_Data *) buf;
+    memcpy (buf, data_msg, size);
+    copy->oid = my_full_id;
+    copy->tid = htonl (t->id.tid);
+    copy->ttl = htonl (default_ttl);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  calling generic handler...\n");
+        handle_mesh_unicast (NULL, &my_full_id, &copy->header);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+
+  return;
+}
+
+
+/**
+ * Handler for client traffic directed to the origin
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
+                        const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_Data *data_msg;
+  struct MeshFlowControl *fc;
+  struct MeshClient *c;
+  struct MeshTunnel *t;
+  MESH_TunnelNumber tid;
+  size_t size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got a ToOrigin request from a client!\n");
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  data_msg = (struct GNUNET_MESH_Data *) message;
+
+  /* Sanity check for message size */
+  size = ntohs (message->size);
+  if (sizeof (struct GNUNET_MESH_Data) +
+      sizeof (struct GNUNET_MessageHeader) > size)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Tunnel exists? */
+  tid = ntohl (data_msg->tid);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", tid);
+  if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  t = tunnel_get_by_local_id (c, tid);
+  if (NULL == t)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /*  It should be sent by someone who has this as incoming tunnel. */
+  if (t->client != c)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* PID should be as expected */
+  fc = &t->next_fc;
+  if (ntohl (data_msg->pid) != fc->last_pid_recv + 1)
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "To Origin PID, expected %u, got %u\n",
+                fc->last_pid_recv + 1,
+                ntohl (data_msg->pid));
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Ok, everything is correct, send the message
+   * (pretend we got it from a mesh peer)
+   */
+  {
+    char buf[ntohs (message->size)] GNUNET_ALIGN;
+    struct GNUNET_MESH_Data *copy;
+
+    /* Work around 'const' limitation */
+    memcpy (buf, data_msg, size);
+    copy = (struct GNUNET_MESH_Data *) buf;
+    GNUNET_PEER_resolve (t->id.oid, &copy->oid);
+    copy->tid = htonl (t->id.tid);
+    copy->ttl = htonl (default_ttl);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "  calling generic handler...\n");
+        handle_mesh_to_orig (NULL, &my_full_id, &copy->header);
+  }
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+
+  return;
+}
+
+
+/**
+ * Handler for client's ACKs for payload traffic.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client,
+                  const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_LocalAck *msg;
+  struct MeshTunnel *t;
+  struct MeshClient *c;
+  MESH_TunnelNumber tid;
+  uint32_t ack;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  msg = (struct GNUNET_MESH_LocalAck *) message;
+
+  /* Tunnel exists? */
+  tid = ntohl (msg->tunnel_id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", tid);
+  t = tunnel_get_by_local_id (c, tid);
+  if (NULL == t)
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  ack = ntohl (msg->ack);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ack %u\n", ack);
+
+  /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */
+  if (t->owner == c)
+  {
+    /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */
+    t->prev_fc.last_ack_recv = ack;
+    tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
+  }
+  else
+  {
+    /* The client doesn't own the tunnel, this ACK is for FWD traffic. */
+    t->next_fc.last_ack_recv = ack;
+    tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
+  }
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+
+  return;
+}
+
+
+
+/**
+ * Iterator over all tunnels to send a monitoring client info about each 
tunnel.
+ *
+ * @param cls Closure (client handle).
+ * @param key Key (hashed tunnel ID, unused).
+ * @param value Tunnel info.
+ *
+ * @return GNUNET_YES, to keep iterating.
+ */
+static int
+monitor_all_tunnels_iterator (void *cls,
+                              const struct GNUNET_HashCode * key,
+                              void *value)
+{
+  struct GNUNET_SERVER_Client *client = cls;
+  struct MeshTunnel *t = value;
+  struct GNUNET_MESH_LocalMonitor *msg;
+
+  msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
+  GNUNET_PEER_resolve(t->id.oid, &msg->owner);
+  msg->tunnel_id = htonl (t->id.tid);
+  msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
+  GNUNET_PEER_resolve (t->dest, &msg->destination);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "*  sending info about tunnel %s [%u]\n",
+              GNUNET_i2s (&msg->owner), t->id.tid);
+
+  GNUNET_SERVER_notification_context_unicast (nc, client,
+                                              &msg->header, GNUNET_NO);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's MONITOR request.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
+                          const struct GNUNET_MessageHeader *message)
+{
+  struct MeshClient *c;
+
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Received get tunnels request from client %u\n",
+              c->id);
+  GNUNET_CONTAINER_multihashmap_iterate (tunnels,
+                                         monitor_all_tunnels_iterator,
+                                         client);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Get tunnels request from client %u completed\n",
+              c->id);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Handler for client's MONITOR_TUNNEL request.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
+                          const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_MESH_LocalMonitor *msg;
+  struct GNUNET_MESH_LocalMonitor *resp;
+  struct MeshClient *c;
+  struct MeshTunnel *t;
+
+  /* Sanity check for client registration */
+  if (NULL == (c = client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  msg = (struct GNUNET_MESH_LocalMonitor *) message;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Received tunnel info request from client %u for tunnel 
%s[%X]\n",
+              c->id,
+              &msg->owner,
+              ntohl (msg->tunnel_id));
+  t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id));
+  if (NULL == t)
+  {
+    /* We don't know the tunnel FIXME */
+    struct GNUNET_MESH_LocalMonitor warn;
+
+    warn = *msg;
+    GNUNET_SERVER_notification_context_unicast (nc, client,
+                                                &warn.header,
+                                                GNUNET_NO);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+
+  /* Initialize context */
+  resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
+  *resp = *msg;
+  GNUNET_PEER_resolve (t->dest, &resp->destination);
+  resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
+  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
+                                              &resp->header, GNUNET_NO);
+  GNUNET_free (resp);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Monitor tunnel request from client %u completed\n",
+              c->id);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Functions to handle messages from clients
+ */
+static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
+  {&handle_local_new_client, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
+  {&handle_local_tunnel_create, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
+   sizeof (struct GNUNET_MESH_TunnelMessage)},
+  {&handle_local_tunnel_destroy, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
+   sizeof (struct GNUNET_MESH_TunnelMessage)},
+  {&handle_local_tunnel_buffer, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER,
+   sizeof (struct GNUNET_MESH_TunnelMessage)},
+  {&handle_local_tunnel_buffer, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER,
+   sizeof (struct GNUNET_MESH_TunnelMessage)},
+  {&handle_local_unicast, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
+  {&handle_local_to_origin, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
+  {&handle_local_ack, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
+   sizeof (struct GNUNET_MESH_LocalAck)},
+  {&handle_local_get_tunnels, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
+   sizeof (struct GNUNET_MessageHeader)},
+  {&handle_local_show_tunnel, NULL,
+   GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
+     sizeof (struct GNUNET_MESH_LocalMonitor)},
+  {NULL, NULL, 0, 0}
+};
+
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+  struct MeshPeerInfo *peer_info;
+  struct MeshPeerPath *path;
+
+  DEBUG_CONN ("Peer connected\n");
+  DEBUG_CONN ("     %s\n", GNUNET_i2s (&my_full_id));
+  peer_info = peer_get (peer);
+  if (myid == peer_info->id)
+  {
+    DEBUG_CONN ("     (self)\n");
+    path = path_new (1);
+  }
+  else
+  {
+    DEBUG_CONN ("     %s\n", GNUNET_i2s (peer));
+    path = path_new (2);
+    path->peers[1] = peer_info->id;
+    GNUNET_PEER_change_rc (peer_info->id, 1);
+    GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
+  }
+  path->peers[0] = myid;
+  GNUNET_PEER_change_rc (myid, 1);
+  peer_info_add_path (peer_info, path, GNUNET_YES);
+  return;
+}
+
+
+/**
+ * Method called whenever a peer disconnects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+  struct MeshPeerInfo *pi;
+  struct MeshPeerQueue *q;
+  struct MeshPeerQueue *n;
+
+  DEBUG_CONN ("Peer disconnected\n");
+  pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
+  if (NULL == pi)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  q = pi->queue_head;
+  while (NULL != q)
+  {
+      n = q->next;
+      /* TODO try to reroute this traffic instead */
+      queue_destroy(q, GNUNET_YES);
+      q = n;
+  }
+  if (NULL != pi->core_transmit)
+  {
+    GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit);
+    pi->core_transmit = NULL;
+  }
+    peer_remove_path (pi, pi->id, myid);
+  if (myid == pi->id)
+  {
+    DEBUG_CONN ("     (self)\n");
+  }
+  GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
+  return;
+}
+
+
+/**
+ * Install server (service) handlers and start listening to clients.
+ */
+static void
+server_init (void)
+{
+  GNUNET_SERVER_add_handlers (server_handle, client_handlers);
+  GNUNET_SERVER_disconnect_notify (server_handle,
+                                   &handle_local_client_disconnect, NULL);
+  nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
+
+  clients_head = NULL;
+  clients_tail = NULL;
+  next_client_id = 0;
+  GNUNET_SERVER_resume (server_handle);
+}
+
+
+/**
+ * To be called on core init/fail.
+ *
+ * @param cls Closure (config)
+ * @param server handle to the server for this service
+ * @param identity the public identity of this peer
+ */
+static void
+core_init (void *cls, struct GNUNET_CORE_Handle *server,
+           const struct GNUNET_PeerIdentity *identity)
+{
+  const struct GNUNET_CONFIGURATION_Handle *c = cls;
+  static int i = 0;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
+  GNUNET_break (core_handle == server);
+  if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
+    NULL == server)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                " core id %s\n",
+                GNUNET_i2s (identity));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                " my id %s\n",
+                GNUNET_i2s (&my_full_id));
+    GNUNET_CORE_disconnect (core_handle);
+    core_handle = GNUNET_CORE_connect (c, /* Main configuration */
+                                       NULL,      /* Closure passed to MESH 
functions */
+                                       &core_init,        /* Call core_init 
once connected */
+                                       &core_connect,     /* Handle connects */
+                                       &core_disconnect,  /* remove peers on 
disconnects */
+                                       NULL,      /* Don't notify about all 
incoming messages */
+                                       GNUNET_NO, /* For header only in 
notification */
+                                       NULL,      /* Don't notify about all 
outbound messages */
+                                       GNUNET_NO, /* For header-only out 
notification */
+                                       core_handlers);    /* Register these 
handlers */
+    if (10 < i++)
+      GNUNET_abort();
+  }
+  server_init ();
+  return;
+}
+
+
+/******************************************************************************/
+/************************      MAIN FUNCTIONS      
****************************/
+/******************************************************************************/
+
+/**
+ * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to iterate,
+ *         GNUNET_NO if not.
+ */
+static int
+shutdown_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+  struct MeshTunnel *t = value;
+
+  tunnel_destroy (t);
+  return GNUNET_YES;
+}
+
+/**
+ * Iterator over peer hash map entries to destroy the tunnel during shutdown.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to iterate,
+ *         GNUNET_NO if not.
+ */
+static int
+shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+  struct MeshPeerInfo *p = value;
+  struct MeshPeerQueue *q;
+  struct MeshPeerQueue *n;
+
+  q = p->queue_head;
+  while (NULL != q)
+  {
+      n = q->next;
+      if (q->peer == p)
+      {
+        queue_destroy(q, GNUNET_YES);
+      }
+      q = n;
+  }
+  peer_info_destroy (p);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
+
+  if (core_handle != NULL)
+  {
+    GNUNET_CORE_disconnect (core_handle);
+    core_handle = NULL;
+  }
+  if (NULL != keygen)
+  {
+    GNUNET_CRYPTO_ecc_key_create_stop (keygen);
+    keygen = NULL;
+  }
+  GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL);
+  GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL);
+  if (dht_handle != NULL)
+  {
+    GNUNET_DHT_disconnect (dht_handle);
+    dht_handle = NULL;
+  }
+  if (nc != NULL)
+  {
+    GNUNET_SERVER_notification_context_destroy (nc);
+    nc = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
+  {
+    GNUNET_SCHEDULER_cancel (announce_id_task);
+    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
+}
+
+
+/**
+ * Callback for hostkey read/generation.
+ *
+ * @param cls Closure (Configuration handle).
+ * @param pk The ECC private key.
+ * @param emsg Error message, if any.
+ */
+static void
+key_generation_cb (void *cls,
+                   struct GNUNET_CRYPTO_EccPrivateKey *pk,
+                   const char *emsg)
+{
+  const struct GNUNET_CONFIGURATION_Handle *c = cls;
+
+  keygen = NULL;
+  if (NULL == pk)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Could not access hostkey: %s. Exiting.\n"),
+                emsg);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  my_private_key = pk;
+  GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key);
+  GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
+                      &my_full_id.hashPubKey);
+  myid = GNUNET_PEER_intern (&my_full_id);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Mesh for peer [%s] starting\n",
+              GNUNET_i2s(&my_full_id));
+
+  core_handle = GNUNET_CORE_connect (c, /* Main configuration */
+                                     NULL,      /* Closure passed to MESH 
functions */
+                                     &core_init,        /* Call core_init once 
connected */
+                                     &core_connect,     /* Handle connects */
+                                     &core_disconnect,  /* remove peers on 
disconnects */
+                                     NULL,      /* Don't notify about all 
incoming messages */
+                                     GNUNET_NO, /* For header only in 
notification */
+                                     NULL,      /* Don't notify about all 
outbound messages */
+                                     GNUNET_NO, /* For header-only out 
notification */
+                                     core_handlers);    /* Register these 
handlers */
+  if (core_handle == NULL)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  next_tid = 0;
+  next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
+
+  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
+}
+
+
+/**
+ * Process mesh requests.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls, struct GNUNET_SERVER_Handle *server,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  char *keyfile;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
+  server_handle = server;
+  GNUNET_SERVER_suspend (server_handle);
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY",
+                                               &keyfile))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
+                "mesh", "peer/privatekey");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_PATH_TIME",
+                                           &refresh_path_time))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
+                "mesh", "refresh path time");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
+                                           &id_announce_time))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
+                "mesh", "id announce time");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
+                                           &connect_timeout))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
+                "mesh", "connect timeout");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
+                                             &max_msgs_queue))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
+                "mesh", "max msgs queue");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_TUNNELS",
+                                             &max_tunnels))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("%s service is lacking key configuration settings (%s).  
Exiting.\n"),
+                "mesh", "max tunnels");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
+                                             &default_ttl))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _
+                ("%s service is lacking key configuration settings (%s). Using 
default (%u).\n"),
+                "mesh", "default ttl", 64);
+    default_ttl = 64;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
+                                             &max_peers))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("%s service is lacking key configuration settings (%s). 
Using default (%u).\n"),
+                "mesh", "max peers", 1000);
+    max_peers = 1000;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "MESH", 
"DHT_REPLICATION_LEVEL",
+                                             &dht_replication_level))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _
+                ("%s service is lacking key configuration settings (%s). Using 
default (%u).\n"),
+                "mesh", "dht replication level", 3);
+    dht_replication_level = 3;
+  }
+
+  tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+  incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+  peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+  ports = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+
+  dht_handle = GNUNET_DHT_connect (c, 64);
+  if (NULL == dht_handle)
+  {
+    GNUNET_break (0);
+  }
+  stats = GNUNET_STATISTICS_create ("mesh", c);
+
+  /* Scheduled the task to clean up when shutdown is called */
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
+                                NULL);
+  keygen = GNUNET_CRYPTO_ecc_key_create_start (keyfile,
+                                               &key_generation_cb,
+                                               (void *) c);
+  GNUNET_free (keyfile);
+}
+
+
+/**
+ * The main function for the mesh service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  int ret;
+  int r;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
+  r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
+                          NULL);
+  ret = (GNUNET_OK == r) ? 0 : 1;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");
+
+  INTERVAL_SHOW;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Mesh for peer [%s] FWD ACKs %u, BCK ACKs %u\n",
+              GNUNET_i2s(&my_full_id), debug_fwd_ack, debug_bck_ack);
+
+  return ret;
+}

Deleted: gnunet/src/mesh/mesh.h
===================================================================
--- gnunet/src/mesh/mesh.h      2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh.h      2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,454 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @author Bartlomiej Polot
- * @file mesh/mesh.h
- */
-
-#ifndef MESH_H_
-#define MESH_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include <stdint.h>
-
-#define MESH_DEBUG              GNUNET_YES
-
-#define INITIAL_WINDOW_SIZE     8
-#define ACK_THRESHOLD           INITIAL_WINDOW_SIZE / 2
-
-#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_peer_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_protocols.h"
-#include <gnunet_mesh_service.h>
-
-/******************************************************************************/
-/********************        MESH LOCAL MESSAGES      
*************************/
-/******************************************************************************/
-/*  Any API call should be documented in the folowing table under API CALL.
- *  Also, any message type should be documented in the following table, with 
the
- * associated event.
- *
- * API CALL (GNUNET_MESH_*)             MESSAGE USED
- * ------------------------             ------------
- * connect                              GNUNET_MESH_ClientConnect
- * disconnect                           None (network level disconnect)
- *
- * tunnel_create                        GNUNET_MESH_TunnelMessage
- * tunnel_destroy                       GNUNET_MESH_TunnelMessage
- * tunnel_speed_max                     GNUNET_MESH_TunnelMessage
- * tunnel_speed_min                     GNUNET_MESH_TunnelMessage
- * tunnel_buffer                        GNUNET_MESH_TunnelMessage
- *
- * peer_request_connect_add             GNUNET_MESH_PeerControl
- * peer_request_connect_del             GNUNET_MESH_PeerControl
- * peer_request_connect_by_type         GNUNET_MESH_ConnectPeerByType
- * peer_request_connect_by_string       GNUNET_MESH_ConnectPeerByString
- * 
- * peer_blacklist                       GNUNET_MESH_PeerControl
- * peer_unblacklist                     GNUNET_MESH_PeerControl
- *
- * notify_transmit_ready                None (queue / 
GNUNET_CLIENT_ntf_tmt_rdy)
- * notify_transmit_ready_cancel         None (clear of internal data 
structures)
- *
- * 
- * EVENT                                MESSAGE USED
- * -----                                ------------
- * data                                 GNUNET_MESH_Unicast OR
- *                                      GNUNET_MESH_Multicast OR
- *                                      GNUNET_MESH_ToOrigin
- * data ack                             GNUNET_MESH_LocalAck
- * 
- * new incoming tunnel                  GNUNET_MESH_PeerControl
- * peer connects to a tunnel            GNUNET_MESH_PeerControl
- * peer disconnects from a tunnel       GNUNET_MESH_PeerControl
- */
-
-/******************************************************************************/
-/**************************       CONSTANTS      
******************************/
-/******************************************************************************/
-
-#define GNUNET_MESH_LOCAL_TUNNEL_ID_CLI         0x80000000
-#define GNUNET_MESH_LOCAL_TUNNEL_ID_SERV        0xB0000000
-
-#define HIGH_PID                                0xFFFF0000
-#define LOW_PID                                 0x0000FFFF
-
-#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
-
-/******************************************************************************/
-/**************************        MESSAGES      
******************************/
-/******************************************************************************/
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Message for a client to register to the service
- */
-struct GNUNET_MESH_ClientConnect
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT
-     *
-     * Size: sizeof(struct GNUNET_MESH_ClientConnect) +
-     *       sizeof(MESH_ApplicationType) * applications +
-     *       sizeof(uint16_t) * types
-     */
-  struct GNUNET_MessageHeader header;
-  uint16_t applications GNUNET_PACKED;
-  uint16_t types GNUNET_PACKED;
-  /* uint32_t                 list_apps[applications]     */
-  /* uint16_t                 list_types[types]           */
-};
-
-
-/**
- * Type for tunnel numbering.
- * - Local tunnel numbers given by the service (incoming) are >= 0xB0000000
- * - Local tunnel numbers given by the client (created) are >= 0x80000000
- * - Global tunnel numbers are < 0x80000000
- */
-typedef uint32_t MESH_TunnelNumber;
-
-/**
- * Message for a client to create and destroy tunnels.
- */
-struct GNUNET_MESH_TunnelMessage
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY]
-     *       GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[MAX|MIN]
-     *
-     * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-};
-
-
-/**
- * Message for the service to let a client know about created tunnels.
- */
-struct GNUNET_MESH_TunnelNotification
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE
-     *
-     * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * Peer at the other end, if any
-     */
-  struct GNUNET_PeerIdentity peer;
-
-    /**
-     * Tunnel options (speed, buffering)
-     */
-  uint32_t opt;
-};
-
-/**
- * Message for announce of regular expressions.
- */
-struct GNUNET_MESH_RegexAnnounce
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX
-     *
-     * Size: sizeof(struct GNUNET_MESH_RegexAnnounce) + strlen (regex)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * How many characters do we want to put in an edge label.
-     */
-  uint16_t compression_characters;
-
-    /**
-     * Is this the last message for this regex? (for regex > 65k)
-     */
-  int16_t last;
-
-  /* regex payload  */
-};
-
-
-/**
- * Message for:
- * - request adding and deleting peers from a tunnel
- * - notify the client that peers have connected:
- *   -- requested
- *   -- unrequested (new incoming tunnels)
- * - notify the client that peers have disconnected
- */
-struct GNUNET_MESH_PeerControl
-{
-
-    /**
-     * Type: 
GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_[ADD|DEL|[UN]BLACKLIST]
-     *       (client to service, client created tunnel)
-     *       GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_[CONNECTED|DISCONNECTED]
-     *       (service to client)
-     *
-     * Size: sizeof(struct GNUNET_MESH_PeerControl)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * Peer to connect/disconnect.
-     */
-  struct GNUNET_PeerIdentity peer;
-};
-
-
-/**
- * Message for connecting to peers offering a service, by service number.
- */
-struct GNUNET_MESH_ConnectPeerByType
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE |
-     *       GNUNET_MESSAGE_TYPE_MESH_LOCAL_DISCONNECT_PEER_BY_TYPE
-     * 
-     * Size: sizeof(struct GNUNET_MESH_ConnectPeerByType)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * Type specification
-     */
-  GNUNET_MESH_ApplicationType type GNUNET_PACKED;
-};
-
-
-/**
- * Message for connecting to peers offering a service, by service string.
- */
-struct GNUNET_MESH_ConnectPeerByString
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING
-     * 
-     * Size: sizeof(struct GNUNET_MESH_ConnectPeerByString) + strlen (string)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-  /* String describing the service */
-};
-
-
-/**
- * Message to allow the client send more data to the service
- * (always service -> client).
- */
-struct GNUNET_MESH_LocalAck
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the tunnel allowed to send more data.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * ID of the last packet allowed.
-     */
-  uint32_t max_pid GNUNET_PACKED;
-};
-
-
-/**
- * Message to inform the client about tunnels in the service.
- */
-struct GNUNET_MESH_LocalMonitor
-{
-  /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR[_TUNNEL]
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the tunnel allowed to send more data.
-   */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-  /**
-   * Number of peers in the tunnel.
-   */
-  uint32_t npeers GNUNET_PACKED;
-
-  /**
-   * Alignment.
-   */
-  uint32_t reserved GNUNET_PACKED;
-
-  /**
-   * ID of the owner of the tunnel (can be local peer).
-   */
-  struct GNUNET_PeerIdentity owner;
-
-  /* struct GNUNET_PeerIdentity peers[npeers] */
-};
-
-
-GNUNET_NETWORK_STRUCT_END
-
-/******************************************************************************/
-/************************        ENUMERATIONS      
****************************/
-/******************************************************************************/
-
-/**
- * All the states a peer participating in a tunnel can be in.
- */
-enum MeshPeerState
-{
-    /**
-     * Uninitialized status, should never appear in operation.
-     */
-  MESH_PEER_INVALID,
-
-    /**
-     * Peer is the root and owner of the tree
-     */
-  MESH_PEER_ROOT,
-
-    /**
-     * Peer only retransmits traffic, is not a final destination
-     */
-  MESH_PEER_RELAY,
-
-    /**
-     * Path to the peer not known yet
-     */
-  MESH_PEER_SEARCHING,
-
-    /**
-     * Request sent, not yet answered.
-     */
-  MESH_PEER_WAITING,
-
-    /**
-     * Peer connected and ready to accept data
-     */
-  MESH_PEER_READY,
-
-    /**
-     * Peer connected previosly but not responding
-     */
-  MESH_PEER_RECONNECTING
-};
-
-
-/**
- * Check if one pid is bigger than other, accounting for overflow.
- *
- * @param bigger Argument that should be bigger.
- * @param smaller Argument that should be smaller.
- *
- * @return True if bigger (arg1) has a higher value than smaller (arg 2).
- */
-int
-GMC_is_pid_bigger (uint32_t bigger, uint32_t smaller);
-
-
-/**
- * Get the higher ACK value out of two values, taking in account overflow.
- *
- * @param a First ACK value.
- * @param b Second ACK value.
- *
- * @return Highest ACK value from the two.
- */
-uint32_t
-GMC_max_pid (uint32_t a, uint32_t b);
-
-
-/**
- * Get the lower ACK value out of two values, taking in account overflow.
- *
- * @param a First ACK value.
- * @param b Second ACK value.
- *
- * @return Lowest ACK value from the two.
- */
-uint32_t
-GMC_min_pid (uint32_t a, uint32_t b);
-
-
-/**
- * Convert a message type into a string to help debug
- * Generated with:
- * FIND:        "#define ([^ ]+)[ ]*([0-9]+)"
- * REPLACE:     "    case \2: return "\1"; break;"
- * 
- * @param m Message type.
- * 
- * @return Human readable string description.
- */
-const char *
-GNUNET_MESH_DEBUG_M2S (uint16_t m);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif

Copied: gnunet/src/mesh/mesh.h (from rev 27670, gnunet/src/mesh/mesh2.h)
===================================================================
--- gnunet/src/mesh/mesh.h                              (rev 0)
+++ gnunet/src/mesh/mesh.h      2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,349 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @author Bartlomiej Polot
+ * @file mesh/mesh.h
+ */
+
+#ifndef MESH_H_
+#define MESH_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include <stdint.h>
+
+#define MESH_DEBUG              GNUNET_YES
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_peer_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_protocols.h"
+#include <gnunet_mesh_service.h>
+
+/******************************************************************************/
+/********************        MESH LOCAL MESSAGES      
*************************/
+/******************************************************************************/
+/*  Any API call should be documented in the folowing table under API CALL.
+ *  Also, any message type should be documented in the following table, with 
the
+ * associated event.
+ *
+ * API CALL (GNUNET_MESH_*)             MESSAGE USED
+ * ------------------------             ------------
+ * connect                              GNUNET_MESH_ClientConnect
+ * disconnect                           None (network level disconnect)
+ *
+ * tunnel_create                        GNUNET_MESH_TunnelMessage
+ * tunnel_destroy                       GNUNET_MESH_TunnelMessage
+ * tunnel_buffer                        GNUNET_MESH_TunnelMessage
+ *
+ * notify_transmit_ready                None (queue / 
GNUNET_CLIENT_ntf_tmt_rdy)
+ * notify_transmit_ready_cancel         None (clear of internal data 
structures)
+ *
+ * 
+ * EVENT                                MESSAGE USED
+ * -----                                ------------
+ * data                                 GNUNET_MESH_Unicast OR
+ *                                      GNUNET_MESH_Multicast OR
+ *                                      GNUNET_MESH_ToOrigin
+ * data ack                             GNUNET_MESH_LocalAck
+ * 
+ * new incoming tunnel                  GNUNET_MESH_PeerControl
+ * peer connects to a tunnel            FIXME
+ * peer disconnects from a tunnel       FIXME
+ */
+
+/******************************************************************************/
+/**************************       CONSTANTS      
******************************/
+/******************************************************************************/
+
+#define GNUNET_MESH_LOCAL_TUNNEL_ID_CLI         0x80000000
+#define GNUNET_MESH_LOCAL_TUNNEL_ID_SERV        0xB0000000
+
+#define HIGH_PID                                0xFFFF0000
+#define LOW_PID                                 0x0000FFFF
+
+#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
+
+/******************************************************************************/
+/**************************        MESSAGES      
******************************/
+/******************************************************************************/
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message for a client to register to the service
+ */
+struct GNUNET_MESH_ClientConnect
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT
+     *
+     * Size: sizeof(struct GNUNET_MESH_ClientConnect) +
+     *       sizeof(MESH_ApplicationType) * applications +
+     *       sizeof(uint16_t) * types
+     */
+  struct GNUNET_MessageHeader header;
+  /* uint32_t                 list_ports[]           */
+};
+
+
+/**
+ * Type for tunnel numbering.
+ * - Local tunnel numbers given by the service (incoming) are >= 0xB0000000
+ * - Local tunnel numbers given by the client (created) are >= 0x80000000
+ * - Global tunnel numbers are < 0x80000000
+ */
+typedef uint32_t MESH_TunnelNumber;
+
+
+/**
+ * Message for a client to create and destroy tunnels.
+ */
+struct GNUNET_MESH_TunnelMessage
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY]
+     *
+     * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of a tunnel controlled by this client.
+     */
+  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
+
+    /**
+     * Tunnel's peer
+     */
+  struct GNUNET_PeerIdentity peer;
+
+    /**
+     * Port of the tunnel.
+     */
+  uint32_t port GNUNET_PACKED;
+};
+
+
+/**
+ * Message for the service to let a client know about created tunnels.
+ */
+struct GNUNET_MESH_TunnelNotification
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE
+     *
+     * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of a tunnel controlled by this client.
+     */
+  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
+
+    /**
+     * Peer at the other end.
+     */
+  struct GNUNET_PeerIdentity peer;
+
+    /**
+     * Port for this tunnel
+     */
+  uint32_t port GNUNET_PACKED;
+
+    /**
+     * Tunnel options (speed, buffering)
+     */
+  uint32_t opt GNUNET_PACKED;
+};
+
+
+/**
+ * Message to allow the client send more data to the service
+ * (always service -> client).
+ */
+struct GNUNET_MESH_LocalAck
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the tunnel allowed to send more data.
+     */
+  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
+
+    /**
+     * ID of the last packet allowed.
+     */
+  uint32_t ack GNUNET_PACKED;
+};
+
+
+/**
+ * Message to inform the client about tunnels in the service.
+ */
+struct GNUNET_MESH_LocalMonitor
+{
+  /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR[_TUNNEL]
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the tunnel allowed to send more data.
+   */
+  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
+
+  /**
+   * Alignment.
+   */
+  uint32_t reserved GNUNET_PACKED;
+
+  /**
+   * ID of the owner of the tunnel (can be local peer).
+   */
+  struct GNUNET_PeerIdentity owner;
+
+  /**
+   * ID of the destination of the tunnel (can be local peer).
+   */
+  struct GNUNET_PeerIdentity destination;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+/******************************************************************************/
+/************************        ENUMERATIONS      
****************************/
+/******************************************************************************/
+
+/**
+ * All the states a tunnel can be in.
+ */
+enum MeshTunnelState
+{
+    /**
+     * Uninitialized status, should never appear in operation.
+     */
+  MESH_TUNNEL_NEW,
+
+    /**
+     * Path to the peer not known yet
+     */
+  MESH_TUNNEL_SEARCHING,
+
+    /**
+     * Request sent, not yet answered.
+     */
+  MESH_TUNNEL_WAITING,
+
+    /**
+     * Peer connected and ready to accept data
+     */
+  MESH_TUNNEL_READY,
+
+    /**
+     * Peer connected previosly but not responding
+     */
+  MESH_TUNNEL_RECONNECTING
+};
+
+
+/**
+ * Check if one pid is bigger than other, accounting for overflow.
+ *
+ * @param bigger Argument that should be bigger.
+ * @param smaller Argument that should be smaller.
+ *
+ * @return True if bigger (arg1) has a higher value than smaller (arg 2).
+ */
+int
+GMC_is_pid_bigger (uint32_t bigger, uint32_t smaller);
+
+
+/**
+ * Get the higher ACK value out of two values, taking in account overflow.
+ *
+ * @param a First ACK value.
+ * @param b Second ACK value.
+ *
+ * @return Highest ACK value from the two.
+ */
+uint32_t
+GMC_max_pid (uint32_t a, uint32_t b);
+
+
+/**
+ * Get the lower ACK value out of two values, taking in account overflow.
+ *
+ * @param a First ACK value.
+ * @param b Second ACK value.
+ *
+ * @return Lowest ACK value from the two.
+ */
+uint32_t
+GMC_min_pid (uint32_t a, uint32_t b);
+
+
+/**
+ * Expand a 32 bit value (message type) into a hash for a MultiHashMap (fast).
+ * WARNING: do not use for anything other than MultiHashMap!
+ *          does not alter anything other than bits used by idx_of !
+ *
+ * @param i 32 bit integer value.
+ * @param h Hash code to fill.
+ */
+void
+GMC_hash32 (uint32_t i, struct GNUNET_HashCode *h);
+
+
+/**
+ * Convert a message type into a string to help debug
+ * Generated with:
+ * FIND:        "#define ([^ ]+)[ ]*([0-9]+)"
+ * REPLACE:     "    case \2: return "\1"; break;"
+ * 
+ * @param m Message type.
+ * 
+ * @return Human readable string description.
+ */
+const char *
+GNUNET_MESH_DEBUG_M2S (uint16_t m);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Deleted: gnunet/src/mesh/mesh2.h
===================================================================
--- gnunet/src/mesh/mesh2.h     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh2.h     2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,349 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @author Bartlomiej Polot
- * @file mesh/mesh.h
- */
-
-#ifndef MESH_H_
-#define MESH_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include <stdint.h>
-
-#define MESH_DEBUG              GNUNET_YES
-
-#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_peer_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_protocols.h"
-#include <gnunet_mesh_service.h>
-
-/******************************************************************************/
-/********************        MESH LOCAL MESSAGES      
*************************/
-/******************************************************************************/
-/*  Any API call should be documented in the folowing table under API CALL.
- *  Also, any message type should be documented in the following table, with 
the
- * associated event.
- *
- * API CALL (GNUNET_MESH_*)             MESSAGE USED
- * ------------------------             ------------
- * connect                              GNUNET_MESH_ClientConnect
- * disconnect                           None (network level disconnect)
- *
- * tunnel_create                        GNUNET_MESH_TunnelMessage
- * tunnel_destroy                       GNUNET_MESH_TunnelMessage
- * tunnel_buffer                        GNUNET_MESH_TunnelMessage
- *
- * notify_transmit_ready                None (queue / 
GNUNET_CLIENT_ntf_tmt_rdy)
- * notify_transmit_ready_cancel         None (clear of internal data 
structures)
- *
- * 
- * EVENT                                MESSAGE USED
- * -----                                ------------
- * data                                 GNUNET_MESH_Unicast OR
- *                                      GNUNET_MESH_Multicast OR
- *                                      GNUNET_MESH_ToOrigin
- * data ack                             GNUNET_MESH_LocalAck
- * 
- * new incoming tunnel                  GNUNET_MESH_PeerControl
- * peer connects to a tunnel            FIXME
- * peer disconnects from a tunnel       FIXME
- */
-
-/******************************************************************************/
-/**************************       CONSTANTS      
******************************/
-/******************************************************************************/
-
-#define GNUNET_MESH_LOCAL_TUNNEL_ID_CLI         0x80000000
-#define GNUNET_MESH_LOCAL_TUNNEL_ID_SERV        0xB0000000
-
-#define HIGH_PID                                0xFFFF0000
-#define LOW_PID                                 0x0000FFFF
-
-#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
-
-/******************************************************************************/
-/**************************        MESSAGES      
******************************/
-/******************************************************************************/
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Message for a client to register to the service
- */
-struct GNUNET_MESH_ClientConnect
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT
-     *
-     * Size: sizeof(struct GNUNET_MESH_ClientConnect) +
-     *       sizeof(MESH_ApplicationType) * applications +
-     *       sizeof(uint16_t) * types
-     */
-  struct GNUNET_MessageHeader header;
-  /* uint32_t                 list_ports[]           */
-};
-
-
-/**
- * Type for tunnel numbering.
- * - Local tunnel numbers given by the service (incoming) are >= 0xB0000000
- * - Local tunnel numbers given by the client (created) are >= 0x80000000
- * - Global tunnel numbers are < 0x80000000
- */
-typedef uint32_t MESH_TunnelNumber;
-
-
-/**
- * Message for a client to create and destroy tunnels.
- */
-struct GNUNET_MESH_TunnelMessage
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY]
-     *
-     * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * Tunnel's peer
-     */
-  struct GNUNET_PeerIdentity peer;
-
-    /**
-     * Port of the tunnel.
-     */
-  uint32_t port GNUNET_PACKED;
-};
-
-
-/**
- * Message for the service to let a client know about created tunnels.
- */
-struct GNUNET_MESH_TunnelNotification
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE
-     *
-     * Size: sizeof(struct GNUNET_MESH_TunnelMessage)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a tunnel controlled by this client.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * Peer at the other end.
-     */
-  struct GNUNET_PeerIdentity peer;
-
-    /**
-     * Port for this tunnel
-     */
-  uint32_t port GNUNET_PACKED;
-
-    /**
-     * Tunnel options (speed, buffering)
-     */
-  uint32_t opt GNUNET_PACKED;
-};
-
-
-/**
- * Message to allow the client send more data to the service
- * (always service -> client).
- */
-struct GNUNET_MESH_LocalAck
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the tunnel allowed to send more data.
-     */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-    /**
-     * ID of the last packet allowed.
-     */
-  uint32_t ack GNUNET_PACKED;
-};
-
-
-/**
- * Message to inform the client about tunnels in the service.
- */
-struct GNUNET_MESH_LocalMonitor
-{
-  /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR[_TUNNEL]
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the tunnel allowed to send more data.
-   */
-  MESH_TunnelNumber tunnel_id GNUNET_PACKED;
-
-  /**
-   * Alignment.
-   */
-  uint32_t reserved GNUNET_PACKED;
-
-  /**
-   * ID of the owner of the tunnel (can be local peer).
-   */
-  struct GNUNET_PeerIdentity owner;
-
-  /**
-   * ID of the destination of the tunnel (can be local peer).
-   */
-  struct GNUNET_PeerIdentity destination;
-};
-
-
-GNUNET_NETWORK_STRUCT_END
-
-/******************************************************************************/
-/************************        ENUMERATIONS      
****************************/
-/******************************************************************************/
-
-/**
- * All the states a tunnel can be in.
- */
-enum MeshTunnelState
-{
-    /**
-     * Uninitialized status, should never appear in operation.
-     */
-  MESH_TUNNEL_NEW,
-
-    /**
-     * Path to the peer not known yet
-     */
-  MESH_TUNNEL_SEARCHING,
-
-    /**
-     * Request sent, not yet answered.
-     */
-  MESH_TUNNEL_WAITING,
-
-    /**
-     * Peer connected and ready to accept data
-     */
-  MESH_TUNNEL_READY,
-
-    /**
-     * Peer connected previosly but not responding
-     */
-  MESH_TUNNEL_RECONNECTING
-};
-
-
-/**
- * Check if one pid is bigger than other, accounting for overflow.
- *
- * @param bigger Argument that should be bigger.
- * @param smaller Argument that should be smaller.
- *
- * @return True if bigger (arg1) has a higher value than smaller (arg 2).
- */
-int
-GMC_is_pid_bigger (uint32_t bigger, uint32_t smaller);
-
-
-/**
- * Get the higher ACK value out of two values, taking in account overflow.
- *
- * @param a First ACK value.
- * @param b Second ACK value.
- *
- * @return Highest ACK value from the two.
- */
-uint32_t
-GMC_max_pid (uint32_t a, uint32_t b);
-
-
-/**
- * Get the lower ACK value out of two values, taking in account overflow.
- *
- * @param a First ACK value.
- * @param b Second ACK value.
- *
- * @return Lowest ACK value from the two.
- */
-uint32_t
-GMC_min_pid (uint32_t a, uint32_t b);
-
-
-/**
- * Expand a 32 bit value (message type) into a hash for a MultiHashMap (fast).
- * WARNING: do not use for anything other than MultiHashMap!
- *          does not alter anything other than bits used by idx_of !
- *
- * @param i 32 bit integer value.
- * @param h Hash code to fill.
- */
-void
-GMC_hash32 (uint32_t i, struct GNUNET_HashCode *h);
-
-
-/**
- * Convert a message type into a string to help debug
- * Generated with:
- * FIND:        "#define ([^ ]+)[ ]*([0-9]+)"
- * REPLACE:     "    case \2: return "\1"; break;"
- * 
- * @param m Message type.
- * 
- * @return Human readable string description.
- */
-const char *
-GNUNET_MESH_DEBUG_M2S (uint16_t m);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif

Deleted: gnunet/src/mesh/mesh2_api.c
===================================================================
--- gnunet/src/mesh/mesh2_api.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh2_api.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,1787 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/mesh2_api.c
- * @brief mesh2 api: client implementation of new mesh service
- * @author Bartlomiej Polot
- *
- * STRUCTURE:
- * - DATA STRUCTURES
- * - DECLARATIONS
- * - AUXILIARY FUNCTIONS
- * - RECEIVE HANDLERS
- * - SEND FUNCTIONS
- * - API CALL DEFINITIONS
- *
- * TODO: add regex to reconnect
- */
-#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_client_lib.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_peer_lib.h"
-#include "gnunet_mesh2_service.h"
-#include "mesh2.h"
-#include "mesh2_protocol.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "mesh2-api",__VA_ARGS__)
-#define DEBUG_ACK GNUNET_YES
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/**
- * Transmission queue to the service
- */
-struct GNUNET_MESH_TransmitHandle
-{
-
-    /**
-     * Double Linked list
-     */
-  struct GNUNET_MESH_TransmitHandle *next;
-
-    /**
-     * Double Linked list
-     */
-  struct GNUNET_MESH_TransmitHandle *prev;
-
-    /**
-     * Tunnel this message is sent on / for (may be NULL for control messages).
-     */
-  struct GNUNET_MESH_Tunnel *tunnel;
-
-    /**
-     * Callback to obtain the message to transmit, or NULL if we
-     * got the message in 'data'.  Notice that messages built
-     * by 'notify' need to be encapsulated with information about
-     * the 'target'.
-     */
-  GNUNET_CONNECTION_TransmitReadyNotify notify;
-
-    /**
-     * Closure for 'notify'
-     */
-  void *notify_cls;
-
-    /**
-     * How long is this message valid.  Once the timeout has been
-     * reached, the message must no longer be sent.  If this
-     * is a message with a 'notify' callback set, the 'notify'
-     * function should be called with 'buf' NULL and size 0.
-     */
-  struct GNUNET_TIME_Absolute timeout;
-
-    /**
-     * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-    /**
-     * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
-     */
-  size_t size;
-};
-
-
-/**
- * Opaque handle to the service.
- */
-struct GNUNET_MESH_Handle
-{
-
-    /**
-     * Handle to the server connection, to send messages later
-     */
-  struct GNUNET_CLIENT_Connection *client;
-
-    /**
-     * Set of handlers used for processing incoming messages in the tunnels
-     */
-  const struct GNUNET_MESH_MessageHandler *message_handlers;
-
-  /**
-   * Number of handlers in the handlers array.
-   */
-  unsigned int n_handlers;
-
-  /**
-   * Ports open.
-   */
-  const uint32_t *ports;
-
-  /**
-   * Number of ports.
-   */
-  unsigned int n_ports;
-
-    /**
-     * Double linked list of the tunnels this client is connected to, head.
-     */
-  struct GNUNET_MESH_Tunnel *tunnels_head;
-
-    /**
-     * Double linked list of the tunnels this client is connected to, tail.
-     */
-  struct GNUNET_MESH_Tunnel *tunnels_tail;
-
-    /**
-     * Callback for inbound tunnel creation
-     */
-  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
-
-    /**
-     * Callback for inbound tunnel disconnection
-     */
-  GNUNET_MESH_TunnelEndHandler *cleaner;
-
-    /**
-     * Handle to cancel pending transmissions in case of disconnection
-     */
-  struct GNUNET_CLIENT_TransmitHandle *th;
-
-    /**
-     * Closure for all the handlers given by the client
-     */
-  void *cls;
-
-    /**
-     * Messages to send to the service, head.
-     */
-  struct GNUNET_MESH_TransmitHandle *th_head;
-
-    /**
-     * Messages to send to the service, tail.
-     */
-  struct GNUNET_MESH_TransmitHandle *th_tail;
-
-    /**
-     * tid of the next tunnel to create (to avoid reusing IDs often)
-     */
-  MESH_TunnelNumber next_tid;
-
-    /**
-     * Have we started the task to receive messages from the service
-     * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
-     */
-  int in_receive;
-
-  /**
-   * Configuration given by the client, in case of reconnection
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Time to the next reconnect in case one reconnect fails
-   */
-  struct GNUNET_TIME_Relative reconnect_time;
-  
-  /**
-   * Task for trying to reconnect.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
-
-  /**
-   * Monitor callback
-   */
-  GNUNET_MESH_TunnelsCB tunnels_cb;
-
-  /**
-   * Monitor callback closure.
-   */
-  void *tunnels_cls;
-
-  /**
-   * Tunnel callback.
-   */
-  GNUNET_MESH_TunnelCB tunnel_cb;
-
-  /**
-   * Tunnel callback closure.
-   */
-  void *tunnel_cls;
-
-#if DEBUG_ACK
-  unsigned int acks_sent;
-  unsigned int acks_recv;
-#endif
-};
-
-
-/**
- * Description of a peer
- */
-struct GNUNET_MESH_Peer
-{
-    /**
-     * ID of the peer in short form
-     */
-  GNUNET_PEER_Id id;
-
-  /**
-   * Tunnel this peer belongs to
-   */
-  struct GNUNET_MESH_Tunnel *t;
-
-  /**
-   * Flag indicating whether service has informed about its connection
-   */
-  int connected;
-
-};
-
-
-/**
- * Opaque handle to a tunnel.
- */
-struct GNUNET_MESH_Tunnel
-{
-
-    /**
-     * DLL next
-     */
-  struct GNUNET_MESH_Tunnel *next;
-
-    /**
-     * DLL prev
-     */
-  struct GNUNET_MESH_Tunnel *prev;
-
-    /**
-     * Handle to the mesh this tunnel belongs to
-     */
-  struct GNUNET_MESH_Handle *mesh;
-
-    /**
-     * Local ID of the tunnel
-     */
-  MESH_TunnelNumber tid;
-
-    /**
-     * Port number.
-     */
-  uint32_t port;
-
-    /**
-     * Other end of the tunnel.
-     */
-  GNUNET_PEER_Id peer;
-
-  /**
-   * Any data the caller wants to put in here
-   */
-  void *ctx;
-
-    /**
-     * Size of packet queued in this tunnel
-     */
-  unsigned int packet_size;
-
-    /**
-     * Is the tunnel allowed to buffer?
-     */
-  int buffering;
-
-    /**
-     * Maximum allowed PID to send (last ACK recevied).
-     */
-  uint32_t last_ack_recv;
-
-    /**
-     * Last PID received from the service.
-     */
-  uint32_t last_pid_recv;
-
-  /**
-   * Last packet ID sent to the service.
-   */
-  uint32_t last_pid_sent;
-
-  /**
-   * Last ACK value sent to the service: how much are we willing to accept?
-   */
-  uint32_t last_ack_sent;
-};
-
-
-/**
- * Implementation state for mesh's message queue.
- */
-struct MeshMQState
-{
-  /**
-   * The current transmit handle, or NULL
-   * if no transmit is active.
-   */
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  /**
-   * Tunnel to send the data over.
-   */
-  struct GNUNET_MESH_Tunnel *tunnel;
-};
-
-
-/******************************************************************************/
-/***********************         DECLARATIONS         
*************************/
-/******************************************************************************/
-
-/**
- * Function called to send a message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, the mesh handle
- * @param size number of bytes available in buf
- * @param buf where the callee should write the connect message
- * @return number of bytes written to buf
- */
-static size_t
-send_callback (void *cls, size_t size, void *buf);
-
-
-/******************************************************************************/
-/***********************     AUXILIARY FUNCTIONS      
*************************/
-/******************************************************************************/
-
-/**
- * Check if transmission is a payload packet.
- *
- * @param th Transmission handle.
- *
- * @return GNUNET_YES if it is a payload packet,
- *         GNUNET_NO if it is a mesh management packet.
- */
-static int
-th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
-{
-  return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Check whether there is any message ready in the queue and find the size.
- * 
- * @param h Mesh handle.
- * 
- * @return The size of the first ready message in the queue,
- *         0 if there is none.
- */
-static size_t
-message_ready_size (struct GNUNET_MESH_Handle *h)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_Tunnel *t;
-
-  for (th = h->th_head; NULL != th; th = th->next)
-  {
-    t = th->tunnel;
-    if (GNUNET_NO == th_is_payload (th))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message internal\n");
-      return th->size;
-    }
-    if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message payload ok (%u =< %u)\n",
-           t->last_pid_sent + 1, t->last_ack_recv);
-      return th->size;
-    }
-  }
-  return 0;
-}
-
-
-/**
- * Get the tunnel handler for the tunnel specified by id from the given handle
- * @param h Mesh handle
- * @param tid ID of the wanted tunnel
- * @return handle to the required tunnel or NULL if not found
- */
-static struct GNUNET_MESH_Tunnel *
-retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
-{
-  struct GNUNET_MESH_Tunnel *t;
-
-  t = h->tunnels_head;
-  while (t != NULL)
-  {
-    if (t->tid == tid)
-      return t;
-    t = t->next;
-  }
-  return NULL;
-}
-
-
-/**
- * Create a new tunnel and insert it in the tunnel list of the mesh handle
- * @param h Mesh handle
- * @param tid desired tid of the tunnel, 0 to assign one automatically
- * @return handle to the created tunnel
- */
-static struct GNUNET_MESH_Tunnel *
-create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
-{
-  struct GNUNET_MESH_Tunnel *t;
-
-  t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
-  GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
-  t->mesh = h;
-  if (0 == tid)
-  {
-    t->tid = h->next_tid;
-    while (NULL != retrieve_tunnel (h, h->next_tid))
-    {
-      h->next_tid++;
-      h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-      h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-    }
-  }
-  else
-  {
-    t->tid = tid;
-  }
-  t->last_ack_recv = (uint32_t) -1;
-  t->last_pid_recv = (uint32_t) -1;
-  t->last_ack_sent = (uint32_t) -1;
-  t->last_pid_sent = (uint32_t) -1;
-  t->buffering = GNUNET_YES;
-  return t;
-}
-
-
-/**
- * Destroy the specified tunnel.
- * - Destroys all peers, calling the disconnect callback on each if needed
- * - Cancels all outgoing traffic for that tunnel, calling respective notifys
- * - Calls cleaner if tunnel was inbound
- * - Frees all memory used
- *
- * @param t Pointer to the tunnel.
- * @param call_cleaner Whether to call the cleaner handler.
- *
- * @return Handle to the required tunnel or NULL if not found.
- */
-static void
-destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
-{
-  struct GNUNET_MESH_Handle *h;
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_TransmitHandle *next;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
-
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  h = t->mesh;
-
-  GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
-
-  /* signal tunnel destruction */
-  if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) )
-    h->cleaner (h->cls, t, t->ctx);
-
-  /* check that clients did not leave messages behind in the queue */
-  for (th = h->th_head; NULL != th; th = next)
-  {
-    next = th->next;
-    if (th->tunnel != t)
-      continue;
-    /* Clients should have aborted their requests already.
-     * Management traffic should be ok, as clients can't cancel that */
-    GNUNET_break (GNUNET_NO == th_is_payload(th));
-    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-
-    /* clean up request */
-    if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
-      GNUNET_SCHEDULER_cancel (th->timeout_task);
-    GNUNET_free (th);    
-  }
-
-  /* if there are no more pending requests with mesh service, cancel active 
request */
-  /* Note: this should be unnecessary... */
-  if ((0 == message_ready_size (h)) && (NULL != h->th))
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
-    h->th = NULL;
-  }
-
-  if (0 != t->peer)
-    GNUNET_PEER_change_rc (t->peer, -1);
-  GNUNET_free (t);
-  return;
-}
-
-
-/**
- * Notify client that the transmission has timed out
- * 
- * @param cls closure
- * @param tc task context
- */
-static void
-timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_MESH_TransmitHandle *th = cls;
-  struct GNUNET_MESH_Handle *mesh;
-
-  mesh = th->tunnel->mesh;
-  GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
-  th->tunnel->packet_size = 0;
-  if (GNUNET_YES == th_is_payload (th))
-    th->notify (th->notify_cls, 0, NULL);
-  GNUNET_free (th);
-  if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
-  {
-    /* nothing ready to transmit, no point in asking for transmission */
-    GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
-    mesh->th = NULL;
-  }
-}
-
-
-/**
- * Add a transmit handle to the transmission queue and set the
- * timeout if needed.
- *
- * @param h mesh handle with the queue head and tail
- * @param th handle to the packet to be transmitted
- */
-static void
-add_to_queue (struct GNUNET_MESH_Handle *h,
-              struct GNUNET_MESH_TransmitHandle *th)
-{
-  GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
-  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
-    return;
-  th->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                    (th->timeout), &timeout_transmission, th);
-}
-
-
-/**
- * Auxiliary function to send an already constructed packet to the service.
- * Takes care of creating a new queue element, copying the message and
- * calling the tmt_rdy function if necessary.
- *
- * @param h mesh handle
- * @param msg message to transmit
- * @param tunnel tunnel this send is related to (NULL if N/A)
- */
-static void
-send_packet (struct GNUNET_MESH_Handle *h,
-             const struct GNUNET_MessageHeader *msg,
-             struct GNUNET_MESH_Tunnel *tunnel);
-
-
-/**
- * Send an ack on the tunnel to confirm the processing of a message.
- * 
- * @param h Mesh handle.
- * @param t Tunnel on which to send the ACK.
- */
-static void
-send_ack (struct GNUNET_MESH_Tunnel *t)
-{
-  struct GNUNET_MESH_LocalAck msg;
-
-  t->last_ack_sent = t->last_pid_recv + 1;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Sending ACK on tunnel %X: %u\n",
-       t->tid, t->last_ack_sent);
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  msg.header.size = htons (sizeof (msg));
-  msg.tunnel_id = htonl (t->tid);
-  msg.ack = htonl (t->last_ack_sent);
-
-#if DEBUG_ACK
-  t->mesh->acks_sent++;
-#endif
-
-  send_packet (t->mesh, &msg.header, t);
-  return;
-}
-
-
-
-/**
- * Reconnect callback: tries to reconnect again after a failer previous
- * reconnecttion
- * @param cls closure (mesh handle)
- * @param tc task context
- */
-static void
-reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Send a connect packet to the service with the applications and types
- * requested by the user.
- *
- * @param h The mesh handle.
- *
- */
-static void
-send_connect (struct GNUNET_MESH_Handle *h)
-{
-  size_t size;
-
-  size = sizeof (struct GNUNET_MESH_ClientConnect);
-  size += h->n_ports * sizeof (uint32_t);
-  {
-    char buf[size] GNUNET_ALIGN;
-    struct GNUNET_MESH_ClientConnect *msg;
-    uint32_t *ports;
-    uint16_t i;
-
-    /* build connection packet */
-    msg = (struct GNUNET_MESH_ClientConnect *) buf;
-    msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
-    msg->header.size = htons (size);
-    ports = (uint32_t *) &msg[1];
-    for (i = 0; i < h->n_ports; i++)
-    {
-      ports[i] = htonl (h->ports[i]);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
-           h->ports[i]);
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Sending %lu bytes long message with %u ports\n",
-         ntohs (msg->header.size), h->n_ports);
-    send_packet (h, &msg->header, NULL);
-  }
-}
-
-
-/**
- * Reconnect to the service, retransmit all infomation to try to restore the
- * original state.
- *
- * @param h handle to the mesh
- *
- * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
- */
-static int
-do_reconnect (struct GNUNET_MESH_Handle *h)
-{
-  struct GNUNET_MESH_Tunnel *t;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-
-  /* disconnect */
-  if (NULL != h->th)
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
-    h->th = NULL;
-  }
-  if (NULL != h->client)
-  {
-    GNUNET_CLIENT_disconnect (h->client);
-  }
-
-  /* connect again */
-  h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
-  if (h->client == NULL)
-  {
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-    h->reconnect_time =
-        GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
-                                  GNUNET_TIME_relative_multiply
-                                  (h->reconnect_time, 2));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, 
-        "Next retry in %s\n",
-         GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
-                                                GNUNET_NO));
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-  else
-  {
-    h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
-  }
-  send_connect (h);
-  /* Rebuild all tunnels */
-  for (t = h->tunnels_head; NULL != t; t = t->next)
-  {
-    struct GNUNET_MESH_TunnelMessage tmsg;
-
-    if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    {
-      /* Tunnel was created by service (incoming tunnel) */
-      /* TODO: Notify service of missing tunnel, to request
-       * creator to recreate path (find a path to him via DHT?)
-       */
-      continue;
-    }
-    t->last_ack_sent = (uint32_t) -1;
-    t->last_pid_sent = (uint32_t) -1;
-    t->last_ack_recv = (uint32_t) -1;
-    t->last_pid_recv = (uint32_t) -1;
-    tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
-    tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-    tmsg.tunnel_id = htonl (t->tid);
-    GNUNET_PEER_resolve (t->peer, &tmsg.peer);
-    send_packet (h, &tmsg.header, t);
-
-    if (GNUNET_NO == t->buffering)
-      GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
-  }
-  return GNUNET_YES;
-}
-
-/**
- * Reconnect callback: tries to reconnect again after a failer previous
- * reconnecttion
- * @param cls closure (mesh handle)
- * @param tc task context
- */
-static void
-reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_MESH_Handle *h = cls;
-
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  do_reconnect (h);
-}
-
-
-/**
- * Reconnect to the service, retransmit all infomation to try to restore the
- * original state.
- *
- * @param h handle to the mesh
- *
- * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
- */
-static void
-reconnect (struct GNUNET_MESH_Handle *h)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
-  h->in_receive = GNUNET_NO;
-  if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-}
-
-
-/******************************************************************************/
-/***********************      RECEIVE HANDLERS     
****************************/
-/******************************************************************************/
-
-/**
- * Process the new tunnel notification and add it to the tunnels in the handle
- *
- * @param h     The mesh handle
- * @param msg   A message with the details of the new incoming tunnel
- */
-static void
-process_tunnel_created (struct GNUNET_MESH_Handle *h,
-                        const struct GNUNET_MESH_TunnelNotification *msg)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  MESH_TunnelNumber tid;
-
-  tid = ntohl (msg->tunnel_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
-  if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (NULL != h->new_tunnel)
-  {
-    t = create_tunnel (h, tid);
-    t->last_ack_sent = 0;
-    t->peer = GNUNET_PEER_intern (&msg->peer);
-    t->mesh = h;
-    t->tid = tid;
-    t->port = ntohl (msg->port);
-    if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER))
-      t->buffering = GNUNET_NO;
-    else
-      t->buffering = GNUNET_YES;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
-    t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
-  }
-  else
-  {
-    struct GNUNET_MESH_TunnelMessage d_msg;
-
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
-
-    d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-    d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-    d_msg.tunnel_id = msg->tunnel_id;
-
-    send_packet (h, &d_msg.header, NULL);
-  }
-  return;
-}
-
-
-/**
- * Process the tunnel destroy notification and free associated resources
- *
- * @param h     The mesh handle
- * @param msg   A message with the details of the tunnel being destroyed
- */
-static void
-process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
-                        const struct GNUNET_MESH_TunnelMessage *msg)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  MESH_TunnelNumber tid;
-
-  tid = ntohl (msg->tunnel_id);
-  t = retrieve_tunnel (h, tid);
-
-  if (NULL == t)
-  {
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
-  destroy_tunnel (t, GNUNET_YES);
-  return;
-}
-
-
-/**
- * Process the incoming data packets, call appropriate handlers.
- *
- * @param h         The mesh handle
- * @param message   A message encapsulating the data
- */
-static void
-process_incoming_data (struct GNUNET_MESH_Handle *h,
-                       const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_MessageHeader *payload;
-  const struct GNUNET_MESH_MessageHandler *handler;
-  const struct GNUNET_PeerIdentity *peer;
-  struct GNUNET_PeerIdentity id;
-  struct GNUNET_MESH_Data *dmsg;
-  struct GNUNET_MESH_Tunnel *t;
-  unsigned int i;
-  uint32_t pid;
-  uint16_t type;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
-  type = ntohs (message->type);
-  switch (type)
-  {
-  case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-  case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-    dmsg = (struct GNUNET_MESH_Data *) message;
-
-    t = retrieve_tunnel (h, ntohl (dmsg->tid));
-    payload = (struct GNUNET_MessageHeader *) &dmsg[1];
-    GNUNET_PEER_resolve (t->peer, &id);
-    peer = &id;
-    pid = ntohl (dmsg->pid);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s data on tunnel %s [%X]\n",
-         type == GNUNET_MESSAGE_TYPE_MESH_UNICAST ? "fwd" : "bck",
-         GNUNET_i2s (peer), ntohl (dmsg->tid));
-    break;
-  default:
-    GNUNET_break (0);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
-  if (NULL == t)
-  {
-    /* Tunnel was ignored/destroyed, probably service didn't get it yet */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
-    return;
-  }
-  if (GNUNET_YES ==
-      GMC_is_pid_bigger(pid, t->last_ack_sent))
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "  unauthorized message! (%u, ACK %u)\n",
-         pid, t->last_ack_sent);
-    // FIXME fc what now? accept? reject?
-    return;
-  }
-  t->last_pid_recv = pid;
-  type = ntohs (payload->type);
-  for (i = 0; i < h->n_handlers; i++)
-  {
-    handler = &h->message_handlers[i];
-    if (handler->type == type)
-    {
-      if (GNUNET_OK !=
-          handler->callback (h->cls, t, &t->ctx, payload))
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
-        GNUNET_MESH_tunnel_destroy (t);
-        return;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG,
-             "callback completed successfully\n");
-      }
-    }
-  }
-}
-
-
-/**
- * Process a local ACK message, enabling the client to send
- * more data to the service.
- * 
- * @param h Mesh handle.
- * @param message Message itself.
- */
-static void
-process_ack (struct GNUNET_MESH_Handle *h,
-             const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalAck *msg;
-  struct GNUNET_MESH_Tunnel *t;
-  uint32_t ack;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
-  h->acks_recv++;
-  msg = (struct GNUNET_MESH_LocalAck *) message;
-
-  t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
-
-  if (NULL == t)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "ACK on unknown tunnel %X\n",
-         ntohl (msg->tunnel_id));
-    return;
-  }
-  ack = ntohl (msg->ack);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
-  if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv))
-    t->last_ack_recv = ack;
-  else
-    return;
-  if (NULL == h->th && 0 < t->packet_size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, 
ack);
-    h->th =
-        GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             GNUNET_YES, &send_callback, h);
-  }
-}
-
-
-/**
- * Process a local reply about info on all tunnels, pass info to the user.
- *
- * @param h Mesh handle.
- * @param message Message itself.
- */
-static void
-process_get_tunnels (struct GNUNET_MESH_Handle *h,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalMonitor *msg;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
-
-  if (NULL == h->tunnels_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
-    return;
-  }
-
-  msg = (struct GNUNET_MESH_LocalMonitor *) message;
-  if (ntohs (message->size) !=
-      (sizeof (struct GNUNET_MESH_LocalMonitor) +
-       sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Get tunnels message: size %hu - expected %u\n",
-                ntohs (message->size),
-                sizeof (struct GNUNET_MESH_LocalMonitor));
-    return;
-  }
-  h->tunnels_cb (h->tunnels_cls,
-                 ntohl (msg->tunnel_id),
-                 &msg->owner,
-                 &msg->destination);
-}
-
-
-
-/**
- * Process a local monitor_tunnel reply, pass info to the user.
- *
- * @param h Mesh handle.
- * @param message Message itself.
- */
-static void
-process_show_tunnel (struct GNUNET_MESH_Handle *h,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalMonitor *msg;
-  size_t esize;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
-
-  if (NULL == h->tunnel_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
-    return;
-  }
-
-  /* Verify message sanity */
-  msg = (struct GNUNET_MESH_LocalMonitor *) message;
-  esize = sizeof (struct GNUNET_MESH_LocalMonitor);
-  if (ntohs (message->size) != esize)
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Show tunnel message: size %hu - expected %u\n",
-                ntohs (message->size),
-                esize);
-
-    h->tunnel_cb (h->tunnel_cls, NULL, NULL);
-    h->tunnel_cb = NULL;
-    h->tunnel_cls = NULL;
-
-    return;
-  }
-
-  h->tunnel_cb (h->tunnel_cls,
-                &msg->destination,
-                &msg->owner);
-}
-
-
-/**
- * Function to process all messages received from the service
- *
- * @param cls closure
- * @param msg message received, NULL on timeout or fatal error
- */
-static void
-msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_MESH_Handle *h = cls;
-
-  if (msg == NULL)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, 
-        "Mesh service disconnected, reconnecting\n", h);
-    reconnect (h);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
-       GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
-       GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
-  switch (ntohs (msg->type))
-  {
-    /* Notify of a new incoming tunnel */
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
-    process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
-    break;
-    /* Notify of a tunnel disconnection */
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
-    process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
-    break;
-    /* Notify of a new data packet in the tunnel */
-  case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-  case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-  case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-    process_incoming_data (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
-    process_ack (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
-        process_get_tunnels (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
-        process_show_tunnel (h, msg);
-    break;
-  default:
-    /* We shouldn't get any other packages, log and ignore */
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "unsolicited message form service (type %s)\n",
-         GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
-  if (GNUNET_YES == h->in_receive)
-  {
-    GNUNET_CLIENT_receive (h->client, &msg_received, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "in receive off, not calling CLIENT_receive\n");
-  }
-}
-
-
-/******************************************************************************/
-/************************       SEND FUNCTIONS     
****************************/
-/******************************************************************************/
-
-/**
- * Function called to send a message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, the mesh handle
- * @param size number of bytes available in buf
- * @param buf where the callee should write the connect message
- * @return number of bytes written to buf
- */
-static size_t
-send_callback (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MESH_Handle *h = cls;
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_TransmitHandle *next;
-  struct GNUNET_MESH_Tunnel *t;
-  char *cbuf = buf;
-  size_t tsize;
-  size_t psize;
-  size_t nsize;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
-  if ((0 == size) || (NULL == buf))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
-    reconnect (h);
-    h->th = NULL;
-    return 0;
-  }
-  tsize = 0;
-  next = h->th_head;
-  nsize = message_ready_size (h);
-  while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
-  {
-    t = th->tunnel;
-    if (GNUNET_YES == th_is_payload (th))
-    {
-      struct GNUNET_MESH_Data *dmsg;
-      struct GNUNET_MessageHeader *mh;
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload\n");
-      if (GNUNET_NO == GMC_is_pid_bigger (t->last_ack_recv, t->last_pid_sent))
-      {
-        /* This tunnel is not ready to transmit yet, try next message */
-        next = th->next;
-        continue;
-      }
-      t->packet_size = 0;
-      GNUNET_assert (size >= th->size);
-      dmsg = (struct GNUNET_MESH_Data *) cbuf;
-      mh = (struct GNUNET_MessageHeader *) &dmsg[1];
-      psize = th->notify (th->notify_cls,
-                          size - sizeof (struct GNUNET_MESH_Data),
-                          mh);
-      if (psize > 0)
-      {
-        psize += sizeof (struct GNUNET_MESH_Data);
-        GNUNET_assert (size >= psize);
-        dmsg->header.size = htons (psize);
-        dmsg->tid = htonl (t->tid);
-        dmsg->pid = htonl (t->last_pid_sent + 1);
-        dmsg->ttl = 0;
-        memset (&dmsg->oid, 0, sizeof (struct GNUNET_PeerIdentity));
-        t->last_pid_sent++;
-      }
-      if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-      {
-        dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "#  to origin, type %s\n",
-             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-      }
-      else
-      {
-        dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "#  unicast, type %s\n",
-             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-      }
-    }
-    else
-    {
-      struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  mesh traffic, type %s\n",
-           GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-      memcpy (cbuf, &th[1], th->size);
-      psize = th->size;
-    }
-    if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-      GNUNET_SCHEDULER_cancel (th->timeout_task);
-    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-    GNUNET_free (th);
-    next = h->th_head;
-    nsize = message_ready_size (h);
-    cbuf += psize;
-    size -= psize;
-    tsize += psize;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "#  total size: %u\n", tsize);
-  h->th = NULL;
-  size = message_ready_size (h);
-  if (0 != size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "#  next size: %u\n", size);
-    h->th =
-        GNUNET_CLIENT_notify_transmit_ready (h->client, size,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             GNUNET_YES, &send_callback, h);
-  }
-  else
-  {
-    if (NULL != h->th_head)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  can't transmit any more\n");
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  nothing left to transmit\n");
-  }
-  if (GNUNET_NO == h->in_receive)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
-    h->in_receive = GNUNET_YES;
-    GNUNET_CLIENT_receive (h->client, &msg_received, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
-  return tsize;
-}
-
-
-/**
- * Auxiliary function to send an already constructed packet to the service.
- * Takes care of creating a new queue element, copying the message and
- * calling the tmt_rdy function if necessary.
- * 
- * @param h mesh handle
- * @param msg message to transmit
- * @param tunnel tunnel this send is related to (NULL if N/A)
- */
-static void
-send_packet (struct GNUNET_MESH_Handle *h,
-             const struct GNUNET_MessageHeader *msg,
-             struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  size_t msize;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
-       GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
-  msize = ntohs (msg->size);
-  th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
-  th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
-  th->size = msize;
-  th->tunnel = tunnel;
-  memcpy (&th[1], msg, msize);
-  add_to_queue (h, th);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
-  if (NULL != h->th)
-    return;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", 
msize);
-  h->th =
-      GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &send_callback, h);
-}
-
-
-/******************************************************************************/
-/**********************      API CALL DEFINITIONS     
*************************/
-/******************************************************************************/
-
-struct GNUNET_MESH_Handle *
-GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
-                     GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                     GNUNET_MESH_TunnelEndHandler cleaner,
-                     const struct GNUNET_MESH_MessageHandler *handlers,
-                     const uint32_t *ports)
-{
-  struct GNUNET_MESH_Handle *h;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
-  h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
-  h->cfg = cfg;
-  h->new_tunnel = new_tunnel;
-  h->cleaner = cleaner;
-  h->client = GNUNET_CLIENT_connect ("mesh", cfg);
-  if (h->client == NULL)
-  {
-    GNUNET_break (0);
-    GNUNET_free (h);
-    return NULL;
-  }
-  h->cls = cls;
-  h->message_handlers = handlers;
-  h->ports = ports;
-  h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-  h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-
-  /* count handlers */
-  for (h->n_handlers = 0;
-       handlers && handlers[h->n_handlers].type;
-       h->n_handlers++) ;
-  for (h->n_ports = 0;
-       ports && ports[h->n_ports];
-       h->n_ports++) ;
-  send_connect (h);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
-  return h;
-}
-
-
-void
-GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  struct GNUNET_MESH_Tunnel *aux;
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
-
-#if DEBUG_ACK
-  LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
-  LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
-#endif
-
-  t = handle->tunnels_head;
-  while (NULL != t)
-  {
-    aux = t->next;
-    if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    {
-      GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
-    }
-    destroy_tunnel (t, GNUNET_YES);
-    t = aux;
-  }
-  while ( (th = handle->th_head) != NULL)
-  {
-    struct GNUNET_MessageHeader *msg;
-
-    /* Make sure it is an allowed packet (everything else should have been
-     * already canceled).
-     */
-    GNUNET_break (GNUNET_NO == th_is_payload (th));
-    msg = (struct GNUNET_MessageHeader *) &th[1];
-    switch (ntohs(msg->type))
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
-        break;
-      default:
-        GNUNET_break (0);
-        LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
-             ntohs(msg->type));
-    }
-
-    GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
-    GNUNET_free (th);
-  }
-
-  if (NULL != handle->th)
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
-    handle->th = NULL;
-  }
-  if (NULL != handle->client)
-  {
-    GNUNET_CLIENT_disconnect (handle->client);
-    handle->client = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel(handle->reconnect_task);
-    handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_free (handle);
-}
-
-
-struct GNUNET_MESH_Tunnel *
-GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, 
-                           void *tunnel_ctx,
-                           const struct GNUNET_PeerIdentity *peer,
-                           uint32_t port)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  struct GNUNET_MESH_TunnelMessage msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
-  t = create_tunnel (h, 0);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
-  t->ctx = tunnel_ctx;
-  t->peer = GNUNET_PEER_intern (peer);
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (t->tid);
-  msg.port = htonl (port);
-  msg.peer = *peer;
-  t->last_ack_sent = 0;
-  send_packet (h, &msg.header, t);
-  return t;
-}
-
-
-void
-GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MESH_Handle *h;
-  struct GNUNET_MESH_TunnelMessage msg;
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
-  h = tunnel->mesh;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (tunnel->tid);
-  th = h->th_head;
-  while (th != NULL)
-  {
-    struct GNUNET_MESH_TransmitHandle *aux;
-    if (th->tunnel == tunnel)
-    {
-      aux = th->next;
-      /* FIXME call the handler? */
-      if (GNUNET_YES == th_is_payload (th))
-        th->notify (th->notify_cls, 0, NULL);
-      GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-      GNUNET_free (th);
-      th = aux;
-    }
-    else
-      th = th->next;
-  }
-
-  destroy_tunnel (tunnel, GNUNET_YES);
-  send_packet (h, &msg.header, NULL);
-}
-
-
-void
-GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-  struct GNUNET_MESH_Handle *h;
-
-  h = tunnel->mesh;
-  tunnel->buffering = buffer;
-
-  if (GNUNET_YES == buffer)
-    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
-  else
-    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (tunnel->tid);
-
-  send_packet (h, &msg.header, NULL);
-}
-
-
-struct GNUNET_MESH_TransmitHandle *
-GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
-                                   struct GNUNET_TIME_Relative maxdelay,
-                                   size_t notify_size,
-                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
-                                   void *notify_cls)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  GNUNET_assert (NULL != tunnel);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
-  if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
-  GNUNET_assert (NULL != notify);
-  GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
-  th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
-  th->tunnel = tunnel;
-  th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
-  th->size = notify_size + sizeof (struct GNUNET_MESH_Data);
-  tunnel->packet_size = th->size;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
-  th->notify = notify;
-  th->notify_cls = notify_cls;
-  add_to_queue (tunnel->mesh, th);
-  if (NULL != tunnel->mesh->th)
-    return th;
-  if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent))
-    return th;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    call client notify tmt rdy\n");
-  tunnel->mesh->th =
-      GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &send_callback,
-                                           tunnel->mesh);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
-  return th;
-}
-
-
-void
-GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle 
*th)
-{
-  struct GNUNET_MESH_Handle *mesh;
-
-  th->tunnel->packet_size = 0;
-  mesh = th->tunnel->mesh;
-  if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (th->timeout_task);
-  GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
-  GNUNET_free (th);
-  if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
-  {
-    /* queue empty, no point in asking for transmission */
-    GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
-    mesh->th = NULL;
-  }
-}
-
-void
-GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  send_ack (tunnel);
-}
-
-
-/**
- * Request information about the running mesh peer.
- * The callback will be called for every tunnel known to the service,
- * listing all active peers that blong to the tunnel.
- *
- * If called again on the same handle, it will overwrite the previous
- * callback and cls. To retrieve the cls, monitor_cancel must be
- * called first.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
-                         GNUNET_MESH_TunnelsCB callback,
-                         void *callback_cls)
-{
-  struct GNUNET_MessageHeader msg;
-
-  msg.size = htons (sizeof (msg));
-  msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
-  send_packet (h, &msg, NULL);
-  h->tunnels_cb = callback;
-  h->tunnels_cls = callback_cls;
-
-  return;
-}
-
-
-/**
- * Cancel a monitor request. The monitor callback will not be called.
- *
- * @param h Mesh handle.
- *
- * @return Closure given to GNUNET_MESH_monitor, if any.
- */
-void *
-GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
-{
-  void *cls;
-
-  cls = h->tunnels_cls;
-  h->tunnels_cb = NULL;
-  h->tunnels_cls = NULL;
-  return cls;
-}
-
-
-/**
- * Request information about a specific tunnel of the running mesh peer.
- *
- * WARNING: unstable API, likely to change in the future!
- * FIXME Add destination option.
- *
- * @param h Handle to the mesh peer.
- * @param initiator ID of the owner of the tunnel.
- * @param tunnel_number Tunnel number.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
-                         struct GNUNET_PeerIdentity *initiator,
-                         unsigned int tunnel_number,
-                         GNUNET_MESH_TunnelCB callback,
-                         void *callback_cls)
-{
-  struct GNUNET_MESH_LocalMonitor msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
-  msg.owner = *initiator;
-  msg.tunnel_id = htonl (tunnel_number);
-  msg.reserved = 0;
-  send_packet (h, &msg.header, NULL);
-  h->tunnel_cb = callback;
-  h->tunnel_cls = callback_cls;
-
-  return;
-}
-
-
-/**
- * Function called to notify a client about the connection
- * begin ready to queue more data.  "buf" will be
- * NULL and "size" zero if the connection was closed for
- * writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-mesh_mq_ntr (void *cls, size_t size,
-             void *buf)
-{
-  struct GNUNET_MQ_Handle *mq = cls; 
-  struct MeshMQState *state = GNUNET_MQ_impl_state (mq);
-  const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
-  uint16_t msize;
-
-  state->th = NULL;
-  if (NULL == buf)
-  {
-    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
-    return 0;
-  }
-  msize = ntohs (msg->size);
-  GNUNET_assert (msize <= size);
-  memcpy (buf, msg, msize);
-  GNUNET_MQ_impl_send_continue (mq);
-  return msize;
-}
-
-
-/**
- * Signature of functions implementing the
- * sending functionality of a message queue.
- *
- * @param mq the message queue
- * @param msg the message to send
- * @param impl_state state of the implementation
- */
-static void
-mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq,
-                   const struct GNUNET_MessageHeader *msg, void *impl_state)
-{
-  struct MeshMQState *state = impl_state;
-
-  GNUNET_assert (NULL == state->th);
-  GNUNET_MQ_impl_send_commit (mq);
-  state->th =
-      GNUNET_MESH_notify_transmit_ready (state->tunnel,
-                                         /* FIXME: add option for corking */
-                                         GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL, 
-                                         ntohs (msg->size),
-                                         mesh_mq_ntr, mq);
-
-}
-
-
-/**
- * Signature of functions implementing the
- * destruction of a message queue.
- * Implementations must not free 'mq', but should
- * take care of 'impl_state'.
- * 
- * @param mq the message queue to destroy
- * @param impl_state state of the implementation
- */
-static void
-mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
-{
-  struct MeshMQState *state = impl_state;
-
-  if (NULL != state->th)
-    GNUNET_MESH_notify_transmit_ready_cancel (state->th);
-
-  GNUNET_free (state);
-}
-
-
-/**
- * Create a message queue for a mesh tunnel.
- * The message queue can only be used to transmit messages,
- * not to receive them.
- *
- * @param tunnel the tunnel to create the message qeue for
- * @return a message queue to messages over the tunnel
- */
-struct GNUNET_MQ_Handle *
-GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MQ_Handle *mq;
-  struct MeshMQState *state;
-
-  state = GNUNET_new (struct MeshMQState);
-  state->tunnel = tunnel;
-
-  mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl,
-                                      mesh_mq_destroy_impl,
-                                      NULL, /* FIXME: cancel impl. */
-                                      state,
-                                      NULL, /* no msg handlers */
-                                      NULL, /* no err handlers */
-                                      NULL); /* no handler cls */
-  return mq;
-}
-

Deleted: gnunet/src/mesh/mesh2_protocol.h
===================================================================
--- gnunet/src/mesh/mesh2_protocol.h    2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh2_protocol.h    2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,316 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @author Bartlomiej Polot
- * @file mesh/mesh_protocol.h
- */
-
-#ifndef MESH_PROTOCOL_H_
-#define MESH_PROTOCOL_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0
-  /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#define MESH_TUNNEL_OPT_NOBUFFER        0x2
-
-
-/******************************************************************************/
-/********************      MESH NETWORK MESSAGES     
**************************/
-/******************************************************************************/
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Message for mesh path creation.
- */
-struct GNUNET_MESH_CreateTunnel
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE
-     *
-     * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
-     *       path_length * sizeof (struct GNUNET_PeerIdentity)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * Global id of the tunnel this path belongs to,
-     * unique in conjunction with the origin.
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * Tunnel options (MESH_TUNNEL_OPT_*).
-     */
-  uint32_t opt GNUNET_PACKED;
-
-    /**
-     * Destination port.
-     */
-  uint32_t port GNUNET_PACKED;
-
-    /**
-     * FIXME do not add the first hop
-     * path_length structs defining the *whole* path from the origin [0] to the
-     * final destination [path_length-1].
-     */
-  /* struct GNUNET_PeerIdentity peers[path_length]; */
-};
-
-/**
- * Message for mesh path destruction.
- */
-struct GNUNET_MESH_DestroyTunnel
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY
-   *
-   * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
-   *       path_length * sizeof (struct GNUNET_PeerIdentity)
-   */
-  struct GNUNET_MessageHeader header;
-  
-  /**
-   * Global id of the tunnel this path belongs to,
-   * unique in conjunction with the origin.
-   */
-  uint32_t tid GNUNET_PACKED;
-};
-
-
-/**
- * Message for mesh data traffic.
- */
-struct GNUNET_MESH_Data
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST,
-     *       GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * Number of hops to live
-     */
-  uint32_t ttl GNUNET_PACKED;
-
-    /**
-     * Unique ID of the packet
-     */
-  uint32_t pid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * Payload follows
-     */
-};
-
-
-/**
- * Message to acknowledge mesh data traffic.
- */
-struct GNUNET_MESH_ACK
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * Maximum packet ID authorized.
-     */
-  uint32_t pid;
-
-};
-
-/**
- * Message to query a peer about its Flow Control status regarding a tunnel.
- */
-struct GNUNET_MESH_Poll
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_MESH_POLL
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * TID of the tunnel
-   */
-  uint32_t tid GNUNET_PACKED;
-
-  /**
-   * OID of the tunnel
-   */
-  struct GNUNET_PeerIdentity oid;
-};
-
-/**
- * Message for ack'ing a path
- */
-struct GNUNET_MESH_PathACK
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer_id;
-
-    /**
-     * Initial ACK value for payload.
-     */
-  uint32_t ack GNUNET_PACKED;
-
-  /* TODO: signature */
-};
-
-
-/**
- * Message for notifying a disconnection in a path
- */
-struct GNUNET_MESH_PathBroken
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer1;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer2;
-
-  /* TODO: signature */
-};
-
-
-/**
- * Message to destroy a tunnel
- */
-struct GNUNET_MESH_TunnelDestroy
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-  /* TODO: signature */
-};
-
-
-/**
- * Message to destroy a tunnel
- */
-struct GNUNET_MESH_TunnelKeepAlive
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE
-   */
-  struct GNUNET_MessageHeader header;
-  
-  /**
-   * TID of the tunnel
-   */
-  uint32_t tid GNUNET_PACKED;
-  
-  /**
-   * OID of the tunnel
-   */
-  struct GNUNET_PeerIdentity oid;
-};
-
-
-
-GNUNET_NETWORK_STRUCT_END
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef MESH_PROTOCOL_H */
-#endif
-/* end of mesh_protocol.h */

Deleted: gnunet/src/mesh/mesh2_test_lib.c
===================================================================
--- gnunet/src/mesh/mesh2_test_lib.c    2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh2_test_lib.c    2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,283 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/mesh2_test_lib.c
- * @author Bartlomiej Polot
- * @brief library for writing MESH tests
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "mesh2_test_lib.h"
-#include "gnunet_mesh2_service.h"
-
-/**
- * Test context for a MESH Test.
- */
-struct GNUNET_MESH_TEST_Context
-{
-  /**
-   * Array of running peers.
-   */
-  struct GNUNET_TESTBED_Peer **peers;
-
-  /**
-   * Array of handles to the MESH for each peer.
-   */
-  struct GNUNET_MESH_Handle **meshes;
-
-  /**
-   * Operation associated with the connection to the MESH.
-   */
-  struct GNUNET_TESTBED_Operation **ops;
-
-  /**
-   * Main function of the test to run once all MESHs are available.
-   */
-  GNUNET_MESH_TEST_AppMain app_main;
-  
-  /**
-   * Closure for 'app_main'.
-   */
-  void *app_main_cls;
-
-  /**
-   * Number of peers running, size of the arrays above.
-   */
-  unsigned int num_peers;
-
-  /**
-   * Handler for incoming tunnels.
-   */
-  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
-
-  /**
-   * Cleaner for destroyed incoming tunnels.
-   */
-  GNUNET_MESH_TunnelEndHandler *cleaner;
-
-  /**
-   * Message handlers.
-   */
-  struct GNUNET_MESH_MessageHandler* handlers;
-
-  /**
-   * Application ports.
-   */
-  const uint32_t *ports;
-
-};
-
-
-/**
- * Context for a mesh adapter callback.
- */
-struct GNUNET_MESH_TEST_AdapterContext
-{
-  /**
-   * Peer number for the particular peer.
-   */
-  unsigned int peer;
-
-  /**
-   * General context.
-   */
-  struct GNUNET_MESH_TEST_Context *ctx;
-};
-
-
-/**
- * Adapter function called to establish a connection to
- * the MESH service.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- *          GNUNET_TESTBED_operation_done() is called on the operation returned
- *          from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-mesh_connect_adapter (void *cls,
-                      const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
-  struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
-  struct GNUNET_MESH_Handle *h;
-
-  h = GNUNET_MESH_connect (cfg,
-                           (void *) (long) actx->peer,
-                           ctx->new_tunnel,
-                           ctx->cleaner,
-                           ctx->handlers,
-                           ctx->ports);
-  return h;
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * the MESH service.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void 
-mesh_disconnect_adapter (void *cls,
-                         void *op_result)
-{
-  struct GNUNET_MESH_Handle *mesh = op_result;
-  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
-
-  GNUNET_free (actx);
-  GNUNET_MESH_disconnect (mesh);
-}
-
-
-/**
- * Callback to be called when a service connect operation is completed.
- *
- * @param cls The callback closure from functions generating an operation.
- * @param op The operation that has been finished.
- * @param ca_result The service handle returned from 
- *                  GNUNET_TESTBED_ConnectAdapter() (mesh handle).
- * @param emsg Error message in case the operation has failed.
- *             NULL if operation has executed successfully.
- */
-static void 
-mesh_connect_cb (void *cls,
-                 struct GNUNET_TESTBED_Operation *op,
-                 void *ca_result,
-                 const char *emsg)
-{
-  struct GNUNET_MESH_TEST_Context *ctx = cls;
-  unsigned int i;
- 
-  if (NULL != emsg)
-  {
-    fprintf (stderr, "Failed to connect to MESH service: %s\n",
-             emsg);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  for (i = 0; i < ctx->num_peers; i++)
-    if (op == ctx->ops[i])
-      ctx->meshes[i] = ca_result;
-  for (i = 0; i < ctx->num_peers; i++)
-    if (NULL == ctx->meshes[i])
-      return; /* still some MESH connections missing */
-  /* all MESH connections ready! */
-  ctx->app_main (ctx->app_main_cls,
-                 ctx,
-                 ctx->num_peers,
-                 ctx->peers,
-                 ctx->meshes);
-}
-
-
-void
-GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
-{
-  unsigned int i;
-
-  for (i = 0; i < ctx->num_peers; i++)
-  {
-    GNUNET_assert (NULL != ctx->ops[i]);
-    GNUNET_TESTBED_operation_done (ctx->ops[i]);
-    ctx->ops[i] = NULL;
-  }
-  GNUNET_free (ctx->ops);
-  GNUNET_free (ctx->meshes);
-  GNUNET_free (ctx);
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callback run when the testbed is ready (peers running and connected to
- * each other)
- * 
- * @param cls Closure (context).
- * @param num_peers Number of peers that are running.
- * @param peers Handles to each one of the @c num_peers peers.
- * @param links_succeeded the number of overlay link connection attempts that
- *          succeeded
- * @param links_failed the number of overlay link connection attempts that
- *          failed
- */
-static void
-mesh_test_run (void *cls,
-               unsigned int num_peers,
-               struct GNUNET_TESTBED_Peer **peers,
-               unsigned int links_succeeded,
-               unsigned int links_failed)
-{
-  struct GNUNET_MESH_TEST_Context *ctx = cls;
-  unsigned int i;
-
-  GNUNET_assert (num_peers == ctx->num_peers);
-  ctx->peers = peers;
-  for (i = 0; i < num_peers; i++)
-  {
-    struct GNUNET_MESH_TEST_AdapterContext *newctx;
-    newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
-    newctx->peer = i;
-    newctx->ctx = ctx;
-    ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
-                                                  peers[i],
-                                                  "mesh",
-                                                  &mesh_connect_cb,
-                                                  ctx,
-                                                  &mesh_connect_adapter,
-                                                  &mesh_disconnect_adapter,
-                                                  newctx);
-  }
-}
-
-
-void 
-GNUNET_MESH_TEST_run (const char *testname,
-                      const char *cfgname,
-                      unsigned int num_peers,
-                      GNUNET_MESH_TEST_AppMain tmain,
-                      void *tmain_cls,
-                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                      GNUNET_MESH_TunnelEndHandler cleaner,
-                      struct GNUNET_MESH_MessageHandler* handlers,
-                      const uint32_t *ports)
-{
-  struct GNUNET_MESH_TEST_Context *ctx;
-
-  ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
-  ctx->num_peers = num_peers;
-  ctx->ops = GNUNET_malloc (num_peers * sizeof (struct 
GNUNET_TESTBED_Operation *));
-  ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle 
*));
-  ctx->app_main = tmain;
-  ctx->app_main_cls = tmain_cls;
-  ctx->new_tunnel = new_tunnel;
-  ctx->cleaner = cleaner;
-  ctx->handlers = handlers;
-  ctx->ports = ports;
-  GNUNET_TESTBED_test_run (testname,
-                           cfgname,
-                           num_peers,
-                           0LL, NULL, NULL,
-                           &mesh_test_run, ctx);
-}
-
-/* end of mesh_test_lib.c */

Deleted: gnunet/src/mesh/mesh2_test_lib.h
===================================================================
--- gnunet/src/mesh/mesh2_test_lib.h    2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh2_test_lib.h    2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,106 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/mesh2_test_lib.h
- * @author Bartlomiej Polot
- * @brief library for writing MESH tests
- */
-#ifndef MESH_TEST_LIB_H
-#define MESH_TEST_LIB_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_testbed_service.h"
-#include "gnunet_mesh2_service.h"
-
-/**
- * Test context for a MESH Test.
- */
-struct GNUNET_MESH_TEST_Context;
-
-
-/**
- * Main function of a MESH test.
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param peers Array of peers.
- * @param meshes Handle to each of the MESHs of the peers.
- */
-typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls,
-                                          struct GNUNET_MESH_TEST_Context *ctx,
-                                          unsigned int num_peers,
-                                          struct GNUNET_TESTBED_Peer **peers,
-                                          struct GNUNET_MESH_Handle **meshes);
-
-
-/**
- * Run a test using the given name, configuration file and number of
- * peers.
- * All mesh callbacks will receive the peer number as the closure.
- *
- * @param testname Name of the test (for logging).
- * @param cfgname Name of the configuration file.
- * @param num_peers Number of peers to start.
- * @param tmain Main function to run once the testbed is ready.
- * @param tmain_cls Closure for 'tmain'.
- * @param new_tunnel Handler for incoming tunnels.
- * @param cleaner Cleaner for destroyed incoming tunnels.
- * @param handlers Message handlers.
- * @param ports Ports the peers offer.
- */
-void 
-GNUNET_MESH_TEST_run (const char *testname,
-                      const char *cfgname,
-                      unsigned int num_peers,
-                      GNUNET_MESH_TEST_AppMain tmain,
-                      void *tmain_cls,
-                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                      GNUNET_MESH_TunnelEndHandler cleaner,
-                      struct GNUNET_MESH_MessageHandler* handlers,
-                      const uint32_t* ports);
-
-
-/**
- * Clean up the testbed.
- *
- * @param ctx handle for the testbed
- */
-void
-GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-
-/* ifndef MESH_TEST_LIB_H */
-#endif

Deleted: gnunet/src/mesh/mesh_api.c
===================================================================
--- gnunet/src/mesh/mesh_api.c  2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh_api.c  2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,2417 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/mesh_api.c
- * @brief mesh api: client implementation of mesh service
- * @author Bartlomiej Polot
- *
- * STRUCTURE:
- * - DATA STRUCTURES
- * - DECLARATIONS
- * - AUXILIARY FUNCTIONS
- * - RECEIVE HANDLERS
- * - SEND FUNCTIONS
- * - API CALL DEFINITIONS
- *
- * TODO: add regex to reconnect
- */
-#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_client_lib.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_peer_lib.h"
-#include "gnunet_mesh_service.h"
-#include "mesh.h"
-#include "mesh_protocol.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__)
-
-#define DEBUG_ACK GNUNET_YES
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/**
- * Transmission queue to the service
- */
-struct GNUNET_MESH_TransmitHandle
-{
-
-    /**
-     * Double Linked list
-     */
-  struct GNUNET_MESH_TransmitHandle *next;
-
-    /**
-     * Double Linked list
-     */
-  struct GNUNET_MESH_TransmitHandle *prev;
-
-    /**
-     * Tunnel this message is sent on / for (may be NULL for control messages).
-     */
-  struct GNUNET_MESH_Tunnel *tunnel;
-
-    /**
-     * Callback to obtain the message to transmit, or NULL if we
-     * got the message in 'data'.  Notice that messages built
-     * by 'notify' need to be encapsulated with information about
-     * the 'target'.
-     */
-  GNUNET_CONNECTION_TransmitReadyNotify notify;
-
-    /**
-     * Closure for 'notify'
-     */
-  void *notify_cls;
-
-    /**
-     * How long is this message valid.  Once the timeout has been
-     * reached, the message must no longer be sent.  If this
-     * is a message with a 'notify' callback set, the 'notify'
-     * function should be called with 'buf' NULL and size 0.
-     */
-  struct GNUNET_TIME_Absolute timeout;
-
-    /**
-     * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-    /**
-     * Target of the message, 0 for multicast.  This field
-     * is only valid if 'notify' is non-NULL.
-     */
-  GNUNET_PEER_Id target;
-
-    /**
-     * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
-     */
-  size_t size;
-};
-
-
-/**
- * Opaque handle to the service.
- */
-struct GNUNET_MESH_Handle
-{
-
-    /**
-     * Handle to the server connection, to send messages later
-     */
-  struct GNUNET_CLIENT_Connection *client;
-
-    /**
-     * Set of handlers used for processing incoming messages in the tunnels
-     */
-  const struct GNUNET_MESH_MessageHandler *message_handlers;
-
-    /**
-     * Set of applications that should be claimed to be offered at this node.
-     * Note that this is just informative, the appropiate handlers must be
-     * registered independently and the mapping is up to the developer of the
-     * client application.
-     */
-  GNUNET_MESH_ApplicationType *applications;
-
-    /**
-     * Double linked list of the tunnels this client is connected to, head.
-     */
-  struct GNUNET_MESH_Tunnel *tunnels_head;
-
-    /**
-     * Double linked list of the tunnels this client is connected to, tail.
-     */
-  struct GNUNET_MESH_Tunnel *tunnels_tail;
-
-    /**
-     * Callback for inbound tunnel creation
-     */
-  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
-
-    /**
-     * Callback for inbound tunnel disconnection
-     */
-  GNUNET_MESH_TunnelEndHandler *cleaner;
-
-    /**
-     * Handle to cancel pending transmissions in case of disconnection
-     */
-  struct GNUNET_CLIENT_TransmitHandle *th;
-
-    /**
-     * Closure for all the handlers given by the client
-     */
-  void *cls;
-
-    /**
-     * Messages to send to the service, head.
-     */
-  struct GNUNET_MESH_TransmitHandle *th_head;
-
-    /**
-     * Messages to send to the service, tail.
-     */
-  struct GNUNET_MESH_TransmitHandle *th_tail;
-
-    /**
-     * tid of the next tunnel to create (to avoid reusing IDs often)
-     */
-  MESH_TunnelNumber next_tid;
-
-    /**
-     * Number of handlers in the handlers array.
-     */
-  unsigned int n_handlers;
-
-    /**
-     * Number of applications in the applications array.
-     */
-  unsigned int n_applications;
-
-    /**
-     * Have we started the task to receive messages from the service
-     * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
-     */
-  int in_receive;
-
-  /**
-   * Configuration given by the client, in case of reconnection
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Time to the next reconnect in case one reconnect fails
-   */
-  struct GNUNET_TIME_Relative reconnect_time;
-  
-  /**
-   * Task for trying to reconnect.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
-
-  /**
-   * Monitor callback
-   */
-  GNUNET_MESH_TunnelsCB tunnels_cb;
-
-  /**
-   * Monitor callback closure.
-   */
-  void *tunnels_cls;
-
-  /**
-   * Tunnel callback.
-   */
-  GNUNET_MESH_TunnelCB tunnel_cb;
-
-  /**
-   * Tunnel callback closure.
-   */
-  void *tunnel_cls;
-
-  /**
-   * All the peer in the tunnel so far.
-   */
-  struct GNUNET_PeerIdentity *peers;
-
-  /**
-   * How many peers we have in this tunnel so far.
-   */
-  unsigned int tunnel_npeers;
-
-#if DEBUG_ACK
-  unsigned int acks_sent;
-  unsigned int acks_recv;
-#endif
-};
-
-
-/**
- * Description of a peer
- */
-struct GNUNET_MESH_Peer
-{
-    /**
-     * ID of the peer in short form
-     */
-  GNUNET_PEER_Id id;
-
-  /**
-   * Tunnel this peer belongs to
-   */
-  struct GNUNET_MESH_Tunnel *t;
-
-  /**
-   * Flag indicating whether service has informed about its connection
-   */
-  int connected;
-
-};
-
-
-/**
- * Opaque handle to a tunnel.
- */
-struct GNUNET_MESH_Tunnel
-{
-
-    /**
-     * DLL next
-     */
-  struct GNUNET_MESH_Tunnel *next;
-
-    /**
-     * DLL prev
-     */
-  struct GNUNET_MESH_Tunnel *prev;
-
-    /**
-     * Callback to execute when peers connect to the tunnel
-     */
-  GNUNET_MESH_PeerConnectHandler connect_handler;
-
-    /**
-     * Callback to execute when peers disconnect from the tunnel
-     */
-  GNUNET_MESH_PeerDisconnectHandler disconnect_handler;
-
-    /**
-     * Closure for the connect/disconnect handlers
-     */
-  void *cls;
-
-    /**
-     * Handle to the mesh this tunnel belongs to
-     */
-  struct GNUNET_MESH_Handle *mesh;
-
-    /**
-     * Local ID of the tunnel
-     */
-  MESH_TunnelNumber tid;
-
-    /**
-     * Owner of the tunnel. 0 if the tunnel is the local client.
-     */
-  GNUNET_PEER_Id owner;
-
-    /**
-     * All peers added to the tunnel
-     */
-  struct GNUNET_MESH_Peer **peers;
-
-  /**
-   * List of application types that have been requested for this tunnel
-   */
-  GNUNET_MESH_ApplicationType *apps;
-
-  /**
-   * Any data the caller wants to put in here
-   */
-  void *ctx;
-
-  /**
-     * Number of peers added to the tunnel
-     */
-  unsigned int npeers;
-
-    /**
-     * Size of packet queued in this tunnel
-     */
-  unsigned int packet_size;
-
-    /**
-     * Number of applications requested this tunnel
-     */
-  unsigned int napps;
-
-    /**
-     * Is the tunnel throttled to the slowest peer?
-     */
-  int speed_min;
-
-    /**
-     * Is the tunnel allowed to buffer?
-     */
-  int buffering;
-
-    /**
-     * Next packet ID to send.
-     */
-  uint32_t next_send_pid;
-
-    /**
-     * Maximum allowed PID to send (ACK recevied).
-     */
-  uint32_t max_send_pid;
-
-    /**
-     * Last pid received from the service.
-     */
-  uint32_t last_recv_pid;
-
-  /**
-   * Which ACK value have we last sent to the service?
-   */
-  uint32_t max_recv_pid;
-};
-
-
-/******************************************************************************/
-/***********************         DECLARATIONS         
*************************/
-/******************************************************************************/
-
-/**
- * Function called to send a message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, the mesh handle
- * @param size number of bytes available in buf
- * @param buf where the callee should write the connect message
- * @return number of bytes written to buf
- */
-static size_t
-send_callback (void *cls, size_t size, void *buf);
-
-
-/******************************************************************************/
-/***********************     AUXILIARY FUNCTIONS      
*************************/
-/******************************************************************************/
-
-/**
- * Check if transmission is a payload packet.
- *
- * @param th Transmission handle.
- *
- * @return GNUNET_YES if it is a payload packet,
- *         GNUNET_NO if it is a mesh management packet.
- */
-static int
-th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
-{
-  return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Check whether there is any message ready in the queue and find the size.
- * 
- * @param h Mesh handle.
- * 
- * @return The size of the first ready message in the queue,
- *         0 if there is none.
- */
-static size_t
-message_ready_size (struct GNUNET_MESH_Handle *h)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_Tunnel *t;
-
-  for (th = h->th_head; NULL != th; th = th->next)
-  {
-    t = th->tunnel;
-    if (GNUNET_NO == th_is_payload (th))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  message internal\n");
-      return th->size;
-    }
-    if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  message payload ok (%u <= %u)\n",
-           t->next_send_pid, t->max_send_pid);
-      return th->size;
-    }
-  }
-  return 0;
-}
-
-
-/**
- * Get the tunnel handler for the tunnel specified by id from the given handle
- * @param h Mesh handle
- * @param tid ID of the wanted tunnel
- * @return handle to the required tunnel or NULL if not found
- */
-static struct GNUNET_MESH_Tunnel *
-retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
-{
-  struct GNUNET_MESH_Tunnel *t;
-
-  t = h->tunnels_head;
-  while (t != NULL)
-  {
-    if (t->tid == tid)
-      return t;
-    t = t->next;
-  }
-  return NULL;
-}
-
-
-/**
- * Create a new tunnel and insert it in the tunnel list of the mesh handle
- * @param h Mesh handle
- * @param tid desired tid of the tunnel, 0 to assign one automatically
- * @return handle to the created tunnel
- */
-static struct GNUNET_MESH_Tunnel *
-create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
-{
-  struct GNUNET_MESH_Tunnel *t;
-
-  t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
-  GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
-  t->mesh = h;
-  if (0 == tid)
-  {
-    t->tid = h->next_tid;
-    while (NULL != retrieve_tunnel (h, h->next_tid))
-    {
-      h->next_tid++;
-      h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
-      h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-    }
-  }
-  else
-  {
-    t->tid = tid;
-  }
-  t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
-  t->last_recv_pid = (uint32_t) -1;
-  t->buffering = GNUNET_YES;
-  return t;
-}
-
-
-/**
- * Destroy the specified tunnel.
- * - Destroys all peers, calling the disconnect callback on each if needed
- * - Cancels all outgoing traffic for that tunnel, calling respective notifys
- * - Calls cleaner if tunnel was inbound
- * - Frees all memory used
- *
- * @param t Pointer to the tunnel.
- * @param call_cleaner Whether to call the cleaner handler.
- *
- * @return Handle to the required tunnel or NULL if not found.
- */
-static void
-destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
-{
-  struct GNUNET_MESH_Handle *h;
-  struct GNUNET_PeerIdentity pi;
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_TransmitHandle *next;
-  unsigned int i;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
-
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  h = t->mesh;
-
-  /* disconnect all peers */
-  GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
-  for (i = 0; i < t->npeers; i++)
-  {
-    if ( (NULL != t->disconnect_handler) && t->peers[i]->connected)
-    {
-      GNUNET_PEER_resolve (t->peers[i]->id, &pi);
-      t->disconnect_handler (t->cls, &pi);
-    }
-    GNUNET_PEER_change_rc (t->peers[i]->id, -1);
-    GNUNET_free (t->peers[i]);
-  }
-
-  /* signal tunnel destruction */
-  if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) 
)
-    h->cleaner (h->cls, t, t->ctx);
-
-  /* check that clients did not leave messages behind in the queue */
-  for (th = h->th_head; NULL != th; th = next)
-  {
-    next = th->next;
-    if (th->tunnel != t)
-      continue;
-    /* Clients should have aborted their requests already.
-     * Management traffic should be ok, as clients can't cancel that */
-    GNUNET_break (GNUNET_NO == th_is_payload(th));
-    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-
-    /* clean up request */
-    if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
-      GNUNET_SCHEDULER_cancel (th->timeout_task);
-    GNUNET_free (th);    
-  }
-
-  /* if there are no more pending requests with mesh service, cancel active 
request */
-  /* Note: this should be unnecessary... */
-  if ((0 == message_ready_size (h)) && (NULL != h->th))
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
-    h->th = NULL;
-  }
-
-
-  if (t->npeers > 0)
-    GNUNET_free (t->peers);
-  if (0 != t->owner)
-    GNUNET_PEER_change_rc (t->owner, -1);
-  if (0 != t->napps && t->apps)
-    GNUNET_free (t->apps);
-  GNUNET_free (t);
-  return;
-}
-
-
-/**
- * Get the peer descriptor for the peer with id from the given tunnel
- * @param t Tunnel handle
- * @param id Short form ID of the wanted peer
- * @return handle to the requested peer or NULL if not found
- */
-static struct GNUNET_MESH_Peer *
-retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
-{
-  unsigned int i;
-
-  for (i = 0; i < t->npeers; i++)
-    if (t->peers[i]->id == id)
-      return t->peers[i];
-  return NULL;
-}
-
-
-/**
- * Add a peer into a tunnel
- * @param t Tunnel handle
- * @param pi Full ID of the new peer
- * @return handle to the newly created peer
- */
-static struct GNUNET_MESH_Peer *
-add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
-                    const struct GNUNET_PeerIdentity *pi)
-{
-  struct GNUNET_MESH_Peer *p;
-  GNUNET_PEER_Id id;
-
-  if (0 != t->owner)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  id = GNUNET_PEER_intern (pi);
-
-  p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
-  p->id = id;
-  p->t = t;
-  GNUNET_array_append (t->peers, t->npeers, p);
-  return p;
-}
-
-
-/**
- * Remove a peer from a tunnel
- * @param p Peer handle
- */
-static void
-remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
-{
-  unsigned int i;
-
-  for (i = 0; i < p->t->npeers; i++)
-  {
-    if (p->t->peers[i] == p)
-      break;
-  }
-  if (i == p->t->npeers)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  p->t->peers[i] = p->t->peers[p->t->npeers - 1];
-  GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
-}
-
-
-/**
- * Notify client that the transmission has timed out
- * 
- * @param cls closure
- * @param tc task context
- */
-static void
-timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_MESH_TransmitHandle *th = cls;
-  struct GNUNET_MESH_Handle *mesh;
-
-  mesh = th->tunnel->mesh;
-  GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
-  th->tunnel->packet_size = 0;
-  if (GNUNET_YES == th_is_payload (th))
-    th->notify (th->notify_cls, 0, NULL);
-  GNUNET_free (th);
-  if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
-  {
-    /* nothing ready to transmit, no point in asking for transmission */
-    GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
-    mesh->th = NULL;
-  }
-}
-
-
-/**
- * Add a transmit handle to the transmission queue and set the
- * timeout if needed.
- *
- * @param h mesh handle with the queue head and tail
- * @param th handle to the packet to be transmitted
- */
-static void
-add_to_queue (struct GNUNET_MESH_Handle *h,
-              struct GNUNET_MESH_TransmitHandle *th)
-{
-  GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
-  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
-    return;
-  th->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                    (th->timeout), &timeout_transmission, th);
-}
-
-
-/**
- * Auxiliary function to send an already constructed packet to the service.
- * Takes care of creating a new queue element, copying the message and
- * calling the tmt_rdy function if necessary.
- *
- * @param h mesh handle
- * @param msg message to transmit
- * @param tunnel tunnel this send is related to (NULL if N/A)
- */
-static void
-send_packet (struct GNUNET_MESH_Handle *h,
-             const struct GNUNET_MessageHeader *msg,
-             struct GNUNET_MESH_Tunnel *tunnel);
-
-
-/**
- * Send an ack on the tunnel to confirm the processing of a message.
- * 
- * @param h Mesh handle.
- * @param t Tunnel on which to send the ACK.
- */
-static void
-send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t)
-{
-  struct GNUNET_MESH_LocalAck msg;
-  uint32_t delta;
-
-  delta = t->max_recv_pid - t->last_recv_pid;
-  if (delta > ACK_THRESHOLD)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
-         t->tid, t->max_recv_pid, t->last_recv_pid, delta);
-    return;
-  }
-  if (GNUNET_YES == t->buffering)
-    t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE;
-  else
-    t->max_recv_pid = t->last_recv_pid + 1;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Sending ACK on tunnel %X: %u\n",
-       t->tid, t->max_recv_pid);
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
-  msg.header.size = htons (sizeof (msg));
-  msg.tunnel_id = htonl (t->tid);
-  msg.max_pid = htonl (t->max_recv_pid);
-
-#if DEBUG_ACK
-  t->mesh->acks_sent++;
-#endif
-
-  send_packet (h, &msg.header, t);
-  return;
-}
-
-
-
-/**
- * Reconnect callback: tries to reconnect again after a failer previous
- * reconnecttion
- * @param cls closure (mesh handle)
- * @param tc task context
- */
-static void
-reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Send a connect packet to the service with the applications and types
- * requested by the user.
- *
- * @param h The mesh handle.
- *
- */
-static void
-send_connect (struct GNUNET_MESH_Handle *h)
-{
-  size_t size;
-
-  size = sizeof (struct GNUNET_MESH_ClientConnect);
-  size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
-  size += h->n_handlers * sizeof (uint16_t);
-  {
-    char buf[size] GNUNET_ALIGN;
-    struct GNUNET_MESH_ClientConnect *msg;
-    GNUNET_MESH_ApplicationType *apps;
-    uint16_t napps;
-    uint16_t *types;
-    uint16_t ntypes;
-
-    /* build connection packet */
-    msg = (struct GNUNET_MESH_ClientConnect *) buf;
-    msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
-    msg->header.size = htons (size);
-    apps = (GNUNET_MESH_ApplicationType *) &msg[1];
-    for (napps = 0; napps < h->n_applications; napps++)
-    {
-      apps[napps] = htonl (h->applications[napps]);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n",
-           h->applications[napps]);
-    }
-    types = (uint16_t *) & apps[napps];
-    for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
-    {
-      types[ntypes] = htons (h->message_handlers[ntypes].type);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n",
-           h->message_handlers[ntypes].type);
-    }
-    msg->applications = htons (napps);
-    msg->types = htons (ntypes);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Sending %lu bytes long message %d types and %d apps\n",
-         ntohs (msg->header.size), ntypes, napps);
-    send_packet (h, &msg->header, NULL);
-  }
-}
-
-
-/**
- * Reconnect to the service, retransmit all infomation to try to restore the
- * original state.
- *
- * @param h handle to the mesh
- *
- * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
- */
-static int
-do_reconnect (struct GNUNET_MESH_Handle *h)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  unsigned int i;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-
-  /* disconnect */
-  if (NULL != h->th)
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
-    h->th = NULL;
-  }
-  if (NULL != h->client)
-  {
-    GNUNET_CLIENT_disconnect (h->client);
-  }
-
-  /* connect again */
-  h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
-  if (h->client == NULL)
-  {
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-    h->reconnect_time =
-        GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
-                                  GNUNET_TIME_relative_multiply
-                                  (h->reconnect_time, 2));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, 
-        "Next retry in %s\n",
-         GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
-                                                GNUNET_NO));
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-  else
-  {
-    h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
-  }
-  send_connect (h);
-  /* Rebuild all tunnels */
-  for (t = h->tunnels_head; NULL != t; t = t->next)
-  {
-    struct GNUNET_MESH_TunnelMessage tmsg;
-    struct GNUNET_MESH_PeerControl pmsg;
-
-    if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    {
-      /* Tunnel was created by service (incoming tunnel) */
-      /* TODO: Notify service of missing tunnel, to request
-       * creator to recreate path (find a path to him via DHT?)
-       */
-      continue;
-    }
-    t->next_send_pid = 0;
-    t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
-    t->last_recv_pid = (uint32_t) -1;
-    tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
-    tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-    tmsg.tunnel_id = htonl (t->tid);
-    send_packet (h, &tmsg.header, t);
-
-    pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-    pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
-    pmsg.tunnel_id = htonl (t->tid);
-
-    /* Reconnect all peers */
-    /* If the tunnel was "by type", dont connect individual peers */
-    for (i = 0; i < t->npeers && 0 == t->napps; i++)
-    {
-      GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
-      if (NULL != t->disconnect_handler && t->peers[i]->connected)
-        t->disconnect_handler (t->cls, &pmsg.peer);
-      send_packet (t->mesh, &pmsg.header, t);
-    }
-    /* Reconnect all types, if any  */
-    for (i = 0; i < t->napps; i++)
-    {
-      struct GNUNET_MESH_ConnectPeerByType msg;
-
-      msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
-      msg.header.type = htons 
(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
-      msg.tunnel_id = htonl (t->tid);
-      msg.type = htonl (t->apps[i]);
-      send_packet (t->mesh, &msg.header, t);
-    }
-    if (GNUNET_NO == t->buffering)
-      GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
-    if (GNUNET_YES == t->speed_min)
-      GNUNET_MESH_tunnel_speed_min (t);
-  }
-  return GNUNET_YES;
-}
-
-/**
- * Reconnect callback: tries to reconnect again after a failer previous
- * reconnecttion
- * @param cls closure (mesh handle)
- * @param tc task context
- */
-static void
-reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_MESH_Handle *h = cls;
-
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  do_reconnect (h);
-}
-
-
-/**
- * Reconnect to the service, retransmit all infomation to try to restore the
- * original state.
- *
- * @param h handle to the mesh
- *
- * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
- */
-static void
-reconnect (struct GNUNET_MESH_Handle *h)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
-  h->in_receive = GNUNET_NO;
-  if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-}
-
-
-/******************************************************************************/
-/***********************      RECEIVE HANDLERS     
****************************/
-/******************************************************************************/
-
-/**
- * Process the new tunnel notification and add it to the tunnels in the handle
- *
- * @param h     The mesh handle
- * @param msg   A message with the details of the new incoming tunnel
- */
-static void
-process_tunnel_created (struct GNUNET_MESH_Handle *h,
-                        const struct GNUNET_MESH_TunnelNotification *msg)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  MESH_TunnelNumber tid;
-
-  tid = ntohl (msg->tunnel_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
-  if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (NULL != h->new_tunnel)
-  {
-    struct GNUNET_ATS_Information atsi;
-
-    t = create_tunnel (h, tid);
-    t->owner = GNUNET_PEER_intern (&msg->peer);
-    t->npeers = 1;
-    t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
-    t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
-    t->peers[0]->t = t;
-    t->peers[0]->connected = 1;
-    t->peers[0]->id = t->owner;
-    GNUNET_PEER_change_rc (t->owner, 1);
-    t->mesh = h;
-    t->tid = tid;
-    if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0)
-      t->buffering = GNUNET_NO;
-    else
-      t->buffering = GNUNET_YES;
-    if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0)
-      t->speed_min = GNUNET_YES;
-    atsi.type = 0;
-    atsi.value = 0;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
-    t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
-  }
-  else
-  {
-    struct GNUNET_MESH_TunnelMessage d_msg;
-
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
-
-    d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-    d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-    d_msg.tunnel_id = msg->tunnel_id;
-
-    send_packet (h, &d_msg.header, NULL);
-  }
-  return;
-}
-
-
-/**
- * Process the tunnel destroy notification and free associated resources
- *
- * @param h     The mesh handle
- * @param msg   A message with the details of the tunnel being destroyed
- */
-static void
-process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
-                        const struct GNUNET_MESH_TunnelMessage *msg)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  MESH_TunnelNumber tid;
-
-  tid = ntohl (msg->tunnel_id);
-  t = retrieve_tunnel (h, tid);
-
-  if (NULL == t)
-  {
-    return;
-  }
-  if (0 == t->owner)
-  {
-    GNUNET_break (0);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
-  destroy_tunnel (t, GNUNET_YES);
-  return;
-}
-
-
-/**
- * Process the new peer event and notify the upper level of it
- *
- * @param h     The mesh handle
- * @param msg   A message with the details of the peer event
- */
-static void
-process_peer_event (struct GNUNET_MESH_Handle *h,
-                    const struct GNUNET_MESH_PeerControl *msg)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  struct GNUNET_MESH_Peer *p;
-  struct GNUNET_ATS_Information atsi;
-  GNUNET_PEER_Id id;
-  uint16_t size;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
-  size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_MESH_PeerControl))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  id = GNUNET_PEER_search (&msg->peer);
-  if ((p = retrieve_peer (t, id)) == NULL)
-    p = add_peer_to_tunnel (t, &msg->peer);
-  if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
-    if (NULL != t->connect_handler)
-    {
-      atsi.type = 0;
-      atsi.value = 0;
-      t->connect_handler (t->cls, &msg->peer, &atsi);
-    }
-    p->connected = 1;
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
-    if (NULL != t->disconnect_handler && p->connected)
-    {
-      t->disconnect_handler (t->cls, &msg->peer);
-    }
-    remove_peer_from_tunnel (p);
-    GNUNET_free (p);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
-}
-
-
-/**
- * Process the incoming data packets
- *
- * @param h         The mesh handle
- * @param message   A message encapsulating the data
- * 
- * @return GNUNET_YES if everything went fine
- *         GNUNET_NO if client closed connection (h no longer valid)
- */
-static int
-process_incoming_data (struct GNUNET_MESH_Handle *h,
-                       const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_MessageHeader *payload;
-  const struct GNUNET_MESH_MessageHandler *handler;
-  const struct GNUNET_PeerIdentity *peer;
-  struct GNUNET_MESH_Unicast *ucast;
-  struct GNUNET_MESH_Multicast *mcast;
-  struct GNUNET_MESH_ToOrigin *to_orig;
-  struct GNUNET_MESH_Tunnel *t;
-  unsigned int i;
-  uint32_t pid;
-  uint16_t type;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
-  type = ntohs (message->type);
-  switch (type)
-  {
-  case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-    ucast = (struct GNUNET_MESH_Unicast *) message;
-
-    t = retrieve_tunnel (h, ntohl (ucast->tid));
-    payload = (struct GNUNET_MessageHeader *) &ucast[1];
-    peer = &ucast->oid;
-    pid = ntohl (ucast->pid);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ucast on tunnel %s [%X]\n",
-         GNUNET_i2s (peer), ntohl (ucast->tid));
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-    mcast = (struct GNUNET_MESH_Multicast *) message;
-    t = retrieve_tunnel (h, ntohl (mcast->tid));
-    payload = (struct GNUNET_MessageHeader *) &mcast[1];
-    peer = &mcast->oid;
-    pid = ntohl (mcast->pid);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  mcast on tunnel %s [%X]\n",
-         GNUNET_i2s (peer), ntohl (mcast->tid));
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-    to_orig = (struct GNUNET_MESH_ToOrigin *) message;
-    t = retrieve_tunnel (h, ntohl (to_orig->tid));
-    payload = (struct GNUNET_MessageHeader *) &to_orig[1];
-    peer = &to_orig->sender;
-    pid = ntohl (to_orig->pid);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  torig on tunnel %s [%X]\n",
-         GNUNET_i2s (peer), ntohl (to_orig->tid));
-    break;
-  default:
-    GNUNET_break (0);
-    return GNUNET_YES;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
-  if (NULL == t)
-  {
-    /* Tunnel was ignored/destroyed, probably service didn't get it yet */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
-    return GNUNET_YES;
-  }
-  if (GNUNET_YES ==
-      GMC_is_pid_bigger(pid, t->max_recv_pid))
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "  unauthorized message! (%u, max %u)\n",
-         pid, t->max_recv_pid);
-    // FIXME fc what now? accept? reject?
-    return GNUNET_YES;
-  }
-  t->last_recv_pid = pid;
-  type = ntohs (payload->type);
-  send_ack (h, t);
-  for (i = 0; i < h->n_handlers; i++)
-  {
-    handler = &h->message_handlers[i];
-    if (handler->type == type)
-    {
-      struct GNUNET_ATS_Information atsi;
-
-      atsi.type = 0;
-      atsi.value = 0;
-      if (GNUNET_OK !=
-          handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
-        GNUNET_MESH_disconnect (h);
-        return GNUNET_NO;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG,
-             "callback completed successfully\n");
-      }
-    }
-  }
-  return GNUNET_YES;
-}
-
-
-/**
- * Process a local ACK message, enabling the client to send
- * more data to the service.
- * 
- * @param h Mesh handle.
- * @param message Message itself.
- */
-static void
-process_ack (struct GNUNET_MESH_Handle *h,
-             const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalAck *msg;
-  struct GNUNET_MESH_Tunnel *t;
-  uint32_t ack;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
-  h->acks_recv++;
-  msg = (struct GNUNET_MESH_LocalAck *) message;
-
-  t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
-
-  if (NULL == t)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "ACK on unknown tunnel %X\n",
-         ntohl (msg->tunnel_id));
-    return;
-  }
-  ack = ntohl (msg->max_pid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
-  if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid))
-    t->max_send_pid = ack;
-  else
-    return;
-  if (NULL == h->th && 0 < t->packet_size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, 
ack);
-    h->th =
-        GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             GNUNET_YES, &send_callback, h);
-  }
-}
-
-
-/**
- * Process a local reply about info on all tunnels, pass info to the user.
- *
- * @param h Mesh handle.
- * @param message Message itself.
- */
-static void
-process_get_tunnels (struct GNUNET_MESH_Handle *h,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalMonitor *msg;
-  uint32_t npeers;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
-
-  if (NULL == h->tunnels_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
-    return;
-  }
-
-  msg = (struct GNUNET_MESH_LocalMonitor *) message;
-  npeers = ntohl (msg->npeers);
-  if (ntohs (message->size) !=
-      (sizeof (struct GNUNET_MESH_LocalMonitor) +
-       npeers * sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Get tunnels message: size %hu - expected %u (%u peers)\n",
-                ntohs (message->size),
-                sizeof (struct GNUNET_MESH_LocalMonitor) +
-                npeers * sizeof (struct GNUNET_PeerIdentity),
-                npeers);
-    return;
-  }
-  h->tunnels_cb (h->tunnels_cls,
-                 &msg->owner,
-                 ntohl (msg->tunnel_id),
-                 (struct GNUNET_PeerIdentity *) &msg[1],
-                 npeers);
-}
-
-
-
-/**
- * Process a local monitor_tunnel reply, pass info to the user.
- *
- * @param h Mesh handle.
- * @param message Message itself.
- */
-static void
-process_show_tunnel (struct GNUNET_MESH_Handle *h,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_LocalMonitor *msg;
-  struct GNUNET_PeerIdentity *new_peers;
-  uint32_t *new_parents;
-  size_t esize;
-  uint32_t npeers;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
-
-  if (NULL == h->tunnel_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
-    return;
-  }
-
-  /* Verify message sanity */
-  msg = (struct GNUNET_MESH_LocalMonitor *) message;
-  npeers = ntohl (msg->npeers);
-  esize = sizeof (struct GNUNET_MESH_LocalMonitor);
-  esize += npeers * (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t));
-  if (ntohs (message->size) != esize)
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Show tunnel message: size %hu - expected %u (%u peers)\n",
-                ntohs (message->size),
-                esize,
-                npeers);
-
-    h->tunnel_cb (h->tunnel_cls, NULL, NULL);
-    h->tunnel_cb = NULL;
-    h->tunnel_cls = NULL;
-    h->tunnel_npeers = 0;
-    GNUNET_free_non_null (h->peers);
-    h->peers = NULL;
-
-    return;
-  }
-
-  new_peers = (struct GNUNET_PeerIdentity *) &msg[1];
-  new_parents = (uint32_t *) &new_peers[npeers];
-
-  h->peers = GNUNET_realloc (h->peers, h->tunnel_npeers + npeers);
-  memcpy (&h->peers[h->tunnel_npeers],
-          new_peers,
-          npeers * sizeof (struct GNUNET_PeerIdentity));
-  h->tunnel_npeers += npeers;
-  for (i = 0; i < npeers; i++)
-    h->tunnel_cb (h->tunnel_cls,
-                  &new_peers[i],
-                  &h->peers[new_parents[i]]);
-}
-
-
-/**
- * Function to process all messages received from the service
- *
- * @param cls closure
- * @param msg message received, NULL on timeout or fatal error
- */
-static void
-msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_MESH_Handle *h = cls;
-
-  if (msg == NULL)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, 
-        "Mesh service disconnected, reconnecting\n", h);
-    reconnect (h);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
-       GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
-       GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
-  switch (ntohs (msg->type))
-  {
-    /* Notify of a new incoming tunnel */
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
-    process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
-    break;
-    /* Notify of a tunnel disconnection */
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
-    process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
-    break;
-    /* Notify of a new peer or a peer disconnect in the tunnel */
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
-    process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
-    break;
-    /* Notify of a new data packet in the tunnel */
-  case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
-  case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
-  case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
-    if (GNUNET_NO == process_incoming_data (h, msg))
-      return;
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
-    process_ack (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
-        process_get_tunnels (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
-        process_show_tunnel (h, msg);
-    break;
-  default:
-    /* We shouldn't get any other packages, log and ignore */
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "unsolicited message form service (type %s)\n",
-         GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
-  if (GNUNET_YES == h->in_receive)
-  {
-    GNUNET_CLIENT_receive (h->client, &msg_received, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "in receive off, not calling CLIENT_receive\n");
-  }
-}
-
-
-/******************************************************************************/
-/************************       SEND FUNCTIONS     
****************************/
-/******************************************************************************/
-
-/**
- * Function called to send a message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, the mesh handle
- * @param size number of bytes available in buf
- * @param buf where the callee should write the connect message
- * @return number of bytes written to buf
- */
-static size_t
-send_callback (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MESH_Handle *h = cls;
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_TransmitHandle *next;
-  struct GNUNET_MESH_Tunnel *t;
-  char *cbuf = buf;
-  size_t tsize;
-  size_t psize;
-  size_t nsize;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size);
-  if ((0 == size) || (NULL == buf))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h);
-    reconnect (h);
-    h->th = NULL;
-    return 0;
-  }
-  tsize = 0;
-  next = h->th_head;
-  nsize = message_ready_size (h);
-  while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
-  {
-    t = th->tunnel;
-    if (GNUNET_YES == th_is_payload (th))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n");
-      if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
-      {
-        /* This tunnel is not ready to transmit yet, try next message */
-        next = th->next;
-        continue;
-      }
-      t->packet_size = 0;
-      if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-      {
-        /* traffic to origin */
-        struct GNUNET_MESH_ToOrigin to;
-        struct GNUNET_MessageHeader *mh;
-
-        GNUNET_assert (size >= th->size);
-        mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
-        psize = th->notify (th->notify_cls, size - sizeof (to), mh);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  to origin, type %s\n",
-             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-        if (psize > 0)
-        {
-          psize += sizeof (to);
-          GNUNET_assert (size >= psize);
-          to.header.size = htons (psize);
-          to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
-          to.tid = htonl (t->tid);
-          to.pid = htonl (t->next_send_pid);
-          to.ttl = 0;
-          memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
-          memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
-          memcpy (cbuf, &to, sizeof (to));
-        }
-      }
-      else if (th->target == 0)
-      {
-        /* multicast */
-        struct GNUNET_MESH_Multicast mc;
-        struct GNUNET_MessageHeader *mh;
-
-        GNUNET_assert (size >= th->size);
-        mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
-        psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  multicast, type %s\n",
-             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-        if (psize > 0)
-        {
-          psize += sizeof (mc);
-          GNUNET_assert (size >= psize);
-          mc.header.size = htons (psize);
-          mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
-          mc.tid = htonl (t->tid);
-          mc.pid = htonl (t->next_send_pid);
-          mc.ttl = 0;
-          memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
-          memcpy (cbuf, &mc, sizeof (mc));
-        }
-      }
-      else
-      {
-        /* unicast */
-        struct GNUNET_MESH_Unicast uc;
-        struct GNUNET_MessageHeader *mh;
-
-        GNUNET_assert (size >= th->size);
-        mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
-        psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  unicast, type %s\n",
-             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-        if (psize > 0)
-        {
-          psize += sizeof (uc);
-          GNUNET_assert (size >= psize);
-          uc.header.size = htons (psize);
-          uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
-          uc.tid = htonl (t->tid);
-          uc.pid = htonl (t->next_send_pid);
-          uc.ttl = 0;
-          memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
-          GNUNET_PEER_resolve (th->target, &uc.destination);
-          memcpy (cbuf, &uc, sizeof (uc));
-        }
-      }
-      t->next_send_pid++;
-    }
-    else
-    {
-      struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  mesh traffic, type %s\n",
-           GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
-      memcpy (cbuf, &th[1], th->size);
-      psize = th->size;
-    }
-    if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-      GNUNET_SCHEDULER_cancel (th->timeout_task);
-    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-    GNUNET_free (th);
-    next = h->th_head;
-    nsize = message_ready_size (h);
-    cbuf += psize;
-    size -= psize;
-    tsize += psize;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  total size: %u\n", tsize);
-  h->th = NULL;
-  size = message_ready_size (h);
-  if (0 != size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  next size: %u\n", size);
-    h->th =
-        GNUNET_CLIENT_notify_transmit_ready (h->client, size,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             GNUNET_YES, &send_callback, h);
-  }
-  else
-  {
-    if (NULL != h->th_head)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  can't transmit any more\n");
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  nothing left to transmit\n");
-  }
-  if (GNUNET_NO == h->in_receive)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n");
-    h->in_receive = GNUNET_YES;
-    GNUNET_CLIENT_receive (h->client, &msg_received, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n");
-  return tsize;
-}
-
-
-/**
- * Auxiliary function to send an already constructed packet to the service.
- * Takes care of creating a new queue element, copying the message and
- * calling the tmt_rdy function if necessary.
- * 
- * @param h mesh handle
- * @param msg message to transmit
- * @param tunnel tunnel this send is related to (NULL if N/A)
- */
-static void
-send_packet (struct GNUNET_MESH_Handle *h,
-             const struct GNUNET_MessageHeader *msg,
-             struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  size_t msize;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
-       GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
-  msize = ntohs (msg->size);
-  th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
-  th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
-  th->size = msize;
-  th->tunnel = tunnel;
-  memcpy (&th[1], msg, msize);
-  add_to_queue (h, th);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
-  if (NULL != h->th)
-    return;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", 
msize);
-  h->th =
-      GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &send_callback, h);
-}
-
-
-/******************************************************************************/
-/**********************      API CALL DEFINITIONS     
*************************/
-/******************************************************************************/
-
-/**
- * Connect to the mesh service.
- *
- * @param cfg configuration to use
- * @param cls closure for the various callbacks that follow
- *            (including handlers in the handlers array)
- * @param new_tunnel function called when an *inbound* tunnel is created
- * @param cleaner function called when an *inbound* tunnel is destroyed by the
- *                remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
- *                is called on the tunnel
- * @param handlers callbacks for messages we care about, NULL-terminated
- *                note that the mesh is allowed to drop notifications about
- *                inbound messages if the client does not process them fast
- *                enough (for this notification type, a bounded queue is used)
- * @param stypes list of the applications that this client claims to provide
- * @return handle to the mesh service NULL on error
- *         (in this case, init is never called)
- */
-struct GNUNET_MESH_Handle *
-GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
-                     GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                     GNUNET_MESH_TunnelEndHandler cleaner,
-                     const struct GNUNET_MESH_MessageHandler *handlers,
-                     const GNUNET_MESH_ApplicationType *stypes)
-{
-  struct GNUNET_MESH_Handle *h;
-  size_t size;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
-  h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
-  h->cfg = cfg;
-  h->new_tunnel = new_tunnel;
-  h->cleaner = cleaner;
-  h->client = GNUNET_CLIENT_connect ("mesh", cfg);
-  if (h->client == NULL)
-  {
-    GNUNET_break (0);
-    GNUNET_free (h);
-    return NULL;
-  }
-  h->cls = cls;
-  h->message_handlers = handlers;
-  h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
-  h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-
-  /* count apps */
-  for (h->n_applications = 0;
-       stypes && stypes[h->n_applications];
-       h->n_applications++) ;
-  if (0 < h->n_applications)
-  {
-    size = h->n_applications * sizeof (GNUNET_MESH_ApplicationType *);
-    h->applications = GNUNET_malloc (size);
-    memcpy (h->applications, stypes, size);
-  }
-  /* count handlers */
-  for (h->n_handlers = 0;
-       handlers && handlers[h->n_handlers].type;
-       h->n_handlers++) ;
-  send_connect (h);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
-  return h;
-}
-
-
-/**
- * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
- * disconnect callbacks will be called on any still connected peers, notifying
- * about their disconnection. The registered inbound tunnel cleaner will be
- * called should any inbound tunnels still exist.
- *
- * @param handle connection to mesh to disconnect
- */
-void
-GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  struct GNUNET_MESH_Tunnel *aux;
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
-
-#if DEBUG_ACK
-  LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
-  LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
-#endif
-
-  t = handle->tunnels_head;
-  while (NULL != t)
-  {
-    aux = t->next;
-    if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    {
-      GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
-    }
-    destroy_tunnel (t, GNUNET_YES);
-    t = aux;
-  }
-  while ( (th = handle->th_head) != NULL)
-  {
-    struct GNUNET_MessageHeader *msg;
-
-    /* Make sure it is an allowed packet (everything else should have been
-     * already canceled).
-     */
-    GNUNET_break (GNUNET_NO == th_is_payload (th));
-    msg = (struct GNUNET_MessageHeader *) &th[1];
-    switch (ntohs(msg->type))
-    {
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
-      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
-        break;
-      default:
-        GNUNET_break (0);
-        LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
-             ntohs(msg->type));
-    }
-
-    GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
-    GNUNET_free (th);
-  }
-
-  if (NULL != handle->th)
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
-    handle->th = NULL;
-  }
-  if (NULL != handle->client)
-  {
-    GNUNET_CLIENT_disconnect (handle->client);
-    handle->client = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel(handle->reconnect_task);
-    handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_free_non_null (handle->applications);
-  GNUNET_free (handle);
-}
-
-
-/**
- * Announce to ther peer the availability of services described by the regex,
- * in order to be reachable to other peers via connect_by_string.
- * 
- * Note that the first 8 characters are considered to be part of a prefix,
- * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
- * all matching strings will be stored in the DHT.
- *
- * @param h Handle to mesh.
- * @param regex String with the regular expression describing local services.
- * @param compression_characters How many characters can be assigned to one
- *                               edge of the graph. The bigger the variability
- *                               of the data, the smaller this parameter should
- *                               be (down to 1).
- *                               For maximum compression, use strlen (regex)
- *                               or 0 (special value). Use with care!
- */
-void
-GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
-                            const char *regex,
-                            unsigned int compression_characters)
-{
-  struct GNUNET_MESH_RegexAnnounce *msg;
-  size_t payload;
-  size_t len;
-  size_t msgsize;
-  size_t offset;
-  char buffer[UINT16_MAX];
-
-  len = strlen (regex);
-  payload = UINT16_MAX - sizeof(struct GNUNET_MESH_RegexAnnounce);
-  msg = (struct GNUNET_MESH_RegexAnnounce *) buffer;
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
-  msg->compression_characters = htons (compression_characters);
-  offset = 0;
-  do
-  {
-    msgsize = (len - offset > payload) ? payload : len - offset;
-    memcpy (&msg[1], &regex[offset], msgsize);
-    offset += msgsize;
-    msgsize += sizeof(struct GNUNET_MESH_RegexAnnounce);
-
-    msg->header.size = htons (msgsize);
-    msg->last = htons (offset >= len);
-
-    send_packet (h, &msg->header, NULL);
-  } while (len > offset);
-}
-
-/**
- * Create a new tunnel (we're initiator and will be allowed to add/remove peers
- * and to broadcast).
- *
- * @param h mesh handle
- * @param tunnel_ctx client's tunnel context to associate with the tunnel
- * @param connect_handler function to call when peers are actually connected
- * @param disconnect_handler function to call when peers are disconnected
- * @param handler_cls closure for connect/disconnect handlers
- */
-struct GNUNET_MESH_Tunnel *
-GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
-                           GNUNET_MESH_PeerConnectHandler connect_handler,
-                           GNUNET_MESH_PeerDisconnectHandler 
disconnect_handler,
-                           void *handler_cls)
-{
-  struct GNUNET_MESH_Tunnel *t;
-  struct GNUNET_MESH_TunnelMessage msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
-  t = create_tunnel (h, 0);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
-  t->connect_handler = connect_handler;
-  t->disconnect_handler = disconnect_handler;
-  t->cls = handler_cls;
-  t->ctx = tunnel_ctx;
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (t->tid);
-  send_packet (h, &msg.header, t);
-  return t;
-}
-
-
-/**
- * Destroy an existing tunnel. The existing callback for the tunnel will NOT
- * be called.
- *
- * @param tunnel tunnel handle
- */
-void
-GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MESH_Handle *h;
-  struct GNUNET_MESH_TunnelMessage msg;
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
-  h = tunnel->mesh;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (tunnel->tid);
-  th = h->th_head;
-  while (th != NULL)
-  {
-    struct GNUNET_MESH_TransmitHandle *aux;
-    if (th->tunnel == tunnel)
-    {
-      aux = th->next;
-      /* FIXME call the handler? */
-      if (GNUNET_YES == th_is_payload (th))
-        th->notify (th->notify_cls, 0, NULL);
-      GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-      GNUNET_free (th);
-      th = aux;
-    }
-    else
-      th = th->next;
-  }
-
-  destroy_tunnel (tunnel, GNUNET_NO);
-  send_packet (h, &msg.header, NULL);
-}
-
-/**
- * Request that the tunnel data rate is limited to the speed of the slowest
- * receiver.
- *
- * @param tunnel Tunnel affected.
- */
-void
-GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-  struct GNUNET_MESH_Handle *h;
-
-  h = tunnel->mesh;
-  tunnel->speed_min = GNUNET_YES;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (tunnel->tid);
-
-  send_packet (h, &msg.header, NULL);
-}
-
-
-/**
- * Request that the tunnel data rate is limited to the speed of the fastest
- * receiver. This is the default behavior.
- *
- * @param tunnel Tunnel affected.
- */
-void
-GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-  struct GNUNET_MESH_Handle *h;
-
-  h = tunnel->mesh;
-  tunnel->speed_min = GNUNET_NO;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (tunnel->tid);
-
-  send_packet (h, &msg.header, NULL);
-}
-
-/**
- * Turn on/off the buffering status of the tunnel.
- * 
- * @param tunnel Tunnel affected.
- * @param buffer GNUNET_YES to turn buffering on (default),
- *               GNUNET_NO otherwise.
- */
-void
-GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
-{
-  struct GNUNET_MESH_TunnelMessage msg;
-  struct GNUNET_MESH_Handle *h;
-
-  h = tunnel->mesh;
-  tunnel->buffering = buffer;
-  tunnel->max_send_pid = tunnel->next_send_pid;
-
-  if (GNUNET_YES == buffer)
-    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
-  else
-    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
-  msg.tunnel_id = htonl (tunnel->tid);
-
-  send_packet (h, &msg.header, NULL);
-}
-
-
-/**
- * Request that a peer should be added to the tunnel.  The existing
- * connect handler will be called ONCE with either success or failure.
- * This function should NOT be called again with the same peer before the
- * connect handler is called.
- * FIXME: I think the above documentation is false. I think it should
- * read: "The connect handler will be called once the peer was actually
- * successfully added to the multicast group. This function should
- * not be called twice for the same peer (unless, of course,
- * the peer was removed using GNUNET_MESH_peer_Request_connect_del in
- * the meantime).
- *
- * @param tunnel handle to existing tunnel
- * @param peer peer to add
- */
-void
-GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
-                                      const struct GNUNET_PeerIdentity *peer)
-{
-  struct GNUNET_MESH_PeerControl msg;
-  GNUNET_PEER_Id peer_id;
-  unsigned int i;
-
-  peer_id = GNUNET_PEER_intern (peer);
-  for (i = 0; i < tunnel->npeers; i++)
-  {
-    if (tunnel->peers[i]->id == peer_id)
-    {
-      /* Peer already exists in tunnel */
-      GNUNET_PEER_change_rc (peer_id, -1);
-      GNUNET_break (0);
-      return;
-    }
-  }
-  if (NULL == add_peer_to_tunnel (tunnel, peer))
-    return;
-
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
-  msg.tunnel_id = htonl (tunnel->tid);
-  msg.peer = *peer;
-  send_packet (tunnel->mesh, &msg.header, tunnel);
-}
-
-
-/**
- * Request that a peer should be removed from the tunnel.  The existing
- * disconnect handler will be called ONCE if we were connected.
- *
- * @param tunnel handle to existing tunnel
- * @param peer peer to remove
- */
-void
-GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
-                                      const struct GNUNET_PeerIdentity *peer)
-{
-  struct GNUNET_MESH_PeerControl msg;
-  GNUNET_PEER_Id peer_id;
-  unsigned int i;
-
-  peer_id = GNUNET_PEER_search (peer);
-  if (0 == peer_id)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  for (i = 0; i < tunnel->npeers; i++)
-    if (tunnel->peers[i]->id == peer_id)
-      break;
-  if (i == tunnel->npeers)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
-    tunnel->disconnect_handler (tunnel->cls, peer);
-  GNUNET_PEER_change_rc (peer_id, -1);
-  GNUNET_free (tunnel->peers[i]);
-  tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
-  GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
-
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
-  msg.tunnel_id = htonl (tunnel->tid);
-  memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
-  send_packet (tunnel->mesh, &msg.header, tunnel);
-}
-
-
-/**
- * Request that the mesh should try to connect to a peer supporting the given
- * message type.
- *
- * @param tunnel handle to existing tunnel
- * @param app_type application type that must be supported by the peer (MESH
- *                 should discover peer in proximity handling this type)
- */
-void
-GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
-                                          GNUNET_MESH_ApplicationType app_type)
-{
-  struct GNUNET_MESH_ConnectPeerByType msg;
-
-  GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n");
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
-  msg.tunnel_id = htonl (tunnel->tid);
-  msg.type = htonl (app_type);
-  send_packet (tunnel->mesh, &msg.header, tunnel);
-}
-
-
-/**
- * Request that the mesh should try to connect to a peer matching the
- * description given in the service string.
- * 
- * FIXME: allow multiple? how to deal with reconnect?
- *
- * @param tunnel handle to existing tunnel
- * @param description string describing the destination node requirements
- */
-void
-GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
-                                            const char *description)
-{
-  struct GNUNET_MESH_ConnectPeerByString *m;
-  size_t len;
-  size_t msgsize;
-
-  len = strlen (description);
-  msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
-  GNUNET_assert (UINT16_MAX > msgsize);
-  {
-    char buffer[msgsize];
-
-    m = (struct GNUNET_MESH_ConnectPeerByString *) buffer;
-    m->header.size = htons (msgsize);
-    m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
-    m->tunnel_id = htonl (tunnel->tid);
-    memcpy(&m[1], description, len);
-
-    send_packet (tunnel->mesh, &m->header, tunnel);
-  }
-}
-
-
-/**
- * Request that the given peer isn't added to this tunnel in calls to
- * connect_by_* calls, (due to misbehaviour, bad performance, ...).
- *
- * @param tunnel handle to existing tunnel.
- * @param peer peer identity of the peer which should be blacklisted
- *                  for the tunnel.
- */
-void
-GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
-                            const struct GNUNET_PeerIdentity *peer)
-{
-  struct GNUNET_MESH_PeerControl msg;
-
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
-  msg.tunnel_id = htonl (tunnel->tid);
-  msg.peer = *peer;
-  send_packet (tunnel->mesh, &msg.header, tunnel);
-
-  return;
-}
-
-
-/**
- * Request that the given peer isn't blacklisted anymore from this tunnel,
- * and therefore can be added in future calls to connect_by_*.
- * The peer must have been previously blacklisted for this tunnel.
- *
- * @param tunnel handle to existing tunnel.
- * @param peer peer identity of the peer which shouldn't be blacklisted
- *                  for the tunnel anymore.
- */
-void
-GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
-                              const struct GNUNET_PeerIdentity *peer)
-{
-  struct GNUNET_MESH_PeerControl msg;
-
-  msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
-  msg.tunnel_id = htonl (tunnel->tid);
-  msg.peer = *peer;
-  send_packet (tunnel->mesh, &msg.header, tunnel);
-
-  return;
-}
-
-
-/**
- * Ask the mesh to call "notify" once it is ready to transmit the
- * given number of bytes to the specified tunnel or target.
- * Only one call can be active at any time, to issue another request,
- * wait for the callback or cancel the current request.
- *
- * @param tunnel tunnel to use for transmission
- * @param cork is corking allowed for this transmission?
- * @param maxdelay how long can the message wait?
- * @param target destination for the message
- *               NULL for multicast to all tunnel targets
- * @param notify_size how many bytes of buffer space does notify want?
- * @param notify function to call when buffer space is available;
- *        will be called with NULL on timeout or if the overall queue
- *        for this peer is larger than queue_size and this is currently
- *        the message with the lowest priority
- * @param notify_cls closure for notify
- * @return non-NULL if the notify callback was queued,
- *         NULL if we can not even queue the request (insufficient
- *         memory); if NULL is returned, "notify" will NOT be called.
- */
-struct GNUNET_MESH_TransmitHandle *
-GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
-                                   struct GNUNET_TIME_Relative maxdelay,
-                                   const struct GNUNET_PeerIdentity *target,
-                                   size_t notify_size,
-                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
-                                   void *notify_cls)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  size_t overhead;
-
-  GNUNET_assert (NULL != tunnel);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
-  if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
-  else if (NULL != target)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    target %s\n", GNUNET_i2s (target));
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    target multicast\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
-  GNUNET_assert (NULL != notify);
-  GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
-  th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
-  th->tunnel = tunnel;
-  th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
-  th->target = GNUNET_PEER_intern (target);
-  if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
-    overhead = sizeof (struct GNUNET_MESH_ToOrigin);
-  else if (NULL == target)
-    overhead = sizeof (struct GNUNET_MESH_Multicast);
-  else
-    overhead = sizeof (struct GNUNET_MESH_Unicast);
-  tunnel->packet_size = th->size = notify_size + overhead;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
-  th->notify = notify;
-  th->notify_cls = notify_cls;
-  add_to_queue (tunnel->mesh, th);
-  if (NULL != tunnel->mesh->th)
-    return th;
-  if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid))
-    return th;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    call notify tmt rdy\n");
-  tunnel->mesh->th =
-      GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &send_callback,
-                                           tunnel->mesh);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
-  return th;
-}
-
-
-/**
- * Cancel the specified transmission-ready notification.
- *
- * @param th handle that was returned by "notify_transmit_ready".
- */
-void
-GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle 
*th)
-{
-  struct GNUNET_MESH_Handle *mesh;
-
-  th->tunnel->packet_size = 0;
-  mesh = th->tunnel->mesh;
-  if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (th->timeout_task);
-  GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
-  GNUNET_free (th);
-  if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
-  {
-    /* queue empty, no point in asking for transmission */
-    GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
-    mesh->th = NULL;
-  }
-}
-
-
-/**
- * Request information about the running mesh peer.
- * The callback will be called for every tunnel known to the service,
- * listing all active peers that blong to the tunnel.
- *
- * If called again on the same handle, it will overwrite the previous
- * callback and cls. To retrieve the cls, monitor_cancel must be
- * called first.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
-                         GNUNET_MESH_TunnelsCB callback,
-                         void *callback_cls)
-{
-  struct GNUNET_MessageHeader msg;
-
-  msg.size = htons (sizeof (msg));
-  msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
-  send_packet (h, &msg, NULL);
-  h->tunnels_cb = callback;
-  h->tunnels_cls = callback_cls;
-
-  return;
-}
-
-
-/**
- * Cancel a monitor request. The monitor callback will not be called.
- *
- * @param h Mesh handle.
- *
- * @return Closure given to GNUNET_MESH_monitor, if any.
- */
-void *
-GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
-{
-  void *cls;
-
-  cls = h->tunnels_cls;
-  h->tunnels_cb = NULL;
-  h->tunnels_cls = NULL;
-  return cls;
-}
-
-
-/**
- * Request information about a specific tunnel of the running mesh peer.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the mesh peer.
- * @param initiator ID of the owner of the tunnel.
- * @param tunnel_number Tunnel number.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- */
-void
-GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
-                         struct GNUNET_PeerIdentity *initiator,
-                         unsigned int tunnel_number,
-                         GNUNET_MESH_TunnelCB callback,
-                         void *callback_cls)
-{
-  struct GNUNET_MESH_LocalMonitor msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
-  msg.npeers = htonl (0);
-  msg.owner = *initiator;
-  msg.tunnel_id = htonl (tunnel_number);
-  msg.reserved = 0;
-  send_packet (h, &msg.header, NULL);
-  h->tunnel_cb = callback;
-  h->tunnel_cls = callback_cls;
-
-  return;
-}
-
-
-/**
- * Transition API for tunnel ctx management
- */
-void
-GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
-{
-  tunnel->ctx = data;
-}
-
-/**
- * Transition API for tunnel ctx management
- */
-void *
-GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
-{
-  return tunnel->ctx;
-}
-
-

Copied: gnunet/src/mesh/mesh_api.c (from rev 27670, gnunet/src/mesh/mesh2_api.c)
===================================================================
--- gnunet/src/mesh/mesh_api.c                          (rev 0)
+++ gnunet/src/mesh/mesh_api.c  2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,1787 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file mesh/mesh_api.c
+ * @brief mesh api: client implementation of new mesh service
+ * @author Bartlomiej Polot
+ *
+ * STRUCTURE:
+ * - DATA STRUCTURES
+ * - DECLARATIONS
+ * - AUXILIARY FUNCTIONS
+ * - RECEIVE HANDLERS
+ * - SEND FUNCTIONS
+ * - API CALL DEFINITIONS
+ *
+ * TODO: add regex to reconnect
+ */
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_client_lib.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_peer_lib.h"
+#include "gnunet_mesh_service.h"
+#include "mesh.h"
+#include "mesh_protocol.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__)
+#define DEBUG_ACK GNUNET_YES
+
+/******************************************************************************/
+/************************      DATA STRUCTURES     
****************************/
+/******************************************************************************/
+
+/**
+ * Transmission queue to the service
+ */
+struct GNUNET_MESH_TransmitHandle
+{
+
+    /**
+     * Double Linked list
+     */
+  struct GNUNET_MESH_TransmitHandle *next;
+
+    /**
+     * Double Linked list
+     */
+  struct GNUNET_MESH_TransmitHandle *prev;
+
+    /**
+     * Tunnel this message is sent on / for (may be NULL for control messages).
+     */
+  struct GNUNET_MESH_Tunnel *tunnel;
+
+    /**
+     * Callback to obtain the message to transmit, or NULL if we
+     * got the message in 'data'.  Notice that messages built
+     * by 'notify' need to be encapsulated with information about
+     * the 'target'.
+     */
+  GNUNET_CONNECTION_TransmitReadyNotify notify;
+
+    /**
+     * Closure for 'notify'
+     */
+  void *notify_cls;
+
+    /**
+     * How long is this message valid.  Once the timeout has been
+     * reached, the message must no longer be sent.  If this
+     * is a message with a 'notify' callback set, the 'notify'
+     * function should be called with 'buf' NULL and size 0.
+     */
+  struct GNUNET_TIME_Absolute timeout;
+
+    /**
+     * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
+     */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+    /**
+     * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
+     */
+  size_t size;
+};
+
+
+/**
+ * Opaque handle to the service.
+ */
+struct GNUNET_MESH_Handle
+{
+
+    /**
+     * Handle to the server connection, to send messages later
+     */
+  struct GNUNET_CLIENT_Connection *client;
+
+    /**
+     * Set of handlers used for processing incoming messages in the tunnels
+     */
+  const struct GNUNET_MESH_MessageHandler *message_handlers;
+
+  /**
+   * Number of handlers in the handlers array.
+   */
+  unsigned int n_handlers;
+
+  /**
+   * Ports open.
+   */
+  const uint32_t *ports;
+
+  /**
+   * Number of ports.
+   */
+  unsigned int n_ports;
+
+    /**
+     * Double linked list of the tunnels this client is connected to, head.
+     */
+  struct GNUNET_MESH_Tunnel *tunnels_head;
+
+    /**
+     * Double linked list of the tunnels this client is connected to, tail.
+     */
+  struct GNUNET_MESH_Tunnel *tunnels_tail;
+
+    /**
+     * Callback for inbound tunnel creation
+     */
+  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
+
+    /**
+     * Callback for inbound tunnel disconnection
+     */
+  GNUNET_MESH_TunnelEndHandler *cleaner;
+
+    /**
+     * Handle to cancel pending transmissions in case of disconnection
+     */
+  struct GNUNET_CLIENT_TransmitHandle *th;
+
+    /**
+     * Closure for all the handlers given by the client
+     */
+  void *cls;
+
+    /**
+     * Messages to send to the service, head.
+     */
+  struct GNUNET_MESH_TransmitHandle *th_head;
+
+    /**
+     * Messages to send to the service, tail.
+     */
+  struct GNUNET_MESH_TransmitHandle *th_tail;
+
+    /**
+     * tid of the next tunnel to create (to avoid reusing IDs often)
+     */
+  MESH_TunnelNumber next_tid;
+
+    /**
+     * Have we started the task to receive messages from the service
+     * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
+     */
+  int in_receive;
+
+  /**
+   * Configuration given by the client, in case of reconnection
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Time to the next reconnect in case one reconnect fails
+   */
+  struct GNUNET_TIME_Relative reconnect_time;
+  
+  /**
+   * Task for trying to reconnect.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
+
+  /**
+   * Monitor callback
+   */
+  GNUNET_MESH_TunnelsCB tunnels_cb;
+
+  /**
+   * Monitor callback closure.
+   */
+  void *tunnels_cls;
+
+  /**
+   * Tunnel callback.
+   */
+  GNUNET_MESH_TunnelCB tunnel_cb;
+
+  /**
+   * Tunnel callback closure.
+   */
+  void *tunnel_cls;
+
+#if DEBUG_ACK
+  unsigned int acks_sent;
+  unsigned int acks_recv;
+#endif
+};
+
+
+/**
+ * Description of a peer
+ */
+struct GNUNET_MESH_Peer
+{
+    /**
+     * ID of the peer in short form
+     */
+  GNUNET_PEER_Id id;
+
+  /**
+   * Tunnel this peer belongs to
+   */
+  struct GNUNET_MESH_Tunnel *t;
+
+  /**
+   * Flag indicating whether service has informed about its connection
+   */
+  int connected;
+
+};
+
+
+/**
+ * Opaque handle to a tunnel.
+ */
+struct GNUNET_MESH_Tunnel
+{
+
+    /**
+     * DLL next
+     */
+  struct GNUNET_MESH_Tunnel *next;
+
+    /**
+     * DLL prev
+     */
+  struct GNUNET_MESH_Tunnel *prev;
+
+    /**
+     * Handle to the mesh this tunnel belongs to
+     */
+  struct GNUNET_MESH_Handle *mesh;
+
+    /**
+     * Local ID of the tunnel
+     */
+  MESH_TunnelNumber tid;
+
+    /**
+     * Port number.
+     */
+  uint32_t port;
+
+    /**
+     * Other end of the tunnel.
+     */
+  GNUNET_PEER_Id peer;
+
+  /**
+   * Any data the caller wants to put in here
+   */
+  void *ctx;
+
+    /**
+     * Size of packet queued in this tunnel
+     */
+  unsigned int packet_size;
+
+    /**
+     * Is the tunnel allowed to buffer?
+     */
+  int buffering;
+
+    /**
+     * Maximum allowed PID to send (last ACK recevied).
+     */
+  uint32_t last_ack_recv;
+
+    /**
+     * Last PID received from the service.
+     */
+  uint32_t last_pid_recv;
+
+  /**
+   * Last packet ID sent to the service.
+   */
+  uint32_t last_pid_sent;
+
+  /**
+   * Last ACK value sent to the service: how much are we willing to accept?
+   */
+  uint32_t last_ack_sent;
+};
+
+
+/**
+ * Implementation state for mesh's message queue.
+ */
+struct MeshMQState
+{
+  /**
+   * The current transmit handle, or NULL
+   * if no transmit is active.
+   */
+  struct GNUNET_MESH_TransmitHandle *th;
+
+  /**
+   * Tunnel to send the data over.
+   */
+  struct GNUNET_MESH_Tunnel *tunnel;
+};
+
+
+/******************************************************************************/
+/***********************         DECLARATIONS         
*************************/
+/******************************************************************************/
+
+/**
+ * Function called to send a message to the service.
+ * "buf" will be NULL and "size" zero if the socket was closed for writing in
+ * the meantime.
+ *
+ * @param cls closure, the mesh handle
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the connect message
+ * @return number of bytes written to buf
+ */
+static size_t
+send_callback (void *cls, size_t size, void *buf);
+
+
+/******************************************************************************/
+/***********************     AUXILIARY FUNCTIONS      
*************************/
+/******************************************************************************/
+
+/**
+ * Check if transmission is a payload packet.
+ *
+ * @param th Transmission handle.
+ *
+ * @return GNUNET_YES if it is a payload packet,
+ *         GNUNET_NO if it is a mesh management packet.
+ */
+static int
+th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
+{
+  return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Check whether there is any message ready in the queue and find the size.
+ * 
+ * @param h Mesh handle.
+ * 
+ * @return The size of the first ready message in the queue,
+ *         0 if there is none.
+ */
+static size_t
+message_ready_size (struct GNUNET_MESH_Handle *h)
+{
+  struct GNUNET_MESH_TransmitHandle *th;
+  struct GNUNET_MESH_Tunnel *t;
+
+  for (th = h->th_head; NULL != th; th = th->next)
+  {
+    t = th->tunnel;
+    if (GNUNET_NO == th_is_payload (th))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message internal\n");
+      return th->size;
+    }
+    if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message payload ok (%u =< %u)\n",
+           t->last_pid_sent + 1, t->last_ack_recv);
+      return th->size;
+    }
+  }
+  return 0;
+}
+
+
+/**
+ * Get the tunnel handler for the tunnel specified by id from the given handle
+ * @param h Mesh handle
+ * @param tid ID of the wanted tunnel
+ * @return handle to the required tunnel or NULL if not found
+ */
+static struct GNUNET_MESH_Tunnel *
+retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
+{
+  struct GNUNET_MESH_Tunnel *t;
+
+  t = h->tunnels_head;
+  while (t != NULL)
+  {
+    if (t->tid == tid)
+      return t;
+    t = t->next;
+  }
+  return NULL;
+}
+
+
+/**
+ * Create a new tunnel and insert it in the tunnel list of the mesh handle
+ * @param h Mesh handle
+ * @param tid desired tid of the tunnel, 0 to assign one automatically
+ * @return handle to the created tunnel
+ */
+static struct GNUNET_MESH_Tunnel *
+create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
+{
+  struct GNUNET_MESH_Tunnel *t;
+
+  t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
+  GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
+  t->mesh = h;
+  if (0 == tid)
+  {
+    t->tid = h->next_tid;
+    while (NULL != retrieve_tunnel (h, h->next_tid))
+    {
+      h->next_tid++;
+      h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
+      h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
+    }
+  }
+  else
+  {
+    t->tid = tid;
+  }
+  t->last_ack_recv = (uint32_t) -1;
+  t->last_pid_recv = (uint32_t) -1;
+  t->last_ack_sent = (uint32_t) -1;
+  t->last_pid_sent = (uint32_t) -1;
+  t->buffering = GNUNET_YES;
+  return t;
+}
+
+
+/**
+ * Destroy the specified tunnel.
+ * - Destroys all peers, calling the disconnect callback on each if needed
+ * - Cancels all outgoing traffic for that tunnel, calling respective notifys
+ * - Calls cleaner if tunnel was inbound
+ * - Frees all memory used
+ *
+ * @param t Pointer to the tunnel.
+ * @param call_cleaner Whether to call the cleaner handler.
+ *
+ * @return Handle to the required tunnel or NULL if not found.
+ */
+static void
+destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
+{
+  struct GNUNET_MESH_Handle *h;
+  struct GNUNET_MESH_TransmitHandle *th;
+  struct GNUNET_MESH_TransmitHandle *next;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
+
+  if (NULL == t)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  h = t->mesh;
+
+  GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
+
+  /* signal tunnel destruction */
+  if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) )
+    h->cleaner (h->cls, t, t->ctx);
+
+  /* check that clients did not leave messages behind in the queue */
+  for (th = h->th_head; NULL != th; th = next)
+  {
+    next = th->next;
+    if (th->tunnel != t)
+      continue;
+    /* Clients should have aborted their requests already.
+     * Management traffic should be ok, as clients can't cancel that */
+    GNUNET_break (GNUNET_NO == th_is_payload(th));
+    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
+
+    /* clean up request */
+    if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
+      GNUNET_SCHEDULER_cancel (th->timeout_task);
+    GNUNET_free (th);    
+  }
+
+  /* if there are no more pending requests with mesh service, cancel active 
request */
+  /* Note: this should be unnecessary... */
+  if ((0 == message_ready_size (h)) && (NULL != h->th))
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+  }
+
+  if (0 != t->peer)
+    GNUNET_PEER_change_rc (t->peer, -1);
+  GNUNET_free (t);
+  return;
+}
+
+
+/**
+ * Notify client that the transmission has timed out
+ * 
+ * @param cls closure
+ * @param tc task context
+ */
+static void
+timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_MESH_TransmitHandle *th = cls;
+  struct GNUNET_MESH_Handle *mesh;
+
+  mesh = th->tunnel->mesh;
+  GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
+  th->tunnel->packet_size = 0;
+  if (GNUNET_YES == th_is_payload (th))
+    th->notify (th->notify_cls, 0, NULL);
+  GNUNET_free (th);
+  if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
+  {
+    /* nothing ready to transmit, no point in asking for transmission */
+    GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
+    mesh->th = NULL;
+  }
+}
+
+
+/**
+ * Add a transmit handle to the transmission queue and set the
+ * timeout if needed.
+ *
+ * @param h mesh handle with the queue head and tail
+ * @param th handle to the packet to be transmitted
+ */
+static void
+add_to_queue (struct GNUNET_MESH_Handle *h,
+              struct GNUNET_MESH_TransmitHandle *th)
+{
+  GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
+  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
+    return;
+  th->timeout_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                    (th->timeout), &timeout_transmission, th);
+}
+
+
+/**
+ * Auxiliary function to send an already constructed packet to the service.
+ * Takes care of creating a new queue element, copying the message and
+ * calling the tmt_rdy function if necessary.
+ *
+ * @param h mesh handle
+ * @param msg message to transmit
+ * @param tunnel tunnel this send is related to (NULL if N/A)
+ */
+static void
+send_packet (struct GNUNET_MESH_Handle *h,
+             const struct GNUNET_MessageHeader *msg,
+             struct GNUNET_MESH_Tunnel *tunnel);
+
+
+/**
+ * Send an ack on the tunnel to confirm the processing of a message.
+ * 
+ * @param h Mesh handle.
+ * @param t Tunnel on which to send the ACK.
+ */
+static void
+send_ack (struct GNUNET_MESH_Tunnel *t)
+{
+  struct GNUNET_MESH_LocalAck msg;
+
+  t->last_ack_sent = t->last_pid_recv + 1;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending ACK on tunnel %X: %u\n",
+       t->tid, t->last_ack_sent);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
+  msg.header.size = htons (sizeof (msg));
+  msg.tunnel_id = htonl (t->tid);
+  msg.ack = htonl (t->last_ack_sent);
+
+#if DEBUG_ACK
+  t->mesh->acks_sent++;
+#endif
+
+  send_packet (t->mesh, &msg.header, t);
+  return;
+}
+
+
+
+/**
+ * Reconnect callback: tries to reconnect again after a failer previous
+ * reconnecttion
+ * @param cls closure (mesh handle)
+ * @param tc task context
+ */
+static void
+reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Send a connect packet to the service with the applications and types
+ * requested by the user.
+ *
+ * @param h The mesh handle.
+ *
+ */
+static void
+send_connect (struct GNUNET_MESH_Handle *h)
+{
+  size_t size;
+
+  size = sizeof (struct GNUNET_MESH_ClientConnect);
+  size += h->n_ports * sizeof (uint32_t);
+  {
+    char buf[size] GNUNET_ALIGN;
+    struct GNUNET_MESH_ClientConnect *msg;
+    uint32_t *ports;
+    uint16_t i;
+
+    /* build connection packet */
+    msg = (struct GNUNET_MESH_ClientConnect *) buf;
+    msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
+    msg->header.size = htons (size);
+    ports = (uint32_t *) &msg[1];
+    for (i = 0; i < h->n_ports; i++)
+    {
+      ports[i] = htonl (h->ports[i]);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
+           h->ports[i]);
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Sending %lu bytes long message with %u ports\n",
+         ntohs (msg->header.size), h->n_ports);
+    send_packet (h, &msg->header, NULL);
+  }
+}
+
+
+/**
+ * Reconnect to the service, retransmit all infomation to try to restore the
+ * original state.
+ *
+ * @param h handle to the mesh
+ *
+ * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
+ */
+static int
+do_reconnect (struct GNUNET_MESH_Handle *h)
+{
+  struct GNUNET_MESH_Tunnel *t;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
+
+  /* disconnect */
+  if (NULL != h->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+  }
+  if (NULL != h->client)
+  {
+    GNUNET_CLIENT_disconnect (h->client);
+  }
+
+  /* connect again */
+  h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
+  if (h->client == NULL)
+  {
+    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
+                                                      &reconnect_cbk, h);
+    h->reconnect_time =
+        GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
+                                  GNUNET_TIME_relative_multiply
+                                  (h->reconnect_time, 2));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, 
+        "Next retry in %s\n",
+         GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
+                                                GNUNET_NO));
+    GNUNET_break (0);
+    return GNUNET_NO;
+  }
+  else
+  {
+    h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
+  }
+  send_connect (h);
+  /* Rebuild all tunnels */
+  for (t = h->tunnels_head; NULL != t; t = t->next)
+  {
+    struct GNUNET_MESH_TunnelMessage tmsg;
+
+    if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+    {
+      /* Tunnel was created by service (incoming tunnel) */
+      /* TODO: Notify service of missing tunnel, to request
+       * creator to recreate path (find a path to him via DHT?)
+       */
+      continue;
+    }
+    t->last_ack_sent = (uint32_t) -1;
+    t->last_pid_sent = (uint32_t) -1;
+    t->last_ack_recv = (uint32_t) -1;
+    t->last_pid_recv = (uint32_t) -1;
+    tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
+    tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
+    tmsg.tunnel_id = htonl (t->tid);
+    GNUNET_PEER_resolve (t->peer, &tmsg.peer);
+    send_packet (h, &tmsg.header, t);
+
+    if (GNUNET_NO == t->buffering)
+      GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
+  }
+  return GNUNET_YES;
+}
+
+/**
+ * Reconnect callback: tries to reconnect again after a failer previous
+ * reconnecttion
+ * @param cls closure (mesh handle)
+ * @param tc task context
+ */
+static void
+reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_MESH_Handle *h = cls;
+
+  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  do_reconnect (h);
+}
+
+
+/**
+ * Reconnect to the service, retransmit all infomation to try to restore the
+ * original state.
+ *
+ * @param h handle to the mesh
+ *
+ * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
+ */
+static void
+reconnect (struct GNUNET_MESH_Handle *h)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
+  h->in_receive = GNUNET_NO;
+  if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
+    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
+                                                      &reconnect_cbk, h);
+}
+
+
+/******************************************************************************/
+/***********************      RECEIVE HANDLERS     
****************************/
+/******************************************************************************/
+
+/**
+ * Process the new tunnel notification and add it to the tunnels in the handle
+ *
+ * @param h     The mesh handle
+ * @param msg   A message with the details of the new incoming tunnel
+ */
+static void
+process_tunnel_created (struct GNUNET_MESH_Handle *h,
+                        const struct GNUNET_MESH_TunnelNotification *msg)
+{
+  struct GNUNET_MESH_Tunnel *t;
+  MESH_TunnelNumber tid;
+
+  tid = ntohl (msg->tunnel_id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
+  if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  if (NULL != h->new_tunnel)
+  {
+    t = create_tunnel (h, tid);
+    t->last_ack_sent = 0;
+    t->peer = GNUNET_PEER_intern (&msg->peer);
+    t->mesh = h;
+    t->tid = tid;
+    t->port = ntohl (msg->port);
+    if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER))
+      t->buffering = GNUNET_NO;
+    else
+      t->buffering = GNUNET_YES;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
+    t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
+  }
+  else
+  {
+    struct GNUNET_MESH_TunnelMessage d_msg;
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
+
+    d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
+    d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
+    d_msg.tunnel_id = msg->tunnel_id;
+
+    send_packet (h, &d_msg.header, NULL);
+  }
+  return;
+}
+
+
+/**
+ * Process the tunnel destroy notification and free associated resources
+ *
+ * @param h     The mesh handle
+ * @param msg   A message with the details of the tunnel being destroyed
+ */
+static void
+process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
+                        const struct GNUNET_MESH_TunnelMessage *msg)
+{
+  struct GNUNET_MESH_Tunnel *t;
+  MESH_TunnelNumber tid;
+
+  tid = ntohl (msg->tunnel_id);
+  t = retrieve_tunnel (h, tid);
+
+  if (NULL == t)
+  {
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
+  destroy_tunnel (t, GNUNET_YES);
+  return;
+}
+
+
+/**
+ * Process the incoming data packets, call appropriate handlers.
+ *
+ * @param h         The mesh handle
+ * @param message   A message encapsulating the data
+ */
+static void
+process_incoming_data (struct GNUNET_MESH_Handle *h,
+                       const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_MessageHeader *payload;
+  const struct GNUNET_MESH_MessageHandler *handler;
+  const struct GNUNET_PeerIdentity *peer;
+  struct GNUNET_PeerIdentity id;
+  struct GNUNET_MESH_Data *dmsg;
+  struct GNUNET_MESH_Tunnel *t;
+  unsigned int i;
+  uint32_t pid;
+  uint16_t type;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
+  type = ntohs (message->type);
+  switch (type)
+  {
+  case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+  case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+    dmsg = (struct GNUNET_MESH_Data *) message;
+
+    t = retrieve_tunnel (h, ntohl (dmsg->tid));
+    payload = (struct GNUNET_MessageHeader *) &dmsg[1];
+    GNUNET_PEER_resolve (t->peer, &id);
+    peer = &id;
+    pid = ntohl (dmsg->pid);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s data on tunnel %s [%X]\n",
+         type == GNUNET_MESSAGE_TYPE_MESH_UNICAST ? "fwd" : "bck",
+         GNUNET_i2s (peer), ntohl (dmsg->tid));
+    break;
+  default:
+    GNUNET_break (0);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
+  if (NULL == t)
+  {
+    /* Tunnel was ignored/destroyed, probably service didn't get it yet */
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
+    return;
+  }
+  if (GNUNET_YES ==
+      GMC_is_pid_bigger(pid, t->last_ack_sent))
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "  unauthorized message! (%u, ACK %u)\n",
+         pid, t->last_ack_sent);
+    // FIXME fc what now? accept? reject?
+    return;
+  }
+  t->last_pid_recv = pid;
+  type = ntohs (payload->type);
+  for (i = 0; i < h->n_handlers; i++)
+  {
+    handler = &h->message_handlers[i];
+    if (handler->type == type)
+    {
+      if (GNUNET_OK !=
+          handler->callback (h->cls, t, &t->ctx, payload))
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
+        GNUNET_MESH_tunnel_destroy (t);
+        return;
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "callback completed successfully\n");
+      }
+    }
+  }
+}
+
+
+/**
+ * Process a local ACK message, enabling the client to send
+ * more data to the service.
+ * 
+ * @param h Mesh handle.
+ * @param message Message itself.
+ */
+static void
+process_ack (struct GNUNET_MESH_Handle *h,
+             const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_LocalAck *msg;
+  struct GNUNET_MESH_Tunnel *t;
+  uint32_t ack;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
+  h->acks_recv++;
+  msg = (struct GNUNET_MESH_LocalAck *) message;
+
+  t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
+
+  if (NULL == t)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "ACK on unknown tunnel %X\n",
+         ntohl (msg->tunnel_id));
+    return;
+  }
+  ack = ntohl (msg->ack);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
+  if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv))
+    t->last_ack_recv = ack;
+  else
+    return;
+  if (NULL == h->th && 0 < t->packet_size)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, 
ack);
+    h->th =
+        GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
+                                             GNUNET_TIME_UNIT_FOREVER_REL,
+                                             GNUNET_YES, &send_callback, h);
+  }
+}
+
+
+/**
+ * Process a local reply about info on all tunnels, pass info to the user.
+ *
+ * @param h Mesh handle.
+ * @param message Message itself.
+ */
+static void
+process_get_tunnels (struct GNUNET_MESH_Handle *h,
+                     const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_LocalMonitor *msg;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
+
+  if (NULL == h->tunnels_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
+    return;
+  }
+
+  msg = (struct GNUNET_MESH_LocalMonitor *) message;
+  if (ntohs (message->size) !=
+      (sizeof (struct GNUNET_MESH_LocalMonitor) +
+       sizeof (struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Get tunnels message: size %hu - expected %u\n",
+                ntohs (message->size),
+                sizeof (struct GNUNET_MESH_LocalMonitor));
+    return;
+  }
+  h->tunnels_cb (h->tunnels_cls,
+                 ntohl (msg->tunnel_id),
+                 &msg->owner,
+                 &msg->destination);
+}
+
+
+
+/**
+ * Process a local monitor_tunnel reply, pass info to the user.
+ *
+ * @param h Mesh handle.
+ * @param message Message itself.
+ */
+static void
+process_show_tunnel (struct GNUNET_MESH_Handle *h,
+                     const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_MESH_LocalMonitor *msg;
+  size_t esize;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
+
+  if (NULL == h->tunnel_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
+    return;
+  }
+
+  /* Verify message sanity */
+  msg = (struct GNUNET_MESH_LocalMonitor *) message;
+  esize = sizeof (struct GNUNET_MESH_LocalMonitor);
+  if (ntohs (message->size) != esize)
+  {
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Show tunnel message: size %hu - expected %u\n",
+                ntohs (message->size),
+                esize);
+
+    h->tunnel_cb (h->tunnel_cls, NULL, NULL);
+    h->tunnel_cb = NULL;
+    h->tunnel_cls = NULL;
+
+    return;
+  }
+
+  h->tunnel_cb (h->tunnel_cls,
+                &msg->destination,
+                &msg->owner);
+}
+
+
+/**
+ * Function to process all messages received from the service
+ *
+ * @param cls closure
+ * @param msg message received, NULL on timeout or fatal error
+ */
+static void
+msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_MESH_Handle *h = cls;
+
+  if (msg == NULL)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, 
+        "Mesh service disconnected, reconnecting\n", h);
+    reconnect (h);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
+       GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
+       GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
+  switch (ntohs (msg->type))
+  {
+    /* Notify of a new incoming tunnel */
+  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
+    process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
+    break;
+    /* Notify of a tunnel disconnection */
+  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
+    process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
+    break;
+    /* Notify of a new data packet in the tunnel */
+  case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+  case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
+  case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+    process_incoming_data (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
+    process_ack (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
+        process_get_tunnels (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
+        process_show_tunnel (h, msg);
+    break;
+  default:
+    /* We shouldn't get any other packages, log and ignore */
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "unsolicited message form service (type %s)\n",
+         GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
+  if (GNUNET_YES == h->in_receive)
+  {
+    GNUNET_CLIENT_receive (h->client, &msg_received, h,
+                           GNUNET_TIME_UNIT_FOREVER_REL);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "in receive off, not calling CLIENT_receive\n");
+  }
+}
+
+
+/******************************************************************************/
+/************************       SEND FUNCTIONS     
****************************/
+/******************************************************************************/
+
+/**
+ * Function called to send a message to the service.
+ * "buf" will be NULL and "size" zero if the socket was closed for writing in
+ * the meantime.
+ *
+ * @param cls closure, the mesh handle
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the connect message
+ * @return number of bytes written to buf
+ */
+static size_t
+send_callback (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MESH_Handle *h = cls;
+  struct GNUNET_MESH_TransmitHandle *th;
+  struct GNUNET_MESH_TransmitHandle *next;
+  struct GNUNET_MESH_Tunnel *t;
+  char *cbuf = buf;
+  size_t tsize;
+  size_t psize;
+  size_t nsize;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
+  if ((0 == size) || (NULL == buf))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
+    reconnect (h);
+    h->th = NULL;
+    return 0;
+  }
+  tsize = 0;
+  next = h->th_head;
+  nsize = message_ready_size (h);
+  while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
+  {
+    t = th->tunnel;
+    if (GNUNET_YES == th_is_payload (th))
+    {
+      struct GNUNET_MESH_Data *dmsg;
+      struct GNUNET_MessageHeader *mh;
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload\n");
+      if (GNUNET_NO == GMC_is_pid_bigger (t->last_ack_recv, t->last_pid_sent))
+      {
+        /* This tunnel is not ready to transmit yet, try next message */
+        next = th->next;
+        continue;
+      }
+      t->packet_size = 0;
+      GNUNET_assert (size >= th->size);
+      dmsg = (struct GNUNET_MESH_Data *) cbuf;
+      mh = (struct GNUNET_MessageHeader *) &dmsg[1];
+      psize = th->notify (th->notify_cls,
+                          size - sizeof (struct GNUNET_MESH_Data),
+                          mh);
+      if (psize > 0)
+      {
+        psize += sizeof (struct GNUNET_MESH_Data);
+        GNUNET_assert (size >= psize);
+        dmsg->header.size = htons (psize);
+        dmsg->tid = htonl (t->tid);
+        dmsg->pid = htonl (t->last_pid_sent + 1);
+        dmsg->ttl = 0;
+        memset (&dmsg->oid, 0, sizeof (struct GNUNET_PeerIdentity));
+        t->last_pid_sent++;
+      }
+      if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+      {
+        dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "#  to origin, type %s\n",
+             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
+      }
+      else
+      {
+        dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "#  unicast, type %s\n",
+             GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
+      }
+    }
+    else
+    {
+      struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  mesh traffic, type %s\n",
+           GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
+      memcpy (cbuf, &th[1], th->size);
+      psize = th->size;
+    }
+    if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel (th->timeout_task);
+    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
+    GNUNET_free (th);
+    next = h->th_head;
+    nsize = message_ready_size (h);
+    cbuf += psize;
+    size -= psize;
+    tsize += psize;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "#  total size: %u\n", tsize);
+  h->th = NULL;
+  size = message_ready_size (h);
+  if (0 != size)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "#  next size: %u\n", size);
+    h->th =
+        GNUNET_CLIENT_notify_transmit_ready (h->client, size,
+                                             GNUNET_TIME_UNIT_FOREVER_REL,
+                                             GNUNET_YES, &send_callback, h);
+  }
+  else
+  {
+    if (NULL != h->th_head)
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  can't transmit any more\n");
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  nothing left to transmit\n");
+  }
+  if (GNUNET_NO == h->in_receive)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
+    h->in_receive = GNUNET_YES;
+    GNUNET_CLIENT_receive (h->client, &msg_received, h,
+                           GNUNET_TIME_UNIT_FOREVER_REL);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
+  return tsize;
+}
+
+
+/**
+ * Auxiliary function to send an already constructed packet to the service.
+ * Takes care of creating a new queue element, copying the message and
+ * calling the tmt_rdy function if necessary.
+ * 
+ * @param h mesh handle
+ * @param msg message to transmit
+ * @param tunnel tunnel this send is related to (NULL if N/A)
+ */
+static void
+send_packet (struct GNUNET_MESH_Handle *h,
+             const struct GNUNET_MessageHeader *msg,
+             struct GNUNET_MESH_Tunnel *tunnel)
+{
+  struct GNUNET_MESH_TransmitHandle *th;
+  size_t msize;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
+       GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
+  msize = ntohs (msg->size);
+  th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
+  th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
+  th->size = msize;
+  th->tunnel = tunnel;
+  memcpy (&th[1], msg, msize);
+  add_to_queue (h, th);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
+  if (NULL != h->th)
+    return;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", 
msize);
+  h->th =
+      GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_YES, &send_callback, h);
+}
+
+
+/******************************************************************************/
+/**********************      API CALL DEFINITIONS     
*************************/
+/******************************************************************************/
+
+struct GNUNET_MESH_Handle *
+GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
+                     GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
+                     GNUNET_MESH_TunnelEndHandler cleaner,
+                     const struct GNUNET_MESH_MessageHandler *handlers,
+                     const uint32_t *ports)
+{
+  struct GNUNET_MESH_Handle *h;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
+  h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
+  h->cfg = cfg;
+  h->new_tunnel = new_tunnel;
+  h->cleaner = cleaner;
+  h->client = GNUNET_CLIENT_connect ("mesh", cfg);
+  if (h->client == NULL)
+  {
+    GNUNET_break (0);
+    GNUNET_free (h);
+    return NULL;
+  }
+  h->cls = cls;
+  h->message_handlers = handlers;
+  h->ports = ports;
+  h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
+  h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
+  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+
+  /* count handlers */
+  for (h->n_handlers = 0;
+       handlers && handlers[h->n_handlers].type;
+       h->n_handlers++) ;
+  for (h->n_ports = 0;
+       ports && ports[h->n_ports];
+       h->n_ports++) ;
+  send_connect (h);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
+  return h;
+}
+
+
+void
+GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
+{
+  struct GNUNET_MESH_Tunnel *t;
+  struct GNUNET_MESH_Tunnel *aux;
+  struct GNUNET_MESH_TransmitHandle *th;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
+
+#if DEBUG_ACK
+  LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
+  LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
+#endif
+
+  t = handle->tunnels_head;
+  while (NULL != t)
+  {
+    aux = t->next;
+    if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+    {
+      GNUNET_break (0);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
+    }
+    destroy_tunnel (t, GNUNET_YES);
+    t = aux;
+  }
+  while ( (th = handle->th_head) != NULL)
+  {
+    struct GNUNET_MessageHeader *msg;
+
+    /* Make sure it is an allowed packet (everything else should have been
+     * already canceled).
+     */
+    GNUNET_break (GNUNET_NO == th_is_payload (th));
+    msg = (struct GNUNET_MessageHeader *) &th[1];
+    switch (ntohs(msg->type))
+    {
+      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
+      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
+      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
+      case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
+        break;
+      default:
+        GNUNET_break (0);
+        LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
+             ntohs(msg->type));
+    }
+
+    GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
+    GNUNET_free (th);
+  }
+
+  if (NULL != handle->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
+    handle->th = NULL;
+  }
+  if (NULL != handle->client)
+  {
+    GNUNET_CLIENT_disconnect (handle->client);
+    handle->client = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel(handle->reconnect_task);
+    handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_free (handle);
+}
+
+
+struct GNUNET_MESH_Tunnel *
+GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, 
+                           void *tunnel_ctx,
+                           const struct GNUNET_PeerIdentity *peer,
+                           uint32_t port)
+{
+  struct GNUNET_MESH_Tunnel *t;
+  struct GNUNET_MESH_TunnelMessage msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
+  t = create_tunnel (h, 0);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
+  t->ctx = tunnel_ctx;
+  t->peer = GNUNET_PEER_intern (peer);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
+  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
+  msg.tunnel_id = htonl (t->tid);
+  msg.port = htonl (port);
+  msg.peer = *peer;
+  t->last_ack_sent = 0;
+  send_packet (h, &msg.header, t);
+  return t;
+}
+
+
+void
+GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
+{
+  struct GNUNET_MESH_Handle *h;
+  struct GNUNET_MESH_TunnelMessage msg;
+  struct GNUNET_MESH_TransmitHandle *th;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
+  h = tunnel->mesh;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
+  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
+  msg.tunnel_id = htonl (tunnel->tid);
+  th = h->th_head;
+  while (th != NULL)
+  {
+    struct GNUNET_MESH_TransmitHandle *aux;
+    if (th->tunnel == tunnel)
+    {
+      aux = th->next;
+      /* FIXME call the handler? */
+      if (GNUNET_YES == th_is_payload (th))
+        th->notify (th->notify_cls, 0, NULL);
+      GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
+      GNUNET_free (th);
+      th = aux;
+    }
+    else
+      th = th->next;
+  }
+
+  destroy_tunnel (tunnel, GNUNET_YES);
+  send_packet (h, &msg.header, NULL);
+}
+
+
+void
+GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
+{
+  struct GNUNET_MESH_TunnelMessage msg;
+  struct GNUNET_MESH_Handle *h;
+
+  h = tunnel->mesh;
+  tunnel->buffering = buffer;
+
+  if (GNUNET_YES == buffer)
+    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
+  else
+    msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
+  msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
+  msg.tunnel_id = htonl (tunnel->tid);
+
+  send_packet (h, &msg.header, NULL);
+}
+
+
+struct GNUNET_MESH_TransmitHandle *
+GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
+                                   struct GNUNET_TIME_Relative maxdelay,
+                                   size_t notify_size,
+                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
+                                   void *notify_cls)
+{
+  struct GNUNET_MESH_TransmitHandle *th;
+
+  GNUNET_assert (NULL != tunnel);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
+  if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
+  GNUNET_assert (NULL != notify);
+  GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
+  th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
+  th->tunnel = tunnel;
+  th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
+  th->size = notify_size + sizeof (struct GNUNET_MESH_Data);
+  tunnel->packet_size = th->size;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
+  th->notify = notify;
+  th->notify_cls = notify_cls;
+  add_to_queue (tunnel->mesh, th);
+  if (NULL != tunnel->mesh->th)
+    return th;
+  if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent))
+    return th;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    call client notify tmt rdy\n");
+  tunnel->mesh->th =
+      GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_YES, &send_callback,
+                                           tunnel->mesh);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
+  return th;
+}
+
+
+void
+GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle 
*th)
+{
+  struct GNUNET_MESH_Handle *mesh;
+
+  th->tunnel->packet_size = 0;
+  mesh = th->tunnel->mesh;
+  if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (th->timeout_task);
+  GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
+  GNUNET_free (th);
+  if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
+  {
+    /* queue empty, no point in asking for transmission */
+    GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
+    mesh->th = NULL;
+  }
+}
+
+void
+GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel)
+{
+  send_ack (tunnel);
+}
+
+
+/**
+ * Request information about the running mesh peer.
+ * The callback will be called for every tunnel known to the service,
+ * listing all active peers that blong to the tunnel.
+ *
+ * If called again on the same handle, it will overwrite the previous
+ * callback and cls. To retrieve the cls, monitor_cancel must be
+ * called first.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the mesh peer.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ */
+void
+GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
+                         GNUNET_MESH_TunnelsCB callback,
+                         void *callback_cls)
+{
+  struct GNUNET_MessageHeader msg;
+
+  msg.size = htons (sizeof (msg));
+  msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
+  send_packet (h, &msg, NULL);
+  h->tunnels_cb = callback;
+  h->tunnels_cls = callback_cls;
+
+  return;
+}
+
+
+/**
+ * Cancel a monitor request. The monitor callback will not be called.
+ *
+ * @param h Mesh handle.
+ *
+ * @return Closure given to GNUNET_MESH_monitor, if any.
+ */
+void *
+GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
+{
+  void *cls;
+
+  cls = h->tunnels_cls;
+  h->tunnels_cb = NULL;
+  h->tunnels_cls = NULL;
+  return cls;
+}
+
+
+/**
+ * Request information about a specific tunnel of the running mesh peer.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ * FIXME Add destination option.
+ *
+ * @param h Handle to the mesh peer.
+ * @param initiator ID of the owner of the tunnel.
+ * @param tunnel_number Tunnel number.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ */
+void
+GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
+                         struct GNUNET_PeerIdentity *initiator,
+                         unsigned int tunnel_number,
+                         GNUNET_MESH_TunnelCB callback,
+                         void *callback_cls)
+{
+  struct GNUNET_MESH_LocalMonitor msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
+  msg.owner = *initiator;
+  msg.tunnel_id = htonl (tunnel_number);
+  msg.reserved = 0;
+  send_packet (h, &msg.header, NULL);
+  h->tunnel_cb = callback;
+  h->tunnel_cls = callback_cls;
+
+  return;
+}
+
+
+/**
+ * Function called to notify a client about the connection
+ * begin ready to queue more data.  "buf" will be
+ * NULL and "size" zero if the connection was closed for
+ * writing in the meantime.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+mesh_mq_ntr (void *cls, size_t size,
+             void *buf)
+{
+  struct GNUNET_MQ_Handle *mq = cls; 
+  struct MeshMQState *state = GNUNET_MQ_impl_state (mq);
+  const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
+  uint16_t msize;
+
+  state->th = NULL;
+  if (NULL == buf)
+  {
+    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
+    return 0;
+  }
+  msize = ntohs (msg->size);
+  GNUNET_assert (msize <= size);
+  memcpy (buf, msg, msize);
+  GNUNET_MQ_impl_send_continue (mq);
+  return msize;
+}
+
+
+/**
+ * Signature of functions implementing the
+ * sending functionality of a message queue.
+ *
+ * @param mq the message queue
+ * @param msg the message to send
+ * @param impl_state state of the implementation
+ */
+static void
+mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq,
+                   const struct GNUNET_MessageHeader *msg, void *impl_state)
+{
+  struct MeshMQState *state = impl_state;
+
+  GNUNET_assert (NULL == state->th);
+  GNUNET_MQ_impl_send_commit (mq);
+  state->th =
+      GNUNET_MESH_notify_transmit_ready (state->tunnel,
+                                         /* FIXME: add option for corking */
+                                         GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL, 
+                                         ntohs (msg->size),
+                                         mesh_mq_ntr, mq);
+
+}
+
+
+/**
+ * Signature of functions implementing the
+ * destruction of a message queue.
+ * Implementations must not free 'mq', but should
+ * take care of 'impl_state'.
+ * 
+ * @param mq the message queue to destroy
+ * @param impl_state state of the implementation
+ */
+static void
+mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
+{
+  struct MeshMQState *state = impl_state;
+
+  if (NULL != state->th)
+    GNUNET_MESH_notify_transmit_ready_cancel (state->th);
+
+  GNUNET_free (state);
+}
+
+
+/**
+ * Create a message queue for a mesh tunnel.
+ * The message queue can only be used to transmit messages,
+ * not to receive them.
+ *
+ * @param tunnel the tunnel to create the message qeue for
+ * @return a message queue to messages over the tunnel
+ */
+struct GNUNET_MQ_Handle *
+GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel)
+{
+  struct GNUNET_MQ_Handle *mq;
+  struct MeshMQState *state;
+
+  state = GNUNET_new (struct MeshMQState);
+  state->tunnel = tunnel;
+
+  mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl,
+                                      mesh_mq_destroy_impl,
+                                      NULL, /* FIXME: cancel impl. */
+                                      state,
+                                      NULL, /* no msg handlers */
+                                      NULL, /* no err handlers */
+                                      NULL); /* no handler cls */
+  return mq;
+}
+

Modified: gnunet/src/mesh/mesh_path.c
===================================================================
--- gnunet/src/mesh/mesh_path.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh_path.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -24,7 +24,7 @@
  * @author Bartlomiej Polot
  */
 
-#include "mesh2.h"
+#include "mesh.h"
 #include "mesh_path.h"
 
 

Modified: gnunet/src/mesh/mesh_path.h
===================================================================
--- gnunet/src/mesh/mesh_path.h 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh_path.h 2013-06-28 14:34:55 UTC (rev 27681)
@@ -35,7 +35,7 @@
 #endif
 #endif
 
-#include "mesh2.h"
+#include "mesh.h"
 
 
/******************************************************************************/
 /************************      DATA STRUCTURES     
****************************/

Deleted: gnunet/src/mesh/mesh_protocol.h
===================================================================
--- gnunet/src/mesh/mesh_protocol.h     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh_protocol.h     2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,376 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @author Bartlomiej Polot
- * @file mesh/mesh_protocol.h
- */
-
-#ifndef MESH_PROTOCOL_H_
-#define MESH_PROTOCOL_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0
-  /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#define MESH_TUNNEL_OPT_SPEED_MIN       0x1
-#define MESH_TUNNEL_OPT_NOBUFFER        0x2
-
-
-/******************************************************************************/
-/********************      MESH NETWORK MESSAGES     
**************************/
-/******************************************************************************/
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Message for mesh path management
- */
-struct GNUNET_MESH_ManipulatePath
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_[CREATE|CHANGE|ADD|DESTROY]
-     *
-     * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
-     *       path_length * sizeof (struct GNUNET_PeerIdentity)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * Global id of the tunnel this path belongs to,
-     * unique in conjunction with the origin.
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * Tunnel options (MESH_TUNNEL_OPT_*).
-     */
-  uint32_t opt GNUNET_PACKED;
-
-    /**
-     * 64 bit alignment padding.
-     */
-  uint32_t reserved GNUNET_PACKED;
-
-    /**
-     * path_length structs defining the *whole* path from the origin [0] to the
-     * final destination [path_length-1].
-     */
-  /* struct GNUNET_PeerIdentity peers[path_length]; */
-};
-
-/**
- * Message for mesh data traffic to all tunnel targets.
- */
-struct GNUNET_MESH_Multicast
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_MULTICAST
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * Number of hops to live
-     */
-  uint32_t ttl GNUNET_PACKED;
-
-    /**
-     * Unique ID of the packet
-     */
-  uint32_t pid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * Payload follows
-     */
-};
-
-
-/**
- * Message for mesh data traffic to a particular destination from origin.
- */
-struct GNUNET_MESH_Unicast
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * Number of hops to live
-     */
-  uint32_t ttl GNUNET_PACKED;
-
-    /**
-     * Unique ID of the packet
-     */
-  uint32_t pid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * Destination.
-     */
-  struct GNUNET_PeerIdentity destination;
-
-    /**
-     * Payload follows
-     */
-};
-
-
-/**
- * Message for mesh data traffic from a tunnel participant to origin.
- */
-struct GNUNET_MESH_ToOrigin
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * Number of hops to live
-     */
-  uint32_t ttl GNUNET_PACKED;
-
-    /**
-     * Unique ID of the packet
-     */
-  uint32_t pid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * Sender of the message.
-     */
-  struct GNUNET_PeerIdentity sender;
-
-    /**
-     * Payload follows
-     */
-};
-
-
-/**
- * Message to acknowledge mesh data traffic.
- */
-struct GNUNET_MESH_ACK
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * Maximum packet ID authorized.
-     */
-  uint32_t pid;
-
-};
-
-/**
- * Message to query a peer about its Flow Control status regarding a tunnel.
- */
-struct GNUNET_MESH_Poll
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_MESH_POLL
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * TID of the tunnel
-   */
-  uint32_t tid GNUNET_PACKED;
-
-  /**
-   * OID of the tunnel
-   */
-  struct GNUNET_PeerIdentity oid;
-
-  /**
-   * Last ACK received.
-   */
-  uint32_t last_ack;
-};
-
-/**
- * Message for ack'ing a path
- */
-struct GNUNET_MESH_PathACK
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer_id;
-
-  /* TODO: signature */
-};
-
-
-/**
- * Message for notifying a disconnection in a path
- */
-struct GNUNET_MESH_PathBroken
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer1;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer2;
-
-  /* TODO: signature */
-};
-
-
-/**
- * Message to destroy a tunnel
- */
-struct GNUNET_MESH_TunnelDestroy
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * TID of the tunnel
-     */
-  uint32_t tid GNUNET_PACKED;
-
-    /**
-     * OID of the tunnel
-     */
-  struct GNUNET_PeerIdentity oid;
-
-  /* TODO: signature */
-};
-
-
-/**
- * Message to destroy a tunnel
- */
-struct GNUNET_MESH_TunnelKeepAlive
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE
-   */
-  struct GNUNET_MessageHeader header;
-  
-  /**
-   * TID of the tunnel
-   */
-  uint32_t tid GNUNET_PACKED;
-  
-  /**
-   * OID of the tunnel
-   */
-  struct GNUNET_PeerIdentity oid;
-};
-
-
-
-GNUNET_NETWORK_STRUCT_END
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef MESH_PROTOCOL_H */
-#endif
-/* end of mesh_protocol.h */

Copied: gnunet/src/mesh/mesh_protocol.h (from rev 27670, 
gnunet/src/mesh/mesh2_protocol.h)
===================================================================
--- gnunet/src/mesh/mesh_protocol.h                             (rev 0)
+++ gnunet/src/mesh/mesh_protocol.h     2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,316 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @author Bartlomiej Polot
+ * @file mesh/mesh_protocol.h
+ */
+
+#ifndef MESH_PROTOCOL_H_
+#define MESH_PROTOCOL_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0
+  /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#define MESH_TUNNEL_OPT_NOBUFFER        0x2
+
+
+/******************************************************************************/
+/********************      MESH NETWORK MESSAGES     
**************************/
+/******************************************************************************/
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message for mesh path creation.
+ */
+struct GNUNET_MESH_CreateTunnel
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE
+     *
+     * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
+     *       path_length * sizeof (struct GNUNET_PeerIdentity)
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * Global id of the tunnel this path belongs to,
+     * unique in conjunction with the origin.
+     */
+  uint32_t tid GNUNET_PACKED;
+
+    /**
+     * Tunnel options (MESH_TUNNEL_OPT_*).
+     */
+  uint32_t opt GNUNET_PACKED;
+
+    /**
+     * Destination port.
+     */
+  uint32_t port GNUNET_PACKED;
+
+    /**
+     * FIXME do not add the first hop
+     * path_length structs defining the *whole* path from the origin [0] to the
+     * final destination [path_length-1].
+     */
+  /* struct GNUNET_PeerIdentity peers[path_length]; */
+};
+
+/**
+ * Message for mesh path destruction.
+ */
+struct GNUNET_MESH_DestroyTunnel
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY
+   *
+   * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
+   *       path_length * sizeof (struct GNUNET_PeerIdentity)
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * Global id of the tunnel this path belongs to,
+   * unique in conjunction with the origin.
+   */
+  uint32_t tid GNUNET_PACKED;
+};
+
+
+/**
+ * Message for mesh data traffic.
+ */
+struct GNUNET_MESH_Data
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST,
+     *       GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * TID of the tunnel
+     */
+  uint32_t tid GNUNET_PACKED;
+
+    /**
+     * Number of hops to live
+     */
+  uint32_t ttl GNUNET_PACKED;
+
+    /**
+     * Unique ID of the packet
+     */
+  uint32_t pid GNUNET_PACKED;
+
+    /**
+     * OID of the tunnel
+     */
+  struct GNUNET_PeerIdentity oid;
+
+    /**
+     * Payload follows
+     */
+};
+
+
+/**
+ * Message to acknowledge mesh data traffic.
+ */
+struct GNUNET_MESH_ACK
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_ACK
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * TID of the tunnel
+     */
+  uint32_t tid GNUNET_PACKED;
+
+    /**
+     * OID of the tunnel
+     */
+  struct GNUNET_PeerIdentity oid;
+
+    /**
+     * Maximum packet ID authorized.
+     */
+  uint32_t pid;
+
+};
+
+/**
+ * Message to query a peer about its Flow Control status regarding a tunnel.
+ */
+struct GNUNET_MESH_Poll
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_MESH_POLL
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * TID of the tunnel
+   */
+  uint32_t tid GNUNET_PACKED;
+
+  /**
+   * OID of the tunnel
+   */
+  struct GNUNET_PeerIdentity oid;
+};
+
+/**
+ * Message for ack'ing a path
+ */
+struct GNUNET_MESH_PathACK
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_ACK
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * TID of the tunnel
+     */
+  uint32_t tid GNUNET_PACKED;
+
+    /**
+     * OID of the tunnel
+     */
+  struct GNUNET_PeerIdentity oid;
+
+    /**
+     * ID of the endpoint
+     */
+  struct GNUNET_PeerIdentity peer_id;
+
+    /**
+     * Initial ACK value for payload.
+     */
+  uint32_t ack GNUNET_PACKED;
+
+  /* TODO: signature */
+};
+
+
+/**
+ * Message for notifying a disconnection in a path
+ */
+struct GNUNET_MESH_PathBroken
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * TID of the tunnel
+     */
+  uint32_t tid GNUNET_PACKED;
+
+    /**
+     * OID of the tunnel
+     */
+  struct GNUNET_PeerIdentity oid;
+
+    /**
+     * ID of the endpoint
+     */
+  struct GNUNET_PeerIdentity peer1;
+
+    /**
+     * ID of the endpoint
+     */
+  struct GNUNET_PeerIdentity peer2;
+
+  /* TODO: signature */
+};
+
+
+/**
+ * Message to destroy a tunnel
+ */
+struct GNUNET_MESH_TunnelDestroy
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * TID of the tunnel
+     */
+  uint32_t tid GNUNET_PACKED;
+
+    /**
+     * OID of the tunnel
+     */
+  struct GNUNET_PeerIdentity oid;
+
+  /* TODO: signature */
+};
+
+
+/**
+ * Message to destroy a tunnel
+ */
+struct GNUNET_MESH_TunnelKeepAlive
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * TID of the tunnel
+   */
+  uint32_t tid GNUNET_PACKED;
+  
+  /**
+   * OID of the tunnel
+   */
+  struct GNUNET_PeerIdentity oid;
+};
+
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef MESH_PROTOCOL_H */
+#endif
+/* end of mesh_protocol.h */

Deleted: gnunet/src/mesh/mesh_test_lib.c
===================================================================
--- gnunet/src/mesh/mesh_test_lib.c     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh_test_lib.c     2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,303 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/mesh_test_lib.c
- * @author Bartlomiej Polot
- * @brief library for writing MESH tests
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "mesh_test_lib.h"
-#include "gnunet_mesh_service.h"
-
-/**
- * Test context for a MESH Test.
- */
-struct GNUNET_MESH_TEST_Context
-{
-  /**
-   * Array of running peers.
-   */
-  struct GNUNET_TESTBED_Peer **peers;
-
-  /**
-   * Array of handles to the MESH for each peer.
-   */
-  struct GNUNET_MESH_Handle **meshes;
-
-  /**
-   * Operation associated with the connection to the MESH.
-   */
-  struct GNUNET_TESTBED_Operation **ops;
-
-  /**
-   * Main function of the test to run once all MESHs are available.
-   */
-  GNUNET_MESH_TEST_AppMain app_main;
-  
-  /**
-   * Closure for 'app_main'.
-   */
-  void *app_main_cls;
-
-  /**
-   * Number of peers running, size of the arrays above.
-   */
-  unsigned int num_peers;
-
-  /**
-   * Handler for incoming tunnels.
-   */
-  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
-
-  /**
-   * Cleaner for destroyed incoming tunnels.
-   */
-  GNUNET_MESH_TunnelEndHandler *cleaner;
-
-  /**
-   * Message handlers.
-   */
-  struct GNUNET_MESH_MessageHandler* handlers;
-
-  /**
-   * Application types.
-   */
-  const GNUNET_MESH_ApplicationType* stypes;
-
-};
-
-
-/**
- * Context for a mesh adapter callback.
- */
-struct GNUNET_MESH_TEST_AdapterContext
-{
-  /**
-   * Peer number for the particular peer.
-   */
-  unsigned int peer;
-
-  /**
-   * General context.
-   */
-  struct GNUNET_MESH_TEST_Context *ctx;
-};
-
-
-/**
- * Adapter function called to establish a connection to
- * the MESH service.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- *          GNUNET_TESTBED_operation_done() is called on the operation returned
- *          from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-mesh_connect_adapter (void *cls,
-                      const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
-  struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
-  struct GNUNET_MESH_Handle *h;
-
-  h = GNUNET_MESH_connect (cfg,
-                           (void *) (long) actx->peer,
-                           ctx->new_tunnel,
-                           ctx->cleaner,
-                           ctx->handlers,
-                           ctx->stypes);
-  return h;
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * the MESH service.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void 
-mesh_disconnect_adapter (void *cls,
-                         void *op_result)
-{
-  struct GNUNET_MESH_Handle *mesh = op_result;
-  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
-
-  GNUNET_free (actx);
-  GNUNET_MESH_disconnect (mesh);
-}
-
-
-/**
- * Callback to be called when a service connect operation is completed.
- *
- * @param cls The callback closure from functions generating an operation.
- * @param op The operation that has been finished.
- * @param ca_result The service handle returned from 
- *                  GNUNET_TESTBED_ConnectAdapter() (mesh handle).
- * @param emsg Error message in case the operation has failed.
- *             NULL if operation has executed successfully.
- */
-static void 
-mesh_connect_cb (void *cls,
-                 struct GNUNET_TESTBED_Operation *op,
-                 void *ca_result,
-                 const char *emsg)
-{
-  struct GNUNET_MESH_TEST_Context *ctx = cls;
-  unsigned int i;
- 
-  if (NULL != emsg)
-  {
-    fprintf (stderr, "Failed to connect to MESH service: %s\n",
-             emsg);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  for (i = 0; i < ctx->num_peers; i++)
-    if (op == ctx->ops[i])
-      ctx->meshes[i] = ca_result;
-  for (i = 0; i < ctx->num_peers; i++)
-    if (NULL == ctx->meshes[i])
-      return; /* still some MESH connections missing */
-  /* all MESH connections ready! */
-  ctx->app_main (ctx->app_main_cls,
-                 ctx,
-                 ctx->num_peers,
-                 ctx->peers,
-                 ctx->meshes);
-}
-
-
-/**
- * Clean up the testbed.
- *
- * @param ctx handle for the testbed
- */
-void
-GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
-{
-  unsigned int i;
-
-  for (i = 0; i < ctx->num_peers; i++)
-  {
-    GNUNET_assert (NULL != ctx->ops[i]);
-    GNUNET_TESTBED_operation_done (ctx->ops[i]);
-    ctx->ops[i] = NULL;
-  }
-  GNUNET_free (ctx->ops);
-  GNUNET_free (ctx->meshes);
-  GNUNET_free (ctx);
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callback run when the testbed is ready (peers running and connected to
- * each other)
- * 
- * @param cls Closure (context).
- * @param num_peers Number of peers that are running.
- * @param peers Handles to each one of the @c num_peers peers.
- * @param links_succeeded the number of overlay link connection attempts that
- *          succeeded
- * @param links_failed the number of overlay link connection attempts that
- *          failed
- */
-static void
-mesh_test_run (void *cls,
-               unsigned int num_peers,
-               struct GNUNET_TESTBED_Peer **peers,
-               unsigned int links_succeeded,
-               unsigned int links_failed)
-{
-  struct GNUNET_MESH_TEST_Context *ctx = cls;
-  unsigned int i;
-
-  GNUNET_assert (num_peers == ctx->num_peers);
-  ctx->peers = peers;
-  for (i = 0; i < num_peers; i++)
-  {
-    struct GNUNET_MESH_TEST_AdapterContext *newctx;
-    newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
-    newctx->peer = i;
-    newctx->ctx = ctx;
-    ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
-                                                  peers[i],
-                                                  "mesh",
-                                                  &mesh_connect_cb,
-                                                  ctx,
-                                                  &mesh_connect_adapter,
-                                                  &mesh_disconnect_adapter,
-                                                  newctx);
-  }
-}
-
-
-/**
- * Run a test using the given name, configuration file and number of
- * peers.
- * All mesh callbacks will receive the peer number as the closure.
- *
- * @param testname Name of the test (for logging).
- * @param cfgname Name of the configuration file.
- * @param num_peers Number of peers to start.
- * @param tmain Main function to run once the testbed is ready.
- * @param tmain_cls Closure for 'tmain'.
- * @param new_tunnel Handler for incoming tunnels.
- * @param cleaner Cleaner for destroyed incoming tunnels.
- * @param handlers Message handlers.
- * @param stypes Application types.
- */
-void 
-GNUNET_MESH_TEST_run (const char *testname,
-                      const char *cfgname,
-                      unsigned int num_peers,
-                      GNUNET_MESH_TEST_AppMain tmain,
-                      void *tmain_cls,
-                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                      GNUNET_MESH_TunnelEndHandler cleaner,
-                      struct GNUNET_MESH_MessageHandler* handlers,
-                      const GNUNET_MESH_ApplicationType* stypes)
-{
-  struct GNUNET_MESH_TEST_Context *ctx;
-
-  ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
-  ctx->num_peers = num_peers;
-  ctx->ops = GNUNET_malloc (num_peers * sizeof (struct 
GNUNET_TESTBED_Operation *));
-  ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle 
*));
-  ctx->app_main = tmain;
-  ctx->app_main_cls = tmain_cls;
-  ctx->new_tunnel = new_tunnel;
-  ctx->cleaner = cleaner;
-  ctx->handlers = handlers;
-  ctx->stypes = stypes;
-  GNUNET_TESTBED_test_run (testname,
-                           cfgname,
-                           num_peers,
-                           0LL, NULL, NULL,
-                           &mesh_test_run, ctx);
-}
-
-/* end of mesh_test_lib.c */

Copied: gnunet/src/mesh/mesh_test_lib.c (from rev 27670, 
gnunet/src/mesh/mesh2_test_lib.c)
===================================================================
--- gnunet/src/mesh/mesh_test_lib.c                             (rev 0)
+++ gnunet/src/mesh/mesh_test_lib.c     2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,283 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file mesh/mesh_test_lib.c
+ * @author Bartlomiej Polot
+ * @brief library for writing MESH tests
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "mesh_test_lib.h"
+#include "gnunet_mesh_service.h"
+
+/**
+ * Test context for a MESH Test.
+ */
+struct GNUNET_MESH_TEST_Context
+{
+  /**
+   * Array of running peers.
+   */
+  struct GNUNET_TESTBED_Peer **peers;
+
+  /**
+   * Array of handles to the MESH for each peer.
+   */
+  struct GNUNET_MESH_Handle **meshes;
+
+  /**
+   * Operation associated with the connection to the MESH.
+   */
+  struct GNUNET_TESTBED_Operation **ops;
+
+  /**
+   * Main function of the test to run once all MESHs are available.
+   */
+  GNUNET_MESH_TEST_AppMain app_main;
+  
+  /**
+   * Closure for 'app_main'.
+   */
+  void *app_main_cls;
+
+  /**
+   * Number of peers running, size of the arrays above.
+   */
+  unsigned int num_peers;
+
+  /**
+   * Handler for incoming tunnels.
+   */
+  GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
+
+  /**
+   * Cleaner for destroyed incoming tunnels.
+   */
+  GNUNET_MESH_TunnelEndHandler *cleaner;
+
+  /**
+   * Message handlers.
+   */
+  struct GNUNET_MESH_MessageHandler* handlers;
+
+  /**
+   * Application ports.
+   */
+  const uint32_t *ports;
+
+};
+
+
+/**
+ * Context for a mesh adapter callback.
+ */
+struct GNUNET_MESH_TEST_AdapterContext
+{
+  /**
+   * Peer number for the particular peer.
+   */
+  unsigned int peer;
+
+  /**
+   * General context.
+   */
+  struct GNUNET_MESH_TEST_Context *ctx;
+};
+
+
+/**
+ * Adapter function called to establish a connection to
+ * the MESH service.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer to connect to; will be available until
+ *          GNUNET_TESTBED_operation_done() is called on the operation returned
+ *          from GNUNET_TESTBED_service_connect()
+ * @return service handle to return in 'op_result', NULL on error
+ */
+static void *
+mesh_connect_adapter (void *cls,
+                      const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
+  struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
+  struct GNUNET_MESH_Handle *h;
+
+  h = GNUNET_MESH_connect (cfg,
+                           (void *) (long) actx->peer,
+                           ctx->new_tunnel,
+                           ctx->cleaner,
+                           ctx->handlers,
+                           ctx->ports);
+  return h;
+}
+
+
+/**
+ * Adapter function called to destroy a connection to
+ * the MESH service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
+ */
+static void 
+mesh_disconnect_adapter (void *cls,
+                         void *op_result)
+{
+  struct GNUNET_MESH_Handle *mesh = op_result;
+  struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
+
+  GNUNET_free (actx);
+  GNUNET_MESH_disconnect (mesh);
+}
+
+
+/**
+ * Callback to be called when a service connect operation is completed.
+ *
+ * @param cls The callback closure from functions generating an operation.
+ * @param op The operation that has been finished.
+ * @param ca_result The service handle returned from 
+ *                  GNUNET_TESTBED_ConnectAdapter() (mesh handle).
+ * @param emsg Error message in case the operation has failed.
+ *             NULL if operation has executed successfully.
+ */
+static void 
+mesh_connect_cb (void *cls,
+                 struct GNUNET_TESTBED_Operation *op,
+                 void *ca_result,
+                 const char *emsg)
+{
+  struct GNUNET_MESH_TEST_Context *ctx = cls;
+  unsigned int i;
+ 
+  if (NULL != emsg)
+  {
+    fprintf (stderr, "Failed to connect to MESH service: %s\n",
+             emsg);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  for (i = 0; i < ctx->num_peers; i++)
+    if (op == ctx->ops[i])
+      ctx->meshes[i] = ca_result;
+  for (i = 0; i < ctx->num_peers; i++)
+    if (NULL == ctx->meshes[i])
+      return; /* still some MESH connections missing */
+  /* all MESH connections ready! */
+  ctx->app_main (ctx->app_main_cls,
+                 ctx,
+                 ctx->num_peers,
+                 ctx->peers,
+                 ctx->meshes);
+}
+
+
+void
+GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
+{
+  unsigned int i;
+
+  for (i = 0; i < ctx->num_peers; i++)
+  {
+    GNUNET_assert (NULL != ctx->ops[i]);
+    GNUNET_TESTBED_operation_done (ctx->ops[i]);
+    ctx->ops[i] = NULL;
+  }
+  GNUNET_free (ctx->ops);
+  GNUNET_free (ctx->meshes);
+  GNUNET_free (ctx);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Callback run when the testbed is ready (peers running and connected to
+ * each other)
+ * 
+ * @param cls Closure (context).
+ * @param num_peers Number of peers that are running.
+ * @param peers Handles to each one of the @c num_peers peers.
+ * @param links_succeeded the number of overlay link connection attempts that
+ *          succeeded
+ * @param links_failed the number of overlay link connection attempts that
+ *          failed
+ */
+static void
+mesh_test_run (void *cls,
+               unsigned int num_peers,
+               struct GNUNET_TESTBED_Peer **peers,
+               unsigned int links_succeeded,
+               unsigned int links_failed)
+{
+  struct GNUNET_MESH_TEST_Context *ctx = cls;
+  unsigned int i;
+
+  GNUNET_assert (num_peers == ctx->num_peers);
+  ctx->peers = peers;
+  for (i = 0; i < num_peers; i++)
+  {
+    struct GNUNET_MESH_TEST_AdapterContext *newctx;
+    newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
+    newctx->peer = i;
+    newctx->ctx = ctx;
+    ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
+                                                  peers[i],
+                                                  "mesh",
+                                                  &mesh_connect_cb,
+                                                  ctx,
+                                                  &mesh_connect_adapter,
+                                                  &mesh_disconnect_adapter,
+                                                  newctx);
+  }
+}
+
+
+void 
+GNUNET_MESH_TEST_run (const char *testname,
+                      const char *cfgname,
+                      unsigned int num_peers,
+                      GNUNET_MESH_TEST_AppMain tmain,
+                      void *tmain_cls,
+                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
+                      GNUNET_MESH_TunnelEndHandler cleaner,
+                      struct GNUNET_MESH_MessageHandler* handlers,
+                      const uint32_t *ports)
+{
+  struct GNUNET_MESH_TEST_Context *ctx;
+
+  ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
+  ctx->num_peers = num_peers;
+  ctx->ops = GNUNET_malloc (num_peers * sizeof (struct 
GNUNET_TESTBED_Operation *));
+  ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle 
*));
+  ctx->app_main = tmain;
+  ctx->app_main_cls = tmain_cls;
+  ctx->new_tunnel = new_tunnel;
+  ctx->cleaner = cleaner;
+  ctx->handlers = handlers;
+  ctx->ports = ports;
+  GNUNET_TESTBED_test_run (testname,
+                           cfgname,
+                           num_peers,
+                           0LL, NULL, NULL,
+                           &mesh_test_run, ctx);
+}
+
+/* end of mesh_test_lib.c */

Deleted: gnunet/src/mesh/mesh_test_lib.h
===================================================================
--- gnunet/src/mesh/mesh_test_lib.h     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/mesh_test_lib.h     2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,106 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/mesh_test_lib.h
- * @author Bartlomiej Polot
- * @brief library for writing MESH tests
- */
-#ifndef MESH_TEST_LIB_H
-#define MESH_TEST_LIB_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_testbed_service.h"
-#include "gnunet_mesh_service.h"
-
-/**
- * Test context for a MESH Test.
- */
-struct GNUNET_MESH_TEST_Context;
-
-
-/**
- * Main function of a MESH test.
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param peers Array of peers.
- * @param meshes Handle to each of the MESHs of the peers.
- */
-typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls,
-                                          struct GNUNET_MESH_TEST_Context *ctx,
-                                          unsigned int num_peers,
-                                          struct GNUNET_TESTBED_Peer **peers,
-                                          struct GNUNET_MESH_Handle **meshes);
-
-
-/**
- * Run a test using the given name, configuration file and number of
- * peers.
- * All mesh callbacks will receive the peer number as the closure.
- *
- * @param testname Name of the test (for logging).
- * @param cfgname Name of the configuration file.
- * @param num_peers Number of peers to start.
- * @param tmain Main function to run once the testbed is ready.
- * @param tmain_cls Closure for 'tmain'.
- * @param new_tunnel Handler for incoming tunnels.
- * @param cleaner Cleaner for destroyed incoming tunnels.
- * @param handlers Message handlers.
- * @param stypes Application types.
- */
-void 
-GNUNET_MESH_TEST_run (const char *testname,
-                      const char *cfgname,
-                      unsigned int num_peers,
-                      GNUNET_MESH_TEST_AppMain tmain,
-                      void *tmain_cls,
-                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
-                      GNUNET_MESH_TunnelEndHandler cleaner,
-                      struct GNUNET_MESH_MessageHandler* handlers,
-                      const GNUNET_MESH_ApplicationType* stypes);
-
-
-/**
- * Clean up the testbed.
- *
- * @param ctx handle for the testbed
- */
-void
-GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-
-/* ifndef MESH_TEST_LIB_H */
-#endif

Copied: gnunet/src/mesh/mesh_test_lib.h (from rev 27670, 
gnunet/src/mesh/mesh2_test_lib.h)
===================================================================
--- gnunet/src/mesh/mesh_test_lib.h                             (rev 0)
+++ gnunet/src/mesh/mesh_test_lib.h     2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,106 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file mesh/mesh_test_lib.h
+ * @author Bartlomiej Polot
+ * @brief library for writing MESH tests
+ */
+#ifndef MESH_TEST_LIB_H
+#define MESH_TEST_LIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_testbed_service.h"
+#include "gnunet_mesh_service.h"
+
+/**
+ * Test context for a MESH Test.
+ */
+struct GNUNET_MESH_TEST_Context;
+
+
+/**
+ * Main function of a MESH test.
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param peers Array of peers.
+ * @param meshes Handle to each of the MESHs of the peers.
+ */
+typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls,
+                                          struct GNUNET_MESH_TEST_Context *ctx,
+                                          unsigned int num_peers,
+                                          struct GNUNET_TESTBED_Peer **peers,
+                                          struct GNUNET_MESH_Handle **meshes);
+
+
+/**
+ * Run a test using the given name, configuration file and number of
+ * peers.
+ * All mesh callbacks will receive the peer number as the closure.
+ *
+ * @param testname Name of the test (for logging).
+ * @param cfgname Name of the configuration file.
+ * @param num_peers Number of peers to start.
+ * @param tmain Main function to run once the testbed is ready.
+ * @param tmain_cls Closure for 'tmain'.
+ * @param new_tunnel Handler for incoming tunnels.
+ * @param cleaner Cleaner for destroyed incoming tunnels.
+ * @param handlers Message handlers.
+ * @param ports Ports the peers offer.
+ */
+void 
+GNUNET_MESH_TEST_run (const char *testname,
+                      const char *cfgname,
+                      unsigned int num_peers,
+                      GNUNET_MESH_TEST_AppMain tmain,
+                      void *tmain_cls,
+                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
+                      GNUNET_MESH_TunnelEndHandler cleaner,
+                      struct GNUNET_MESH_MessageHandler* handlers,
+                      const uint32_t* ports);
+
+
+/**
+ * Clean up the testbed.
+ *
+ * @param ctx handle for the testbed
+ */
+void
+GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef MESH_TEST_LIB_H */
+#endif

Modified: gnunet/src/mesh/plugin_block_mesh.c
===================================================================
--- gnunet/src/mesh/plugin_block_mesh.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/plugin_block_mesh.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -149,7 +149,6 @@
                            struct GNUNET_HashCode * key)
 {
   const struct PBlock *pb;
-  GNUNET_MESH_ApplicationType app_type;
   pb = block;
 
   switch (type)
@@ -159,10 +158,6 @@
       return GNUNET_SYSERR;
     *key = pb->id.hashPubKey;
     return GNUNET_OK;
-  case GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE:
-    app_type = ntohl (pb->type);
-    GNUNET_CRYPTO_hash (&app_type, sizeof(GNUNET_MESH_ApplicationType), key);
-    return GNUNET_OK;
   default:
     GNUNET_break (0);
     return GNUNET_SYSERR;

Deleted: gnunet/src/mesh/test_mesh.conf
===================================================================
--- gnunet/src/mesh/test_mesh.conf      2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh.conf      2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,82 +0,0 @@
-[fs]
-AUTOSTART = NO
-
-[resolver]
-AUTOSTART = NO
-
-[mesh]
-AUTOSTART = YES
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 10511
-# PREFIX = valgrind --leak-check=full
-# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
-REFRESH_PATH_TIME = 3 s
-APP_ANNOUNCE_TIME = 5 s
-ID_ANNOUNCE_TIME = 5 s
-CONNECT_TIMEOUT = 30 s
-DEFAULT_TTL = 16
-DHT_REPLICATION_LEVEL = 3
-MAX_TUNNELS = 10
-MAX_MSGS_QUEUE = 20
-
-[vpn]
-AUTOSTART = NO
-PORT = 10012
-
-[dht]
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 12100
-
-[block]
-plugins = dht test
-
-[dhtcache]
-QUOTA = 1 MB
-DATABASE = sqlite
-
-[transport]
-PLUGINS = tcp
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-NEIGHBOUR_LIMIT = 50
-PORT = 12365
-
-[ats]
-WAN_QUOTA_OUT = 3932160
-WAN_QUOTA_IN = 3932160
-
-[core]
-PORT = 12092
-
-[arm]
-DEFAULTSERVICES = core
-PORT = 12366
-
-[transport-tcp]
-TIMEOUT = 300 s
-PORT = 12368
-
-[TESTING]
-WEAKRANDOM = YES
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[PATHS]
-SERVICEHOME = /tmp/test-mesh/
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[namestore]
-AUTOSTART = NO
-
-[consensus]
-AUTOSTART = NO

Copied: gnunet/src/mesh/test_mesh.conf (from rev 27674, 
gnunet/src/mesh/test_mesh2.conf)
===================================================================
--- gnunet/src/mesh/test_mesh.conf                              (rev 0)
+++ gnunet/src/mesh/test_mesh.conf      2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,89 @@
+[PATHS]
+SERVICEHOME = /tmp/test-mesh/
+
+[mesh]
+BINARY = gnunet-service-mesh-new
+AUTOSTART = NO
+ACCEPT_FROM = 127.0.0.1;
+HOSTNAME = localhost
+PORT = 10511
+#PREFIX = valgrind --leak-check=full
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+REFRESH_PATH_TIME = 2 s
+APP_ANNOUNCE_TIME = 5 s
+ID_ANNOUNCE_TIME = 5 s
+CONNECT_TIMEOUT = 30 s
+DEFAULT_TTL = 16
+DHT_REPLICATION_LEVEL = 3
+MAX_TUNNELS = 10
+MAX_MSGS_QUEUE = 20
+
+[testbed]
+NUM_PEERS = 5
+OVERLAY_TOPOLOGY = LINE
+
+[fs]
+AUTOSTART = NO
+
+[resolver]
+AUTOSTART = NO
+
+[vpn]
+AUTOSTART = NO
+PORT = 10012
+
+[dht]
+AUTOSTART = YES
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+HOSTNAME = localhost
+PORT = 12100
+DISABLE_TRY_CONNECT = YES
+FORCE_NSE = 3
+
+[block]
+plugins = dht test
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = sqlite
+
+[transport]
+PLUGINS = tcp
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+NEIGHBOUR_LIMIT = 50
+PORT = 12365
+
+[ats]
+WAN_QUOTA_OUT = 3932160
+WAN_QUOTA_IN = 3932160
+
+[core]
+PORT = 12092
+
+[arm]
+DEFAULTSERVICES = core mesh
+PORT = 12366
+
+[transport-tcp]
+TIMEOUT = 300 s
+PORT = 12368
+
+[TESTING]
+WEAKRANDOM = YES
+
+[gnunetd]
+HOSTKEY = $SERVICEHOME/.hostkey
+
+[dns]
+AUTOSTART = NO
+
+[nse]
+AUTOSTART = NO
+
+[namestore]
+AUTOSTART = NO
+
+[consensus]
+AUTOSTART = NO

Deleted: gnunet/src/mesh/test_mesh2.conf
===================================================================
--- gnunet/src/mesh/test_mesh2.conf     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh2.conf     2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,89 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/test-mesh/
-
-[mesh]
-BINARY = gnunet-service-mesh-new
-AUTOSTART = NO
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 10511
-#PREFIX = valgrind --leak-check=full
-#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
-REFRESH_PATH_TIME = 2 s
-APP_ANNOUNCE_TIME = 5 s
-ID_ANNOUNCE_TIME = 5 s
-CONNECT_TIMEOUT = 30 s
-DEFAULT_TTL = 16
-DHT_REPLICATION_LEVEL = 3
-MAX_TUNNELS = 10
-MAX_MSGS_QUEUE = 20
-
-[testbed]
-NUM_PEERS = 5
-OVERLAY_TOPOLOGY = LINE
-
-[fs]
-AUTOSTART = NO
-
-[resolver]
-AUTOSTART = NO
-
-[vpn]
-AUTOSTART = NO
-PORT = 10012
-
-[dht]
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 12100
-DISABLE_TRY_CONNECT = YES
-FORCE_NSE = 3
-
-[block]
-plugins = dht test
-
-[dhtcache]
-QUOTA = 1 MB
-DATABASE = sqlite
-
-[transport]
-PLUGINS = tcp
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-NEIGHBOUR_LIMIT = 50
-PORT = 12365
-
-[ats]
-WAN_QUOTA_OUT = 3932160
-WAN_QUOTA_IN = 3932160
-
-[core]
-PORT = 12092
-
-[arm]
-DEFAULTSERVICES = core mesh
-PORT = 12366
-
-[transport-tcp]
-TIMEOUT = 300 s
-PORT = 12368
-
-[TESTING]
-WEAKRANDOM = YES
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[namestore]
-AUTOSTART = NO
-
-[consensus]
-AUTOSTART = NO

Deleted: gnunet/src/mesh/test_mesh2_local.c
===================================================================
--- gnunet/src/mesh/test_mesh2_local.c  2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh2_local.c  2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,299 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/test_mesh2_local.c
- * @brief test mesh2 local: test of mesh2 tunnels with just one peer
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_mesh2_service.h"
-
-struct GNUNET_TESTING_Peer *me;
-
-static struct GNUNET_MESH_Handle *mesh_peer_1;
-
-static struct GNUNET_MESH_Handle *mesh_peer_2;
-
-static struct GNUNET_MESH_Tunnel *t;
-
-static int result = GNUNET_OK;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
-
-
-/**
- * Shutdown nicely
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
-  if (GNUNET_SCHEDULER_NO_TASK != abort_task)
-  {
-    GNUNET_SCHEDULER_cancel (abort_task);
-  }
-  if (NULL != t)
-  {
-    GNUNET_MESH_tunnel_destroy (t);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n");
-  if (NULL != mesh_peer_1)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_1);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n");
-  if (NULL != mesh_peer_2)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_2);
-  }
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n");
-  result = GNUNET_SYSERR;
-  abort_task = GNUNET_SCHEDULER_NO_TASK;
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-    shutdown_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  do_shutdown (cls, tc);
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param message the actual message
- * 
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-               const struct GNUNET_MessageHeader *message)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback! Shutting down.\n");
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-  shutdown_task =
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown,
-                                  NULL);
-  GNUNET_MESH_receive_done (tunnel);
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param port port number
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
- */
-static void *
-inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                const struct GNUNET_PeerIdentity *initiator,
-                uint32_t port)
-{
-  long id = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "received incoming tunnel on peer %d, port %u\n",
-              id, port);
-  if (id != 2L)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "wrong peer\n");
-    result = GNUNET_SYSERR;
-  }
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-             void *tunnel_ctx)
-{
-  long id = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "incoming tunnel closed at peer %ld\n",
-              id);
-}
-
-
-/**
- * Handler array for traffic received on peer1
- */
-static struct GNUNET_MESH_MessageHandler handlers1[] = {
-  {&data_callback, 1, 0},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Handler array for traffic received on peer2 (none expected)
- */
-static struct GNUNET_MESH_MessageHandler handlers2[] = {
-  {&data_callback, 1, 0},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Data send callback: fillbuffer with test packet.
- * 
- * @param cls Closure (unused).
- * @param size Buffer size.
- * @param buf Buffer to fill.
- * 
- * @return size of test packet.
- */
-static size_t
-do_send (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *m = buf;
-
-  if (NULL == buf)
-  {
-    GNUNET_break (0);
-    result = GNUNET_SYSERR;
-    return 0;
-  }
-  m->size = htons (sizeof (struct GNUNET_MessageHeader));
-  m->type = htons (1);
-  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
-  return sizeof (struct GNUNET_MessageHeader);
-}
-
-/**
- * Connect to other client and send data
- * 
- * @param cls Closue (unused).
- * @param tc TaskContext.
- */
-static void
-do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_PeerIdentity id;
-
-  GNUNET_TESTING_peer_get_identity (me, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n");
-  t = GNUNET_MESH_tunnel_create (mesh_peer_1, NULL, &id, 1);
-  GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     sizeof (struct GNUNET_MessageHeader),
-                                     &do_send, NULL);
-}
-
-
-/**
- * Initialize framework and start test
- * 
- * @param cls Closure (unused).
- * @param cfg Configuration handle.
- * @param peer Testing peer handle.
- */
-static void
-run (void *cls, 
-     const struct GNUNET_CONFIGURATION_Handle *cfg,
-     struct GNUNET_TESTING_Peer *peer)
-{
-  static uint32_t ports[] = {1, 0};
-
-  me = peer;
-  abort_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort,
-                                    NULL);
-  mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) 1L,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers1, /* traffic handlers */
-                                     NULL);     /* ports offered */
-
-  mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) 2L,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers2, /* traffic handlers */
-                                     ports);     /* ports offered */
-  if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n");
-    result = GNUNET_SYSERR;
-    return;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO MESH :D\n");
-  }
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_connect, NULL);
-}
-
-
-/**
- * Main
- */
-int
-main (int argc, char *argv[])
-{
-  if (0 != GNUNET_TESTING_peer_run ("test-mesh-local",
-                                    "test_mesh2.conf",
-                                &run, NULL))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
-    return 2;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result);
-  return (result == GNUNET_OK) ? 0 : 1;
-}
-
-/* end of test_mesh_local_1.c */

Deleted: gnunet/src/mesh/test_mesh2_small.c
===================================================================
--- gnunet/src/mesh/test_mesh2_small.c  2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh2_small.c  2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,833 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/test_mesh2_small.c
- *
- * @brief Test for the mesh service: retransmission of traffic.
- */
-#include <stdio.h>
-#include "platform.h"
-#include "mesh2_test_lib.h"
-#include "gnunet_mesh2_service.h"
-#include <gauger.h>
-
-
-/**
- * How namy messages to send
- */
-#define TOTAL_PACKETS 1000
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
-
-/**
- * Time to wait for stuff that should be rather fast
- */
-#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
-
-/**
- * DIFFERENT TESTS TO RUN
- */
-#define SETUP 0
-#define FORWARD 1
-#define SPEED 3
-#define SPEED_ACK 4
-#define SPEED_NOBUF 6
-#define P2P_SIGNAL 10
-
-/**
- * Which test are we running?
- */
-static int test;
-
-/**
- * String with test name
- */
-char *test_name;
-
-/**
- * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
- */
-static int test_backwards = GNUNET_NO;
-
-/**
- * How many events have happened
- */
-static int ok;
-
- /**
-  * Each peer is supposed to generate the following callbacks:
-  * 1 incoming tunnel (@dest)
-  * 1 connected peer (@orig)
-  * 1 received data packet (@dest)
-  * 1 received data packet (@orig)
-  * 1 received tunnel destroy (@dest)
-  * _________________________________
-  * 5 x ok expected per peer
-  */
-int ok_goal;
-
-
-/**
- * Size of each test packet
- */
-size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
-
-/**
- * Operation to get peer ids.
- */
-struct GNUNET_TESTBED_Operation *t_op[2];
-
-/**
- * Peer ids.
- */
-struct GNUNET_PeerIdentity *p_id[2];
-
-/**
- * Peer ids counter.
- */
-unsigned int p_ids;
-
-/**
- * Is the setup initialized?
- */
-static int initialized;
-
-/**
- * Peers that have responded
- */
-static int peers_responded;
-
-/**
- * Number of payload packes sent
- */
-static int data_sent;
-
-/**
- * Number of payload packets received
- */
-static int data_received;
-
-/**
- * Number of payload packed explicitly (app level) acknowledged
- */
-static int data_ack;
-
-/**
- * Total number of currently running peers.
- */
-static unsigned long long peers_running;
-
-/**
- * Test context (to shut down).
- */
-struct GNUNET_MESH_TEST_Context *test_ctx;
-
-/**
- * Task called to disconnect peers.
- */
-static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-/**
- * Task To perform tests
- */
-static GNUNET_SCHEDULER_TaskIdentifier test_task;
-
-/**
- * Task called to shutdown test.
- */
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
-
-/**
- * Mesh handle for the root peer
- */
-static struct GNUNET_MESH_Handle *h1;
-
-/**
- * Mesh handle for the first leaf peer
- */
-static struct GNUNET_MESH_Handle *h2;
-
-/**
- * Tunnel handle for the root peer
- */
-static struct GNUNET_MESH_Tunnel *t;
-
-/**
- * Tunnel handle for the first leaf peer
- */
-static struct GNUNET_MESH_Tunnel *incoming_t;
-
-/**
- * Time we started the data transmission (after tunnel has been established
- * and initilized).
- */
-static struct GNUNET_TIME_Absolute start_time;
-
-
-/**
- * Show the results of the test (banwidth acheived) and log them to GAUGER
- */
-static void
-show_end_data (void)
-{
-  static struct GNUNET_TIME_Absolute end_time;
-  static struct GNUNET_TIME_Relative total_time;
-
-  end_time = GNUNET_TIME_absolute_get();
-  total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
-  FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
-  FPRINTF (stderr, "Test time %llu ms\n",
-            (unsigned long long) total_time.rel_value);
-  FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
-            4 * TOTAL_PACKETS * 1.0 / total_time.rel_value); // 4bytes * ms
-  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
-            TOTAL_PACKETS * 1000.0 / total_time.rel_value); // packets * ms
-  GAUGER ("MESH", test_name,
-          TOTAL_PACKETS * 1000.0 / total_time.rel_value,
-          "packets/s");
-}
-
-
-/**
- * Shut down peergroup, clean up.
- * 
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
-  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
-}
-
-
-/**
- * Disconnect from mesh services af all peers, call shutdown.
- * 
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
-{
-  long line = (long) cls;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "disconnecting mesh service of peers, called from line %ld\n",
-              line);
-  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  for (i = 0; i < 2; i++)
-  {
-    GNUNET_TESTBED_operation_done (t_op[i]);
-  }
-  if (NULL != t)
-  {
-    GNUNET_MESH_tunnel_destroy (t);
-    t = NULL;
-  }
-  if (NULL != incoming_t)
-  {
-    GNUNET_MESH_tunnel_destroy (incoming_t);
-    incoming_t = NULL;
-  }
-  GNUNET_MESH_TEST_cleanup (test_ctx);
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_handle);
-  }
-  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
-}
-
-
-/**
- * Abort test: schedule disconnect and shutdown immediately
- * 
- * @param line Line in the code the abort is requested from (__LINE__).
- */
-static void
-abort_test (long line)
-{
-  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
-                                                (void *) line);
-  }
-}
-
-/**
- * Transmit ready callback.
- * 
- * @param cls Closure (message type).
- * @param size Size of the tranmist buffer.
- * @param buf Pointer to the beginning of the buffer.
- * 
- * @return Number of bytes written to buf.
- */
-static size_t
-tmt_rdy (void *cls, size_t size, void *buf);
-
-
-/**
- * Task to schedule a new data transmission.
- * 
- * @param cls Closure (peer #).
- * @param tc Task Context.
- */
-static void
-data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_Tunnel *tunnel;
-
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
-  if (GNUNET_YES == test_backwards)
-  {
-    tunnel = incoming_t;
-  }
-  else
-  {
-    tunnel = t;
-  }
-  th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
-                                          GNUNET_TIME_UNIT_FOREVER_REL,
-                                          size_payload, &tmt_rdy, (void *) 1L);
-  if (NULL == th)
-  {
-    unsigned long i = (unsigned long) cls;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
-    if (0 == i)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
-                                    &data_task, (void *)1UL);
-    }
-    else
-    {
-      i++;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
-                                      GNUNET_TIME_UNIT_MILLISECONDS,
-                                      i),
-                                    &data_task, (void *)i);
-    }
-  }
-}
-
-
-/**
- * Transmit ready callback
- *
- * @param cls Closure (message type).
- * @param size Size of the buffer we have.
- * @param buf Buffer to copy data to.
- */
-size_t
-tmt_rdy (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *msg = buf;
-  uint32_t *data;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " tmt_rdy called\n");
-  if (size < size_payload || NULL == buf)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "size %u, buf %p, data_sent %u, data_received %u\n",
-                size,
-                buf,
-                data_sent,
-                data_received);
-    return 0;
-  }
-  msg->size = htons (size);
-  msg->type = htons ((long) cls);
-  data = (uint32_t *) &msg[1];
-  *data = htonl (data_sent);
-  if (SPEED == test && GNUNET_YES == initialized)
-  {
-    data_sent++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Sent packet %d\n", data_sent);
-    if (data_sent < TOTAL_PACKETS)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Scheduling packet %d\n", data_sent + 1);
-      GNUNET_SCHEDULER_add_now(&data_task, NULL);
-    }
-  }
-  return size_payload;
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-               const struct GNUNET_MessageHeader *message)
-{
-  long client = (long) cls;
-  long expected_target_client;
-  uint32_t *data;
-
-  ok++;
-
-  GNUNET_MESH_receive_done (tunnel);
-
-  if ((ok % 20) == 0)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    {
-      GNUNET_SCHEDULER_cancel (disconnect_task);
-      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                      &disconnect_mesh_peers,
-                                                      (void *) __LINE__);
-    }
-  }
-
-  switch (client)
-  {
-  case 0L:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
-    peers_responded++;
-    break;
-  case 4L:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Leaf client %li got a message.\n",
-                client);
-    client = 4L;
-    break;
-  default:
-    GNUNET_assert (0);
-    break;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
-  data = (uint32_t *) &message[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
-  if (SPEED == test && GNUNET_YES == test_backwards)
-  {
-    expected_target_client = 0L;
-  }
-  else
-  {
-    expected_target_client = 4L;
-  }
-
-  if (GNUNET_NO == initialized)
-  {
-    initialized = GNUNET_YES;
-    start_time = GNUNET_TIME_absolute_get ();
-    if (SPEED == test)
-    {
-      GNUNET_assert (4L == client);
-      GNUNET_SCHEDULER_add_now (&data_task, NULL);
-      return GNUNET_OK;
-    }
-  }
-
-  if (client == expected_target_client) // Normally 3 or 4
-  {
-    data_received++;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                " received data %u\n", data_received);
-    if (SPEED != test || (ok_goal - 2) == ok)
-    {
-      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         size_payload, &tmt_rdy, (void *) 1L);
-      return GNUNET_OK;
-    }
-    else
-    {
-      if (data_received < TOTAL_PACKETS)
-        return GNUNET_OK;
-    }
-  }
-  else // Normally 0
-  {
-    if (test == SPEED_ACK || test == SPEED)
-    {
-      data_ack++;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              " received ack %u\n", data_ack);
-      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         size_payload, &tmt_rdy, (void *) 1L);
-      if (data_ack < TOTAL_PACKETS && SPEED != test)
-        return GNUNET_OK;
-      if (ok == 2 && SPEED == test)
-        return GNUNET_OK;
-      show_end_data();
-    }
-    if (test == P2P_SIGNAL)
-    {
-      GNUNET_MESH_tunnel_destroy (incoming_t);
-      incoming_t = NULL;
-    }
-    else
-    {
-      GNUNET_MESH_tunnel_destroy (t);
-      t = NULL;
-    }
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                    &disconnect_mesh_peers,
-                                                    (void *) __LINE__);
-  }
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Handlers, for diverse services
- */
-static struct GNUNET_MESH_MessageHandler handlers[] = {
-  {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls Closure.
- * @param tunnel New handle to the tunnel.
- * @param initiator Peer that started the tunnel.
- * @param port Port this tunnels is connected to.
- * @return Initial tunnel context for the tunnel
- *         (can be NULL -- that's not an error).
- */
-static void *
-incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                 const struct GNUNET_PeerIdentity *initiator,
-                 uint32_t port)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming tunnel from %s to peer %d\n",
-              GNUNET_i2s (initiator), (long) cls);
-  ok++;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-  if ((long) cls == 4L)
-    incoming_t = tunnel;
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Incoming tunnel for unknown client %lu\n", (long) cls);
-    GNUNET_break(0);
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                    &disconnect_mesh_peers,
-                                                    (void *) __LINE__);
-  }
-
-  return NULL;
-}
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-                void *tunnel_ctx)
-{
-  long i = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming tunnel disconnected at peer %d\n",
-              i);
-  if (4L == i)
-  {
-    ok++;
-    incoming_t = NULL;
-  }
-  else if (0L == i && P2P_SIGNAL == test)
-  {
-    ok ++;
-  }
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Unknown peer! %d\n", i);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
-                                                (void *) __LINE__);
-  }
-
-  return;
-}
-
-
-/**
- * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES.
- * 
- * Testcase continues when the root receives confirmation of connected peers,
- * on callback funtion ch.
- * 
- * @param cls Closure (unsued).
- * @param tc Task Context.
- */
-static void
-do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n");
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "schedule timeout in TIMEOUT\n");
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-  t = GNUNET_MESH_tunnel_create (h1, NULL, p_id[1], 1);
-  if (SPEED_NOBUF == test)
-  {
-    GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
-    test = SPEED;
-  }
-
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_mesh_peers,
-                                                  (void *) __LINE__);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending data initializer...\n");
-  peers_responded = 0;
-  data_ack = 0;
-  data_received = 0;
-  data_sent = 0;
-  GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL, 
-                                     size_payload, &tmt_rdy, (void *) 1L);
-}
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cls the closure from GNUNET_TESTBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed;
- *             NULL if the operation is successfull
- */
-static void
-pi_cb (void *cls,
-       struct GNUNET_TESTBED_Operation *op,
-       const struct GNUNET_TESTBED_PeerInformation *pinfo,
-       const char *emsg)
-{
-  long i = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
-
-  if (NULL == pinfo || NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
-    abort_test (__LINE__);
-    return;
-  }
-  p_id[i] = pinfo->result.id;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  id: %s\n", GNUNET_i2s (p_id[i]));
-  p_ids++;
-  if (p_ids < 2)
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
-  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                            &do_test, NULL);
-}
-
-/**
- * test main: start test when all peers are connected
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param peers Array of peers.
- * @param meshes Handle to each of the MESHs of the peers.
- */
-static void
-tmain (void *cls,
-       struct GNUNET_MESH_TEST_Context *ctx,
-       unsigned int num_peers,
-       struct GNUNET_TESTBED_Peer **peers,
-       struct GNUNET_MESH_Handle **meshes)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
-  ok = 0;
-  test_ctx = ctx;
-  peers_running = num_peers;
-  h1 = meshes[0];
-  h2 = meshes[num_peers - 1];
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_mesh_peers,
-                                                  (void *) __LINE__);
-  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                                  &shutdown_task, NULL);
-  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
-                                                 GNUNET_TESTBED_PIT_IDENTITY,
-                                                 &pi_cb, (void *) 0L);
-  t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
-                                                 GNUNET_TESTBED_PIT_IDENTITY,
-                                                 &pi_cb, (void *) 1L);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
-}
-
-
-/**
- * Main: start test
- */
-int
-main (int argc, char *argv[])
-{
-  initialized = GNUNET_NO;
-  uint32_t ports[2];
-
-  GNUNET_log_setup ("test", "DEBUG", NULL);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
-  if (strstr (argv[0], "_small_forward") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
-    test = FORWARD;
-    test_name = "unicast2";
-    ok_goal = 4;
-  }
-  else if (strstr (argv[0], "_small_signal") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
-    test = P2P_SIGNAL;
-    test_name = "signal2";
-    ok_goal = 4;
-  }
-  else if (strstr (argv[0], "_small_speed_ack") != NULL)
-  {
-   /* Each peer is supposed to generate the following callbacks:
-    * 1 incoming tunnel (@dest)
-    * TOTAL_PACKETS received data packet (@dest)
-    * TOTAL_PACKETS received data packet (@orig)
-    * 1 received tunnel destroy (@dest)
-    * _________________________________
-    * 5 x ok expected per peer
-    */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
-    test = SPEED_ACK;
-    test_name = "speed2 ack";
-    ok_goal = TOTAL_PACKETS * 2 + 2;
-  }
-  else if (strstr (argv[0], "_small_speed") != NULL)
-  {
-   /* Each peer is supposed to generate the following callbacks:
-    * 1 incoming tunnel (@dest)
-    * 1 initial packet (@dest)
-    * TOTAL_PACKETS received data packet (@dest)
-    * 1 received data packet (@orig)
-    * 1 received tunnel destroy (@dest)
-    * _________________________________
-    */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
-    ok_goal = TOTAL_PACKETS + 4;
-    if (strstr (argv[0], "_nobuf") != NULL)
-    {
-      test = SPEED_NOBUF;
-      test_name = "speed2 nobuf";
-    }
-    else
-    {
-      test = SPEED;
-      test_name = "speed2";
-    }
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
-    test = SETUP;
-    ok_goal = 0;
-  }
-
-  if (strstr (argv[0], "backwards") != NULL)
-  {
-    char *aux;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
-    test_backwards = GNUNET_YES;
-    aux = GNUNET_malloc (32);
-    sprintf (aux, "backwards %s", test_name);
-    test_name = aux;
-  }
-
-  p_ids = 0;
-  ports[0] = 1;
-  ports[1] = 0;
-  GNUNET_MESH_TEST_run ("test_mesh2_small",
-                        "test_mesh2.conf",
-                        5,
-                        &tmain,
-                        NULL, /* tmain cls */
-                        &incoming_tunnel,
-                        &tunnel_cleaner,
-                        handlers,
-                        ports);
-
-  if (ok_goal > ok)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "FAILED! (%d/%d)\n", ok, ok_goal);
-    return 1;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
-  return 0;
-}
-
-/* end of test_mesh_small.c */
-

Deleted: gnunet/src/mesh/test_mesh_2dtorus.c
===================================================================
--- gnunet/src/mesh/test_mesh_2dtorus.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh_2dtorus.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,128 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/test_mesh_2dtorus.c
- *
- * @brief Test for creating a 2dtorus.
- */
-#include "platform.h"
-#include "mesh_test_lib.h"
-#include "gnunet_mesh_service.h"
-
-#define REMOVE_DIR GNUNET_YES
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
-
-/**
- * Time to wait for stuff that should be rather fast
- */
-#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-
-
-/**
- * How many events have happened
- */
-static int ok;
-
-/**
- * Total number of currently running peers.
- */
-static unsigned long long peers_running;
-
-/**
- * Task to time out.
- */
-static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down test\n");
-}
-
-
-/**
- * test main: start test when all peers are connected
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param peers Array of peers.
- * @param meshes Handle to each of the MESHs of the peers.
- */
-static void
-tmain (void *cls,
-       struct GNUNET_MESH_TEST_Context *ctx,
-       unsigned int num_peers,
-       struct GNUNET_TESTBED_Peer **peers,
-       struct GNUNET_MESH_Handle **meshes)
-{
-  if (16 != num_peers)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "running peers mismatch, aborting test!\n");
-    ok--;
-    GNUNET_MESH_TEST_cleanup (ctx);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "testbed started successfully with ?? connections\n");
-  peers_running = num_peers;
-  timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, 
-                                               &shutdown_task, ctx);
-  ok = GNUNET_OK;
-  GNUNET_MESH_TEST_cleanup (ctx);
-}
-
-
-/**
- * Main: start test
- */
-int
-main (int argc, char *argv[])
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n");
-  ok = GNUNET_SYSERR;
-
-  GNUNET_MESH_TEST_run ("test_mesh_2dtorus",
-                        "test_mesh_2dtorus.conf",
-                        16,
-                        &tmain,
-                        NULL,
-                        NULL,
-                        NULL,
-                        NULL,
-                        NULL
-  );
-
-  if (GNUNET_OK != ok)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "FAILED!\n");
-    return 1;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
-  return 0;
-}
-
-/* end of test_mesh_2dtorus.c */

Deleted: gnunet/src/mesh/test_mesh_2dtorus.conf
===================================================================
--- gnunet/src/mesh/test_mesh_2dtorus.conf      2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/mesh/test_mesh_2dtorus.conf      2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,71 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/test_mesh_small/
-
-[mesh]
-PORT = 10005
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-DHT_REPLICATION_LEVEL = 10
-# PREFIX = valgrind --leak-check=full
-# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
-
-[testing]
-WEAKRANDOM = YES
-
-[testbed]
-NUM_PEERS = 16
-OVERLAY_TOPOLOGY = 2D_TORUS
-
-[arm]
-PORT = 10010
-DEFAULTSERVICES = core dht mesh
-
-[statistics]
-AUTOSTART = YES
-PORT = 10000
-
-[dht]
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 10001
-DISABLE_TRY_CONNECT = YES
-
-[nse]
-WORKBITS = 0
-
-[dns]
-AUTOSTART = NO
-PORT = 10011
-
-[vpn]
-AUTOSTART = NO
-PORT = 10012
-
-[transport]
-PORT = 10002
-AUTOSTART = YES
-
-[nat]
-DISABLEV6 = YES 
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-RETURN_LOCAL_ADDRESSES = YES
-USE_LOCALADDR = YES
-
-[ats]
-WAN_QUOTA_IN = 1 GB
-WAN_QUOTA_OUT = 1 GB
-
-[core]
-AUTOSTART = YES
-PORT = 10003
-
-[peerinfo]
-AUTOSTART = YES
-PORT = 10004

Deleted: gnunet/src/mesh/test_mesh_api.c
===================================================================
--- gnunet/src/mesh/test_mesh_api.c     2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh_api.c     2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,138 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/test_mesh_api.c
- * @brief test mesh api: dummy test of callbacks
- * @author Bartlomiej Polot
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_mesh_service.h"
-
-static struct GNUNET_MESH_Handle *mesh;
-
-static struct GNUNET_MESH_Tunnel *t;
-
-static int result;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-          const struct GNUNET_PeerIdentity *sender,
-          const struct GNUNET_MessageHeader *message,
-          const struct GNUNET_ATS_Information *atsi)
-{
-  return GNUNET_OK;
-}
-
-
-static struct GNUNET_MESH_MessageHandler handlers[] = { 
-  { &callback, 1, 0 },
-  { NULL, 0, 0 }
-};
-
-
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if (NULL != t)
-  {
-    GNUNET_MESH_tunnel_destroy (t);
-  }
-  if (0 != abort_task)
-  {
-    GNUNET_SCHEDULER_cancel (abort_task);
-  }
-  if (NULL != mesh)
-  {
-    GNUNET_MESH_disconnect (mesh);
-  }
-}
-
-
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  result = GNUNET_SYSERR;
-  abort_task = 0;
-  do_shutdown (cls, tc);
-}
-
-
-static void
-run (void *cls, 
-     const struct GNUNET_CONFIGURATION_Handle *cfg,
-     struct GNUNET_TESTING_Peer *peer)
-{
-  static const GNUNET_MESH_ApplicationType app[] =
-    { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
-
-  mesh = GNUNET_MESH_connect (cfg, NULL, NULL, NULL, handlers, app);
-  if (NULL == mesh)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh 
:(\n");
-    result = GNUNET_SYSERR;
-    return;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
-  }
-  t = GNUNET_MESH_tunnel_create (mesh, NULL, NULL, NULL, NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                (GNUNET_TIME_UNIT_SECONDS, 5), &do_shutdown,
-                                NULL);
-  abort_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
-                                    NULL);
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  result = GNUNET_OK;
-  if (0 != GNUNET_TESTING_peer_run ("test-mesh-api",
-                                   "test_mesh.conf",
-                                   &run, NULL))
-    return 1;
-  return (result == GNUNET_OK) ? 0 : 1;
-}
-
-/* end of test_mesh_api.c */
-

Copied: gnunet/src/mesh/test_mesh_local.c (from rev 27670, 
gnunet/src/mesh/test_mesh2_local.c)
===================================================================
--- gnunet/src/mesh/test_mesh_local.c                           (rev 0)
+++ gnunet/src/mesh/test_mesh_local.c   2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,299 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file mesh/test_mesh_local.c
+ * @brief test mesh local: test of mesh tunnels with just one peer
+ * @author Bartlomiej Polot
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_mesh_service.h"
+
+struct GNUNET_TESTING_Peer *me;
+
+static struct GNUNET_MESH_Handle *mesh_peer_1;
+
+static struct GNUNET_MESH_Handle *mesh_peer_2;
+
+static struct GNUNET_MESH_Tunnel *t;
+
+static int result = GNUNET_OK;
+
+static GNUNET_SCHEDULER_TaskIdentifier abort_task;
+
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
+
+
+/**
+ * Shutdown nicely
+ */
+static void
+do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
+  if (GNUNET_SCHEDULER_NO_TASK != abort_task)
+  {
+    GNUNET_SCHEDULER_cancel (abort_task);
+  }
+  if (NULL != t)
+  {
+    GNUNET_MESH_tunnel_destroy (t);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n");
+  if (NULL != mesh_peer_1)
+  {
+    GNUNET_MESH_disconnect (mesh_peer_1);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n");
+  if (NULL != mesh_peer_2)
+  {
+    GNUNET_MESH_disconnect (mesh_peer_2);
+  }
+}
+
+
+/**
+ * Something went wrong and timed out. Kill everything and set error flag
+ */
+static void
+do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n");
+  result = GNUNET_SYSERR;
+  abort_task = GNUNET_SCHEDULER_NO_TASK;
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_task);
+    shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  do_shutdown (cls, tc);
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_MESH_connect)
+ * @param tunnel connection to the other end
+ * @param tunnel_ctx place to store local state associated with the tunnel
+ * @param message the actual message
+ * 
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
+               const struct GNUNET_MessageHeader *message)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback! Shutting down.\n");
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
+    GNUNET_SCHEDULER_cancel (shutdown_task);
+  shutdown_task =
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown,
+                                  NULL);
+  GNUNET_MESH_receive_done (tunnel);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Method called whenever another peer has added us to a tunnel
+ * the other peer initiated.
+ *
+ * @param cls closure
+ * @param tunnel new handle to the tunnel
+ * @param initiator peer that started the tunnel
+ * @param port port number
+ * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
+ */
+static void *
+inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
+                const struct GNUNET_PeerIdentity *initiator,
+                uint32_t port)
+{
+  long id = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "received incoming tunnel on peer %d, port %u\n",
+              id, port);
+  if (id != 2L)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "wrong peer\n");
+    result = GNUNET_SYSERR;
+  }
+  return NULL;
+}
+
+
+/**
+ * Function called whenever an inbound tunnel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from GNUNET_MESH_connect)
+ * @param tunnel connection to the other end (henceforth invalid)
+ * @param tunnel_ctx place where local state associated
+ *                   with the tunnel is stored
+ */
+static void
+inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
+             void *tunnel_ctx)
+{
+  long id = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "incoming tunnel closed at peer %ld\n",
+              id);
+}
+
+
+/**
+ * Handler array for traffic received on peer1
+ */
+static struct GNUNET_MESH_MessageHandler handlers1[] = {
+  {&data_callback, 1, 0},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * Handler array for traffic received on peer2 (none expected)
+ */
+static struct GNUNET_MESH_MessageHandler handlers2[] = {
+  {&data_callback, 1, 0},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * Data send callback: fillbuffer with test packet.
+ * 
+ * @param cls Closure (unused).
+ * @param size Buffer size.
+ * @param buf Buffer to fill.
+ * 
+ * @return size of test packet.
+ */
+static size_t
+do_send (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *m = buf;
+
+  if (NULL == buf)
+  {
+    GNUNET_break (0);
+    result = GNUNET_SYSERR;
+    return 0;
+  }
+  m->size = htons (sizeof (struct GNUNET_MessageHeader));
+  m->type = htons (1);
+  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
+  return sizeof (struct GNUNET_MessageHeader);
+}
+
+/**
+ * Connect to other client and send data
+ * 
+ * @param cls Closue (unused).
+ * @param tc TaskContext.
+ */
+static void
+do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_PeerIdentity id;
+
+  GNUNET_TESTING_peer_get_identity (me, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n");
+  t = GNUNET_MESH_tunnel_create (mesh_peer_1, NULL, &id, 1);
+  GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     sizeof (struct GNUNET_MessageHeader),
+                                     &do_send, NULL);
+}
+
+
+/**
+ * Initialize framework and start test
+ * 
+ * @param cls Closure (unused).
+ * @param cfg Configuration handle.
+ * @param peer Testing peer handle.
+ */
+static void
+run (void *cls, 
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_TESTING_Peer *peer)
+{
+  static uint32_t ports[] = {1, 0};
+
+  me = peer;
+  abort_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort,
+                                    NULL);
+  mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
+                                     (void *) 1L,     /* cls */
+                                     &inbound_tunnel,   /* inbound new hndlr */
+                                     &inbound_end,      /* inbound end hndlr */
+                                     handlers1, /* traffic handlers */
+                                     NULL);     /* ports offered */
+
+  mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
+                                     (void *) 2L,     /* cls */
+                                     &inbound_tunnel,   /* inbound new hndlr */
+                                     &inbound_end,      /* inbound end hndlr */
+                                     handlers2, /* traffic handlers */
+                                     ports);     /* ports offered */
+  if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n");
+    result = GNUNET_SYSERR;
+    return;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO MESH :D\n");
+  }
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_connect, NULL);
+}
+
+
+/**
+ * Main
+ */
+int
+main (int argc, char *argv[])
+{
+  if (0 != GNUNET_TESTING_peer_run ("test-mesh-local",
+                                    "test_mesh.conf",
+                                &run, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
+    return 2;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result);
+  return (result == GNUNET_OK) ? 0 : 1;
+}
+
+/* end of test_mesh_local_1.c */

Deleted: gnunet/src/mesh/test_mesh_local_1.c
===================================================================
--- gnunet/src/mesh/test_mesh_local_1.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh_local_1.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,294 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/test_mesh_local_1.c
- * @brief test mesh local: test of tunnels with just one peer
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_mesh_service.h"
-
-
-static struct GNUNET_MESH_Handle *mesh_peer_1;
-
-static struct GNUNET_MESH_Handle *mesh_peer_2;
-
-static struct GNUNET_MESH_Tunnel *t;
-
-static unsigned int one = 1;
-
-static unsigned int two = 2;
-
-static int result = GNUNET_OK;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
-
-
-/**
- * Shutdown nicely
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n");
-  if (0 != abort_task)
-  {
-    GNUNET_SCHEDULER_cancel (abort_task);
-  }
-  if (NULL != t)
-  {
-    GNUNET_MESH_tunnel_destroy(t);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n");
-  if (NULL != mesh_peer_1)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_1);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n");
-  if (NULL != mesh_peer_2)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_2);
-  }
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
-  result = GNUNET_SYSERR;
-  abort_task = 0;
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-    shutdown_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  do_shutdown (cls, tc);
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-               const struct GNUNET_PeerIdentity *sender,
-               const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n");
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-  shutdown_task =
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown,
-                                  NULL);
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
- */
-static void *
-inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                const struct GNUNET_PeerIdentity *initiator,
-                const struct GNUNET_ATS_Information *atsi)
-{
-  unsigned int id = *(unsigned int *) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n");
-  if (id != 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "test: received incoming tunnel on peer 2\n");
-    result = GNUNET_SYSERR;
-  }
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-             void *tunnel_ctx)
-{
-  unsigned int id = *(unsigned int *) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n");
-  if (id != 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "test: received closing tunnel on peer 2\n");
-    result = GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * Method called whenever a peer has connected to the tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel stopped working with
- */
-static void
-peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n");
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-    GNUNET_SCHEDULER_cancel(shutdown_task);
-  shutdown_task =  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                 &do_shutdown, NULL);
-}
-
-
-/**
- * Method called whenever a peer has connected to the tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel was created to, NULL on timeout
- * @param atsi performance data for the connection
- */
-static void
-peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n");
-}
-
-
-/**
- * Handler array for traffic received on peer1
- */
-static struct GNUNET_MESH_MessageHandler handlers1[] = {
-  {&data_callback, 1, 0},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Handler array for traffic received on peer2 (none expected)
- */
-static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} };
-
-
-/**
- * Start looking for a peer by type
- */
-static void
-do_find (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CONNECT BY TYPE\n");
-  GNUNET_MESH_peer_request_connect_by_type (t, 1);
-}
-
-
-/**
- * Initialize framework and start test
- */
-static void
-run (void *cls, 
-     const struct GNUNET_CONFIGURATION_Handle *cfg,
-     struct GNUNET_TESTING_Peer *peer)
-{
-  static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 };
-  static const GNUNET_MESH_ApplicationType app2[] = { 0 };
-
-  abort_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
-                                    NULL);
-  mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) &one,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers1, /* traffic handlers */
-                                     app1);     /* apps offered */
-
-  mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) &two,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers2, /* traffic handlers */
-                                     app2);     /* apps offered */
-  if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh 
:(\n");
-    result = GNUNET_SYSERR;
-    return;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
-  }
-  t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected,
-                                 &peer_disconnected, (void *) &two);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_find, NULL);
-}
-
-
-/**
- * Main
- */
-int
-main (int argc, char *argv[])
-{
-  if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-1",
-                                   "test_mesh.conf",
-                                   &run, NULL))
-    return 1;
-  return (result == GNUNET_OK) ? 0 : 1;
-}
-
-/* end of test_mesh_local_1.c */

Deleted: gnunet/src/mesh/test_mesh_local_2.c
===================================================================
--- gnunet/src/mesh/test_mesh_local_2.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh_local_2.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,290 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/test_mesh_local.c
- * @brief test mesh local: test of tunnels with just one peer
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_mesh_service.h"
-
-static struct GNUNET_MESH_Handle *mesh_peer_1;
-
-static struct GNUNET_MESH_Handle *mesh_peer_2;
-
-static struct GNUNET_MESH_Tunnel *t;
-
-static unsigned int one = 1;
-
-static unsigned int two = 2;
-
-static int result = GNUNET_OK;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier test_task;
-
-
-/**
- * Shutdown nicely
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n");
-  if (0 != abort_task)
-  {
-    GNUNET_SCHEDULER_cancel (abort_task);
-  }
-  if (NULL != t)
-  {
-    GNUNET_MESH_tunnel_destroy(t);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n");
-  if (NULL != mesh_peer_1)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_1);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n");
-  if (NULL != mesh_peer_2)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_2);
-  }
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n");
-  if (0 != test_task)
-  {
-    GNUNET_SCHEDULER_cancel (test_task);
-  }
-  result = GNUNET_SYSERR;
-  abort_task = 0;
-  do_shutdown (cls, tc);
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-               const struct GNUNET_PeerIdentity *sender,
-               const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n");
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown,
-                                NULL);
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
- */
-static void *
-inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                const struct GNUNET_PeerIdentity *initiator,
-                const struct GNUNET_ATS_Information *atsi)
-{
-  unsigned int id = *(unsigned int *) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n");
-  if (id != 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "test: received incoming tunnel on peer 2\n");
-    result = GNUNET_SYSERR;
-  }
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-             void *tunnel_ctx)
-{
-  unsigned int id = *(unsigned int *) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n");
-  if (id != 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "test: received closing tunnel on peer 2\n");
-    result = GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * Method called whenever a peer has disconnected from the tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel stopped working with
- */
-static void
-peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n");
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, NULL);
-}
-
-
-/**
- * Method called whenever a peer has connected to the tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel was created to, NULL on timeout
- * @param atsi performance data for the connection
- */
-static void
-peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n");
-}
-
-
-/**
- * Handler array for traffic received on peer1
- */
-static struct GNUNET_MESH_MessageHandler handlers1[] = {
-  {&data_callback, 1, 0},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Handler array for traffic received on peer2 (none expected)
- */
-static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} };
-
-
-/**
- * Start looking for a peer by type
- */
-static void
-do_connect_peer_1 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 };
-
-  test_task = GNUNET_SCHEDULER_NO_TASK;
-  mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) &one,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers1, /* traffic handlers */
-                                     app1);     /* apps offered */
-}
-
-
-/**
- * Initialize framework and start test
- */
-static void
-run (void *cls, 
-     const struct GNUNET_CONFIGURATION_Handle *cfg,
-     struct GNUNET_TESTING_Peer *peer)
-{
-  static const GNUNET_MESH_ApplicationType app2[] = { 0 };
-
-  abort_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
-                                    NULL);
-  mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) &two,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers2, /* traffic handlers */
-                                     app2);     /* apps offered */
-  if (NULL == mesh_peer_2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh 
:(\n");
-    result = GNUNET_SYSERR;
-    return;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n");
-  }
-  t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected,
-                                 &peer_disconnected, (void *) &two);
-  GNUNET_MESH_peer_request_connect_by_type (t, 1);
-  test_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 5),
-                                    &do_connect_peer_1, (void*) cfg);
-}
-
-
-/**
- * Main
- */
-int
-main (int argc, char *argv[])
-{
-  if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-2",
-                                   "test_mesh.conf",
-                                   &run, NULL))
-    return 1;
-  return (result == GNUNET_OK) ? 0 : 1;
-}
-
-/* end of test_mesh_local_2.c */

Deleted: gnunet/src/mesh/test_mesh_local_traffic.c
===================================================================
--- gnunet/src/mesh/test_mesh_local_traffic.c   2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/mesh/test_mesh_local_traffic.c   2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,526 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/test_mesh_local_traffic.c
- * @brief test mesh local traffic: test of tunnels with just one peer
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_mesh_service.h"
-#include "gnunet_testing_lib.h"
-#include <gauger.h>
-
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
-
-#define TARGET 1000
-
-/**
- * DIFFERENT TESTS TO RUN
- */
-#define FWD 0
-#define BCK 1
-#define BOTH 2
-
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-struct test_traffic_message
-{
-  struct GNUNET_MessageHeader header;
-  uint32_t data GNUNET_PACKED;
-};
-
-GNUNET_NETWORK_STRUCT_END
-
-
-/** Which test to run, based on executable name */
-static int test;
-
-static int started;
-
-/** How many packets to send from root to leaf */
-static unsigned int to_send_fwd;
-
-/** How many packets to send from leaf to root */
-static unsigned int to_send_bck;
-
-static unsigned int sent_fwd = 0;
-
-static unsigned int got_fwd = 0;
-
-static unsigned int sent_bck = 0;
-
-static unsigned int got_bck = 0;
-
-static struct GNUNET_MESH_Handle *mesh_peer_1;
-
-static struct GNUNET_MESH_Handle *mesh_peer_2;
-
-static struct GNUNET_MESH_Tunnel *t_fwd;
-
-static struct GNUNET_MESH_Tunnel *t_bck;
-
-static unsigned int one = 1;
-
-static unsigned int two = 2;
-
-static int result = GNUNET_SYSERR;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
-
-static struct GNUNET_TIME_Absolute start_time;
-
-static struct GNUNET_TIME_Absolute end_time;
-
-static struct GNUNET_PeerIdentity peer_id;
-
-
-/**
- * Shutdown nicely
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
-  if (0 != abort_task)
-  {
-    GNUNET_SCHEDULER_cancel (abort_task);
-  }
-  if (NULL != t_fwd)
-  {
-    GNUNET_MESH_tunnel_destroy(t_fwd);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D1\n");
-  if (NULL != mesh_peer_1)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_1);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D2\n");
-  if (NULL != mesh_peer_2)
-  {
-    GNUNET_MESH_disconnect (mesh_peer_2);
-  }
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ABORT\n");
-  result = GNUNET_SYSERR;
-  abort_task = 0;
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-    shutdown_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  do_shutdown (cls, tc);
-}
-
-static void
-finish(void)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-    GNUNET_SCHEDULER_cancel(shutdown_task);
-  shutdown_task =  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                 &do_shutdown, NULL);
-}
-
-
-/**
- * Transmit ready callback.
- * 
- * @param cls Closure (peer number of peer sending the data).
- * @param size Buffer size.
- * @param buf Buffer.
- */
-static size_t
-tmt_rdy (void *cls, size_t size, void *buf)
-{
-  unsigned int peer_number = *(unsigned int *) cls;
-  struct GNUNET_MessageHeader *m = buf;
-  struct GNUNET_MESH_Tunnel *t;
-  struct test_traffic_message *msg = buf;
-  size_t msize = sizeof (struct test_traffic_message);
-  unsigned int *sent;
-  unsigned int target;
-  char *s;
-
-  if (0 == size || NULL == buf)
-    return 0;
-
-  if (1 == peer_number)
-  {
-    sent = &sent_fwd;
-    target = to_send_fwd;
-    t = t_fwd;
-    s = "FWD";
-  }
-  else if (2 == peer_number)
-  {
-    sent = &sent_bck;
-    target = to_send_bck;
-    t = t_bck;
-    s = "BCK";
-  }
-  else
-    GNUNET_abort();
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s data packet # %4u\n",
-              s, *sent);
-  GNUNET_assert (size >= msize);
-  if (GNUNET_YES == started)
-  {
-    (*sent)++;
-    if (target > *sent) {
-      GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         &peer_id, msize, &tmt_rdy, cls);
-    }
-  }
-  m->size = htons (msize);
-  m->type = htons (1);
-  msg->data = htonl (*sent - 1);
-  return msize;
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-               const struct GNUNET_PeerIdentity *sender,
-               const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  struct test_traffic_message *msg;
-  unsigned int *peer_number = cls;
-  unsigned int *got;
-  unsigned int target;
-
-  if (GNUNET_NO == started)
-  {
-    GNUNET_break (2 == *peer_number);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got initial data packet\n");
-    started = GNUNET_YES;
-    start_time = GNUNET_TIME_absolute_get();
-    if (FWD != test) // Send leaf -> root
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first BCK data\n");
-      GNUNET_MESH_notify_transmit_ready (t_bck, GNUNET_NO,
-                                        GNUNET_TIME_UNIT_FOREVER_REL,
-                                        NULL,
-                                        sizeof (struct test_traffic_message),
-                                        &tmt_rdy, &two);
-    }
-    if (BCK != test) // Send root -> leaf
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first FWD data\n");
-      GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO,
-                                        GNUNET_TIME_UNIT_FOREVER_REL,
-                                        &peer_id,
-                                        sizeof (struct test_traffic_message),
-                                        &tmt_rdy, &one);
-    }
-    return GNUNET_OK;
-  }
-
-  if (*peer_number == 1)
-  {
-    got = &got_bck;
-    target = to_send_bck;
-  }
-  else if (*peer_number == 2)
-  {
-    got = &got_fwd;
-    target = to_send_fwd;
-  }
-  else
-  {
-    GNUNET_abort();
-  }
-  msg = (struct test_traffic_message *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got data packet # %u [%u]\n",
-              ntohl (msg->data), *got + 1);
-  (*got)++;
-  if (target == *got)
-  {
-    if (to_send_bck == sent_bck && to_send_fwd == sent_fwd) {
-      end_time = GNUNET_TIME_absolute_get();
-      result = GNUNET_OK;
-      finish();
-    }
-    return GNUNET_OK;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-  shutdown_task =
-    GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shutdown,
-                                  NULL);
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
- */
-static void *
-inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                const struct GNUNET_PeerIdentity *initiator,
-                const struct GNUNET_ATS_Information *atsi)
-{
-  unsigned int id = *(unsigned int *) cls;
-
-  t_bck = tunnel;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming tunnel %p\n", 
tunnel);
-  if (id != 2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "received incoming tunnel on peer 1\n");
-    result = GNUNET_SYSERR;
-  }
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-             void *tunnel_ctx)
-{
-  unsigned int id = *(unsigned int *) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming tunnel closed\n");
-  if (id != 2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "received closing tunnel on peer 1\n");
-    result = GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * Method called whenever a peer has connected to the tunnel.
- *
- * @param cls Closure.
- * @param peer Peer identity of connected peer.
- */
-static void
-peer_connected (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer connected\n");
-  peer_id = *peer;
-  /* Force an inbound tunnel notification on peer 2 */
-  GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO, 
GNUNET_TIME_UNIT_FOREVER_REL,
-                                     peer, sizeof (struct 
test_traffic_message),
-                                     &tmt_rdy, &one);
-}
-
-
-/**
- * Method called whenever a peer has connected to the tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel was created to, NULL on timeout
- * @param atsi performance data for the connection
- */
-static void
-peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer disconnected\n");
-}
-
-
-/**
- * Handler array for traffic received on peer1
- */
-static struct GNUNET_MESH_MessageHandler handlers[] = {
-  {&data_callback, 1, sizeof (struct test_traffic_message)},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Handler array for traffic received on peer2 (none expected)
- */
-static struct GNUNET_MESH_MessageHandler handlers_null[] = { {NULL, 0, 0} };
-
-
-/**
- * Initialize framework and start test
- */
-static void
-run (void *cls, 
-     const struct GNUNET_CONFIGURATION_Handle *cfg,
-     struct GNUNET_TESTING_Peer *peer)
-{
-  static const GNUNET_MESH_ApplicationType app1[] = { 0 };
-  static const GNUNET_MESH_ApplicationType app2[] = { 1, 0 };
-
-  abort_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort,
-                                    NULL);
-  mesh_peer_1 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) &one,     /* cls */
-                                     NULL,      /* inbound new hndlr */
-                                     NULL,      /* inbound end hndlr */
-                                     /* traffic handlers */
-                                     test == FWD ? handlers_null : handlers,
-                                     app1);     /* apps offered */
-
-  mesh_peer_2 = GNUNET_MESH_connect (cfg,       /* configuration */
-                                     (void *) &two,     /* cls */
-                                     &inbound_tunnel,   /* inbound new hndlr */
-                                     &inbound_end,      /* inbound end hndlr */
-                                     handlers,          /* traffic handlers */
-                                     app2);     /* apps offered */
-  if (NULL == mesh_peer_1 || NULL == mesh_peer_2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
-    result = GNUNET_SYSERR;
-    return;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to mesh\n");
-  }
-  t_fwd = GNUNET_MESH_tunnel_create (mesh_peer_1, NULL, &peer_connected,
-                                     &peer_disconnected, (void *) &two);
-  GNUNET_MESH_peer_request_connect_by_type (t_fwd, 1);
-}
-
-
-/**
- * Main
- */
-int
-main (int argc, char *argv[])
-{
-  if (strstr (argv[0], "test_mesh_local_traffic_fwd") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FWD\n");
-    test = FWD;
-    to_send_fwd = TARGET;
-  }
-  else if (strstr (argv[0], "test_mesh_local_traffic_bck") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BCK\n");
-    test = BCK;
-    to_send_bck = TARGET;
-  }
-  else if (strstr (argv[0], "test_mesh_local_traffic_both") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BOTH\n");
-    test = BOTH;
-    to_send_bck = to_send_fwd = TARGET;
-  }
-  else
-  {
-    return 1;
-  }
-
-  if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-traffic",
-                                   "test_mesh.conf",
-                                   &run, NULL))
-    return 1;
-  if (result != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed.\nFWD expected: %u, Sent: %u, Got: %u\n",
-                to_send_fwd, sent_fwd, got_fwd);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "BCK expected: %u, Sent: %u, Got: %u\n",
-                to_send_bck, sent_bck, got_bck);
-    return 1;
-  }
-  else
-  {
-    struct GNUNET_TIME_Relative total_time;
-    unsigned int total_traffic;
-    char *name;
-
-    total_traffic = BOTH == test ? 2 * TARGET : TARGET;
-    switch (test)
-    {
-      case FWD:
-        name = "Local traffic Root to Leaf";
-        break;
-      case BCK:
-        name = "Local traffic Leaf to Root";
-        break;
-      case BOTH:
-        name = "Local traffic bidirectional";
-        break;
-      default:
-        GNUNET_assert (0);
-    }
-
-    total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
-    FPRINTF (stderr, "\nTest time %llu ms\n",
-             (unsigned long long) total_time.rel_value);
-    FPRINTF (stderr, "Test payload bandwidth: %f kb/s\n",
-             total_traffic * 4.0 / total_time.rel_value); // 4bytes * kb/ms
-    FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
-             total_traffic * 1000.0 / total_time.rel_value); // 1000 packets * 
ms
-    GAUGER ("MESH",
-            name,
-            total_traffic * 1000.0 / total_time.rel_value,
-            "packets/s");
-  }
-  return 0;
-}
-
-/* end of test_mesh_local_traffic.c */

Deleted: gnunet/src/mesh/test_mesh_small.c
===================================================================
--- gnunet/src/mesh/test_mesh_small.c   2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/mesh/test_mesh_small.c   2013-06-28 14:34:55 UTC (rev 27681)
@@ -1,1003 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file mesh/test_mesh_small.c
- *
- * @brief Test for the mesh service: retransmission of traffic.
- */
-#include <stdio.h>
-#include "platform.h"
-#include "mesh_test_lib.h"
-#include "gnunet_mesh_service.h"
-#include <gauger.h>
-
-
-/**
- * How namy messages to send
- */
-#define TOTAL_PACKETS 1000
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
-
-/**
- * Time to wait for stuff that should be rather fast
- */
-#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
-
-/**
- * DIFFERENT TESTS TO RUN
- */
-#define SETUP 0
-#define UNICAST 1
-#define MULTICAST 2
-#define SPEED 3
-#define SPEED_ACK 4
-#define SPEED_MIN 5
-#define SPEED_NOBUF 6
-#define P2P_SIGNAL 10
-
-/**
- * Which test are we running?
- */
-static int test;
-
-/**
- * String with test name
- */
-char *test_name;
-
-/**
- * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
- */
-static int test_backwards = GNUNET_NO;
-
-/**
- * How many events have happened
- */
-static int ok;
-
- /**
-  * Each peer is supposed to generate the following callbacks:
-  * 1 incoming tunnel (@dest)
-  * 1 connected peer (@orig)
-  * 1 received data packet (@dest)
-  * 1 received data packet (@orig)
-  * 1 received tunnel destroy (@dest)
-  * _________________________________
-  * 5 x ok expected per peer
-  */
-int ok_goal;
-
-
-/**
- * Size of each test packet
- */
-size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
-
-/**
- * Operation to get peer ids.
- */
-struct GNUNET_TESTBED_Operation *t_op[3];
-
-/**
- * Peer ids.
- */
-struct GNUNET_PeerIdentity *p_id[3];
-
-/**
- * Peer ids counter.
- */
-unsigned int p_ids;
-
-/**
- * Is the setup initialized?
- */
-static int initialized;
-
-/**
- * Peers that have been connected
- */
-static int peers_in_tunnel;
-
-/**
- * Peers that have responded
- */
-static int peers_responded;
-
-/**
- * Number of payload packes sent
- */
-static int data_sent;
-
-/**
- * Number of payload packets received
- */
-static int data_received;
-
-/**
- * Number of payload packed explicitly (app level) acknowledged
- */
-static int data_ack;
-
-/**
- * Total number of currently running peers.
- */
-static unsigned long long peers_running;
-
-/**
- * Test context (to shut down).
- */
-struct GNUNET_MESH_TEST_Context *test_ctx;
-
-/**
- * Task called to disconnect peers.
- */
-static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-/**
- * Task To perform tests
- */
-static GNUNET_SCHEDULER_TaskIdentifier test_task;
-
-/**
- * Task called to shutdown test.
- */
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
-
-/**
- * Mesh handle for the root peer
- */
-static struct GNUNET_MESH_Handle *h1;
-
-/**
- * Mesh handle for the first leaf peer
- */
-static struct GNUNET_MESH_Handle *h2;
-
-/**
- * Mesh handle for the second leaf peer
- */
-static struct GNUNET_MESH_Handle *h3;
-
-/**
- * Tunnel handle for the root peer
- */
-static struct GNUNET_MESH_Tunnel *t;
-
-/**
- * Tunnel handle for the first leaf peer
- */
-static struct GNUNET_MESH_Tunnel *incoming_t;
-
-/**
- * Tunnel handle for the second leaf peer
- */
-static struct GNUNET_MESH_Tunnel *incoming_t2;
-
-/**
- * Time we started the data transmission (after tunnel has been established
- * and initilized).
- */
-static struct GNUNET_TIME_Absolute start_time;
-
-
-/**
- * Show the results of the test (banwidth acheived) and log them to GAUGER
- */
-static void
-show_end_data (void)
-{
-  static struct GNUNET_TIME_Absolute end_time;
-  static struct GNUNET_TIME_Relative total_time;
-
-  end_time = GNUNET_TIME_absolute_get();
-  total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
-  FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
-  FPRINTF (stderr, "Test time %llu ms\n",
-            (unsigned long long) total_time.rel_value);
-  FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
-            4 * TOTAL_PACKETS * 1.0 / total_time.rel_value); // 4bytes * ms
-  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
-            TOTAL_PACKETS * 1000.0 / total_time.rel_value); // packets * ms
-  GAUGER ("MESH", test_name,
-          TOTAL_PACKETS * 1000.0 / total_time.rel_value,
-          "packets/s");
-}
-
-
-/**
- * Shut down peergroup, clean up.
- * 
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
-  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
-}
-
-
-/**
- * Disconnect from mesh services af all peers, call shutdown.
- * 
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
-{
-  long line = (long) cls;
-  unsigned int i;
-
-  for (i = 0; i < 3; i++)
-    if (NULL != t_op[i])
-    {
-      GNUNET_TESTBED_operation_done (t_op[i]);
-      t_op[i] = NULL;
-    }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "disconnecting mesh service of peers, called from line %ld\n",
-              line);
-  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  if (NULL != t)
-  {
-    GNUNET_MESH_tunnel_destroy (t);
-    t = NULL;
-  }
-  if (NULL != incoming_t)
-  {
-    GNUNET_MESH_tunnel_destroy (incoming_t);
-    incoming_t = NULL;
-  }
-  if (NULL != incoming_t2)
-  {
-    GNUNET_MESH_tunnel_destroy (incoming_t2);
-    incoming_t2 = NULL;
-  }
-  GNUNET_MESH_TEST_cleanup (test_ctx);
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_handle);
-  }
-  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
-}
-
-
-/**
- * Abort test: schedule disconnect and shutdown immediately
- * 
- * @param line Line in the code the abort is requested from (__LINE__).
- */
-void
-abort_test (long line)
-{
-  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_mesh_peers,
-                                                  (void *) line);
-}
-
-/**
- * Transmit ready callback.
- * 
- * @param cls Closure (message type).
- * @param size Size of the tranmist buffer.
- * @param buf Pointer to the beginning of the buffer.
- * 
- * @return Number of bytes written to buf.
- */
-static size_t
-tmt_rdy (void *cls, size_t size, void *buf);
-
-
-/**
- * Task to schedule a new data transmission.
- * 
- * @param cls Closure (peer #).
- * @param tc Task Context.
- */
-static void
-data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_MESH_TransmitHandle *th;
-  struct GNUNET_MESH_Tunnel *tunnel;
-  struct GNUNET_PeerIdentity *destination;
-
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
-  if (GNUNET_YES == test_backwards)
-  {
-    tunnel = incoming_t;
-    destination = p_id[0];
-  }
-  else
-  {
-    tunnel = t;
-    destination = p_id[2];
-  }
-  th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
-                                          GNUNET_TIME_UNIT_FOREVER_REL,
-                                          destination,
-                                          size_payload,
-                                          &tmt_rdy, (void *) 1L);
-  if (NULL == th)
-  {
-    unsigned long i = (unsigned long) cls;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
-    if (0 == i)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
-                                    &data_task, (void *)1UL);
-    }
-    else
-    {
-      i++;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
-                                      GNUNET_TIME_UNIT_MILLISECONDS,
-                                      i),
-                                    &data_task, (void *)i);
-    }
-  }
-}
-
-
-/**
- * Transmit ready callback
- *
- * @param cls Closure (message type).
- * @param size Size of the buffer we have.
- * @param buf Buffer to copy data to.
- */
-size_t
-tmt_rdy (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *msg = buf;
-  uint32_t *data;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " tmt_rdy called\n");
-  if (size < size_payload || NULL == buf)
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "size %u, buf %p, data_sent %u, data_received %u\n",
-                size,
-                buf,
-                data_sent,
-                data_received);
-    return 0;
-  }
-  msg->size = htons (size);
-  msg->type = htons ((long) cls);
-  data = (uint32_t *) &msg[1];
-  *data = htonl (data_sent);
-  if (SPEED == test && GNUNET_YES == initialized)
-  {
-    data_sent++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Sent packet %d\n", data_sent);
-    if (data_sent < TOTAL_PACKETS)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Scheduling packet %d\n", data_sent + 1);
-      GNUNET_SCHEDULER_add_now(&data_task, NULL);
-    }
-  }
-  return size_payload;
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end
- * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
-               const struct GNUNET_PeerIdentity *sender,
-               const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  long client = (long) cls;
-  long expected_target_client;
-  uint32_t *data;
-
-  ok++;
-
-  if ((ok % 20) == 0)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    {
-      GNUNET_SCHEDULER_cancel (disconnect_task);
-    }
-    disconnect_task =
-              GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
-                                            (void *) __LINE__);
-  }
-
-  switch (client)
-  {
-  case 0L:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
-    peers_responded++;
-    if (test == MULTICAST && peers_responded < 2)
-      return GNUNET_OK;
-    break;
-  case 3L:
-  case 4L:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Leaf client %li got a message.\n",
-                client);
-    client = 4L;
-    break;
-  default:
-    GNUNET_assert (0);
-    break;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
-  data = (uint32_t *) &message[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
-  if (SPEED == test && GNUNET_YES == test_backwards)
-  {
-    expected_target_client = 0L;
-  }
-  else
-  {
-    expected_target_client = 4L;
-  }
-
-  if (GNUNET_NO == initialized)
-  {
-    initialized = GNUNET_YES;
-    start_time = GNUNET_TIME_absolute_get ();
-    if (SPEED == test)
-    {
-      GNUNET_assert (4L == client);
-      GNUNET_SCHEDULER_add_now (&data_task, NULL);
-      return GNUNET_OK;
-    }
-  }
-
-  if (client == expected_target_client) // Normally 3 or 4
-  {
-    data_received++;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                " received data %u\n", data_received);
-    if (SPEED != test || (ok_goal - 2) == ok)
-    {
-      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
-                                        GNUNET_TIME_UNIT_FOREVER_REL, sender,
-                                               size_payload,
-                                        &tmt_rdy, (void *) 1L);
-      return GNUNET_OK;
-    }
-    else
-    {
-      if (data_received < TOTAL_PACKETS)
-        return GNUNET_OK;
-    }
-  }
-  else // Normally 0
-  {
-    if (test == SPEED_ACK || test == SPEED)
-    {
-      data_ack++;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              " received ack %u\n", data_ack);
-      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
-                                        GNUNET_TIME_UNIT_FOREVER_REL, sender,
-                                               size_payload,
-                                        &tmt_rdy, (void *) 1L);
-      if (data_ack < TOTAL_PACKETS && SPEED != test)
-        return GNUNET_OK;
-      if (ok == 2 && SPEED == test)
-        return GNUNET_OK;
-      show_end_data();
-    }
-    if (test == P2P_SIGNAL)
-    {
-      GNUNET_MESH_tunnel_destroy (incoming_t);
-      incoming_t = NULL;
-    }
-    else
-    {
-      GNUNET_MESH_tunnel_destroy (t);
-      t = NULL;
-    }
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-  disconnect_task =
-        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
-                                      (void *) __LINE__);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Handlers, for diverse services
- */
-static struct GNUNET_MESH_MessageHandler handlers[] = {
-  {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel
- *         (can be NULL -- that's not an error)
- */
-static void *
-incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                 const struct GNUNET_PeerIdentity *initiator,
-                 const struct GNUNET_ATS_Information *atsi)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming tunnel from %s to peer %d\n",
-              GNUNET_i2s (initiator), (long) cls);
-  ok++;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-  if ((long) cls == 4L)
-    incoming_t = tunnel;
-  else if ((long) cls == 3L)
-    incoming_t2 = tunnel;
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Incoming tunnel for unknown client %lu\n", (long) cls);
-    GNUNET_break(0);
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-  disconnect_task =
-        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
-                                      (void *) __LINE__);
-
-  return NULL;
-}
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-                void *tunnel_ctx)
-{
-  long i = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming tunnel disconnected at peer %d\n",
-              i);
-  if (4L == i)
-  {
-    ok++;
-    incoming_t = NULL;
-  }
-  else if (3L == i)
-  {
-    ok++;
-    incoming_t2 = NULL;
-  }
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Unknown peer! %d\n", i);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-  peers_in_tunnel--;
-  if (peers_in_tunnel > 0)
-    return;
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
-                                              (void *) __LINE__);
-
-  return;
-}
-
-
-/**
- * Method called whenever a tunnel falls apart.
- *
- * @param cls closure
- * @param peer peer identity the tunnel stopped working with
- */
-static void
-dh (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "peer %s disconnected\n",
-              GNUNET_i2s (peer));
-  if (P2P_SIGNAL == test)
-  {
-    ok ++;
-    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    {
-      GNUNET_SCHEDULER_cancel (disconnect_task);
-    }
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
-                                                (void *) __LINE__);
-  }
-  return;
-}
-
-
-/**
- * Method called whenever a peer connects to a tunnel.
- *
- * @param cls closure
- * @param peer peer identity the tunnel was created to, NULL on timeout
- * @param atsi performance data for the connection
- */
-static void
-ch (void *cls, const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_ATS_Information *atsi)
-{
-  long i = (long) cls;
-
-  struct GNUNET_PeerIdentity *dest;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "%ld peer %s connected\n", i, GNUNET_i2s (peer));
-
-  if (0 == memcmp (p_id[2], peer, sizeof (struct GNUNET_PeerIdentity)) &&
-      i == 0L)
-  {
-    ok++;
-  }
-  if (test == MULTICAST &&
-      0 == memcmp (p_id[1], peer, sizeof (struct GNUNET_PeerIdentity)) &&
-      i == 0L)
-  {
-    ok++;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-  switch (test)
-  {
-    case UNICAST:
-    case P2P_SIGNAL:
-    case SPEED:
-    case SPEED_ACK:
-      // incoming_t is NULL unless we send a relevant data packet
-      dest = p_id[2];
-      break;
-    case MULTICAST:
-      peers_in_tunnel++;
-      if (peers_in_tunnel < 2)
-        return;
-      dest = NULL;
-      break;
-    default:
-      GNUNET_assert (0);
-      return;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task =
-        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers,
-                                      (void *) __LINE__);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Sending data initializer...\n");
-    peers_responded = 0;
-    data_ack = 0;
-    data_received = 0;
-    data_sent = 0;
-    GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
-                                       GNUNET_TIME_UNIT_FOREVER_REL, dest,
-                                           size_payload,
-                                       &tmt_rdy, (void *) 1L);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Disconnect already run?\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Aborting...\n");
-  }
-  return;
-}
-
-
-/**
- * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES.
- * 
- * Testcase continues when the root receives confirmation of connected peers,
- * on callback funtion ch.
- * 
- * @param cls Closure (unsued).
- * @param tc Task Context.
- */
-static void
-do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n");
-  GNUNET_MESH_peer_request_connect_add (t, p_id[2]);
-
-  if (test == MULTICAST)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "add peer 3\n");
-    GNUNET_MESH_peer_request_connect_add (t, p_id[1]);
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "schedule timeout in TIMEOUT\n");
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
-                                                  &disconnect_mesh_peers,
-                                                  (void *) __LINE__);
-}
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cls the closure from GNUNET_TETSBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed;
- *             NULL if the operation is successfull
- */
-void
-pi_cb (void *cls,
-       struct GNUNET_TESTBED_Operation *op,
-       const struct GNUNET_TESTBED_PeerInformation *pinfo,
-       const char *emsg)
-{
-  long i = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
-  if (NULL == pinfo || NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
-    abort_test (__LINE__);
-    return;
-  }
-  p_id[i] = pinfo->result.id;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  id: %s\n", GNUNET_i2s (p_id[i]));
-  p_ids++;
-  if ((MULTICAST == test && p_ids < 3) || p_ids < 2)
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
-  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                            &do_test, NULL);
-}
-
-/**
- * test main: start test when all peers are connected
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param peers Array of peers.
- * @param meshes Handle to each of the MESHs of the peers.
- */
-static void
-tmain (void *cls,
-       struct GNUNET_MESH_TEST_Context *ctx,
-       unsigned int num_peers,
-       struct GNUNET_TESTBED_Peer **peers,
-       struct GNUNET_MESH_Handle **meshes)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
-  ok = 0;
-  test_ctx = ctx;
-  peers_running = num_peers;
-  h1 = meshes[0];
-  h2 = meshes[num_peers - 1];
-  t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 0L);
-  if (SPEED_MIN == test)
-  {
-    GNUNET_MESH_tunnel_speed_min(t);
-    test = SPEED;
-  }
-  if (SPEED_NOBUF == test)
-  {
-    GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
-    test = SPEED;
-  }
-  peers_in_tunnel = 0;
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_mesh_peers,
-                                                  (void *) __LINE__);
-  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                                  &shutdown_task, NULL);
-  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
-                                                 GNUNET_TESTBED_PIT_IDENTITY,
-                                                 &pi_cb, (void *) 0L);
-  t_op[2] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
-                                                 GNUNET_TESTBED_PIT_IDENTITY,
-                                                 &pi_cb, (void *) 2L);
-  if (MULTICAST == test)
-  {
-    h3 = meshes[num_peers - 2];
-    t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 2],
-                                                   GNUNET_TESTBED_PIT_IDENTITY,
-                                                   &pi_cb, (void *) 1L);
-  }
-  else
-  {
-    t_op[1] = NULL;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
-}
-
-
-/**
- * Main: start test
- */
-int
-main (int argc, char *argv[])
-{
-  initialized = GNUNET_NO;
-
-  GNUNET_log_setup ("test", "DEBUG", NULL);
-  
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
-  if (strstr (argv[0], "test_mesh_small_unicast") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNICAST\n");
-    test = UNICAST;
-    test_name = "unicast";
-    ok_goal = 5;
-  }
-  else if (strstr (argv[0], "test_mesh_small_multicast") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MULTICAST\n");
-    test = MULTICAST;
-    test_name = "multicast";
-    ok_goal = 10;
-  }
-  else if (strstr (argv[0], "test_mesh_small_signal") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
-    test = P2P_SIGNAL;
-    test_name = "signal";
-    ok_goal = 5;
-  }
-  else if (strstr (argv[0], "test_mesh_small_speed_ack") != NULL)
-  {
-   /* Each peer is supposed to generate the following callbacks:
-    * 1 incoming tunnel (@dest)
-    * 1 connected peer (@orig)
-    * TOTAL_PACKETS received data packet (@dest)
-    * TOTAL_PACKETS received data packet (@orig)
-    * 1 received tunnel destroy (@dest)
-    * _________________________________
-    * 5 x ok expected per peer
-    */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
-    test = SPEED_ACK;
-    test_name = "speed ack";
-    ok_goal = TOTAL_PACKETS * 2 + 3;
-  }
-  else if (strstr (argv[0], "test_mesh_small_speed") != NULL)
-  {
-   /* Each peer is supposed to generate the following callbacks:
-    * 1 incoming tunnel (@dest)
-    * 1 connected peer (@orig)
-    * 1 initial packet (@dest)
-    * TOTAL_PACKETS received data packet (@dest)
-    * 1 received data packet (@orig)
-    * 1 received tunnel destroy (@dest)
-    * _________________________________
-    */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
-    ok_goal = TOTAL_PACKETS + 5;
-    if (strstr (argv[0], "_min") != NULL)
-    {
-      test = SPEED_MIN;
-      test_name = "speed min";
-    }
-    else if (strstr (argv[0], "_nobuf") != NULL)
-    {
-      test = SPEED_NOBUF;
-      test_name = "speed nobuf";
-    }
-    else
-    {
-      test = SPEED;
-      test_name = "speed";
-    }
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
-    test = SETUP;
-    ok_goal = 0;
-  }
-
-  if (strstr (argv[0], "backwards") != NULL)
-  {
-    char *aux;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
-    test_backwards = GNUNET_YES;
-    aux = GNUNET_malloc (32);
-    sprintf (aux, "backwards %s", test_name);
-    test_name = aux;
-  }
-
-  p_ids = 0;
-  GNUNET_MESH_TEST_run ("test_mesh_small",
-                        "test_mesh_small.conf",
-                        5,
-                        &tmain,
-                        NULL,
-                        &incoming_tunnel,
-                        &tunnel_cleaner,
-                        handlers,
-                        NULL);
-
-  if (ok_goal > ok)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "FAILED! (%d/%d)\n", ok, ok_goal);
-    return 1;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
-  return 0;
-}
-
-/* end of test_mesh_small.c */

Copied: gnunet/src/mesh/test_mesh_small.c (from rev 27670, 
gnunet/src/mesh/test_mesh2_small.c)
===================================================================
--- gnunet/src/mesh/test_mesh_small.c                           (rev 0)
+++ gnunet/src/mesh/test_mesh_small.c   2013-06-28 14:34:55 UTC (rev 27681)
@@ -0,0 +1,833 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file mesh/test_mesh_small.c
+ *
+ * @brief Test for the mesh service: retransmission of traffic.
+ */
+#include <stdio.h>
+#include "platform.h"
+#include "mesh_test_lib.h"
+#include "gnunet_mesh_service.h"
+#include <gauger.h>
+
+
+/**
+ * How namy messages to send
+ */
+#define TOTAL_PACKETS 1000
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * Time to wait for stuff that should be rather fast
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
+
+/**
+ * DIFFERENT TESTS TO RUN
+ */
+#define SETUP 0
+#define FORWARD 1
+#define SPEED 3
+#define SPEED_ACK 4
+#define SPEED_NOBUF 6
+#define P2P_SIGNAL 10
+
+/**
+ * Which test are we running?
+ */
+static int test;
+
+/**
+ * String with test name
+ */
+char *test_name;
+
+/**
+ * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
+ */
+static int test_backwards = GNUNET_NO;
+
+/**
+ * How many events have happened
+ */
+static int ok;
+
+ /**
+  * Each peer is supposed to generate the following callbacks:
+  * 1 incoming tunnel (@dest)
+  * 1 connected peer (@orig)
+  * 1 received data packet (@dest)
+  * 1 received data packet (@orig)
+  * 1 received tunnel destroy (@dest)
+  * _________________________________
+  * 5 x ok expected per peer
+  */
+int ok_goal;
+
+
+/**
+ * Size of each test packet
+ */
+size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
+
+/**
+ * Operation to get peer ids.
+ */
+struct GNUNET_TESTBED_Operation *t_op[2];
+
+/**
+ * Peer ids.
+ */
+struct GNUNET_PeerIdentity *p_id[2];
+
+/**
+ * Peer ids counter.
+ */
+unsigned int p_ids;
+
+/**
+ * Is the setup initialized?
+ */
+static int initialized;
+
+/**
+ * Peers that have responded
+ */
+static int peers_responded;
+
+/**
+ * Number of payload packes sent
+ */
+static int data_sent;
+
+/**
+ * Number of payload packets received
+ */
+static int data_received;
+
+/**
+ * Number of payload packed explicitly (app level) acknowledged
+ */
+static int data_ack;
+
+/**
+ * Total number of currently running peers.
+ */
+static unsigned long long peers_running;
+
+/**
+ * Test context (to shut down).
+ */
+struct GNUNET_MESH_TEST_Context *test_ctx;
+
+/**
+ * Task called to disconnect peers.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+/**
+ * Task To perform tests
+ */
+static GNUNET_SCHEDULER_TaskIdentifier test_task;
+
+/**
+ * Task called to shutdown test.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
+
+/**
+ * Mesh handle for the root peer
+ */
+static struct GNUNET_MESH_Handle *h1;
+
+/**
+ * Mesh handle for the first leaf peer
+ */
+static struct GNUNET_MESH_Handle *h2;
+
+/**
+ * Tunnel handle for the root peer
+ */
+static struct GNUNET_MESH_Tunnel *t;
+
+/**
+ * Tunnel handle for the first leaf peer
+ */
+static struct GNUNET_MESH_Tunnel *incoming_t;
+
+/**
+ * Time we started the data transmission (after tunnel has been established
+ * and initilized).
+ */
+static struct GNUNET_TIME_Absolute start_time;
+
+
+/**
+ * Show the results of the test (banwidth acheived) and log them to GAUGER
+ */
+static void
+show_end_data (void)
+{
+  static struct GNUNET_TIME_Absolute end_time;
+  static struct GNUNET_TIME_Relative total_time;
+
+  end_time = GNUNET_TIME_absolute_get();
+  total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
+  FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
+  FPRINTF (stderr, "Test time %llu ms\n",
+            (unsigned long long) total_time.rel_value);
+  FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
+            4 * TOTAL_PACKETS * 1.0 / total_time.rel_value); // 4bytes * ms
+  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
+            TOTAL_PACKETS * 1000.0 / total_time.rel_value); // packets * ms
+  GAUGER ("MESH", test_name,
+          TOTAL_PACKETS * 1000.0 / total_time.rel_value,
+          "packets/s");
+}
+
+
+/**
+ * Shut down peergroup, clean up.
+ * 
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
+  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
+}
+
+
+/**
+ * Disconnect from mesh services af all peers, call shutdown.
+ * 
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
+{
+  long line = (long) cls;
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "disconnecting mesh service of peers, called from line %ld\n",
+              line);
+  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  for (i = 0; i < 2; i++)
+  {
+    GNUNET_TESTBED_operation_done (t_op[i]);
+  }
+  if (NULL != t)
+  {
+    GNUNET_MESH_tunnel_destroy (t);
+    t = NULL;
+  }
+  if (NULL != incoming_t)
+  {
+    GNUNET_MESH_tunnel_destroy (incoming_t);
+    incoming_t = NULL;
+  }
+  GNUNET_MESH_TEST_cleanup (test_ctx);
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_handle);
+  }
+  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+
+/**
+ * Abort test: schedule disconnect and shutdown immediately
+ * 
+ * @param line Line in the code the abort is requested from (__LINE__).
+ */
+static void
+abort_test (long line)
+{
+  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
+                                                (void *) line);
+  }
+}
+
+/**
+ * Transmit ready callback.
+ * 
+ * @param cls Closure (message type).
+ * @param size Size of the tranmist buffer.
+ * @param buf Pointer to the beginning of the buffer.
+ * 
+ * @return Number of bytes written to buf.
+ */
+static size_t
+tmt_rdy (void *cls, size_t size, void *buf);
+
+
+/**
+ * Task to schedule a new data transmission.
+ * 
+ * @param cls Closure (peer #).
+ * @param tc Task Context.
+ */
+static void
+data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_MESH_TransmitHandle *th;
+  struct GNUNET_MESH_Tunnel *tunnel;
+
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
+  if (GNUNET_YES == test_backwards)
+  {
+    tunnel = incoming_t;
+  }
+  else
+  {
+    tunnel = t;
+  }
+  th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
+                                          GNUNET_TIME_UNIT_FOREVER_REL,
+                                          size_payload, &tmt_rdy, (void *) 1L);
+  if (NULL == th)
+  {
+    unsigned long i = (unsigned long) cls;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
+    if (0 == i)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
+                                    &data_task, (void *)1UL);
+    }
+    else
+    {
+      i++;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
+                                      GNUNET_TIME_UNIT_MILLISECONDS,
+                                      i),
+                                    &data_task, (void *)i);
+    }
+  }
+}
+
+
+/**
+ * Transmit ready callback
+ *
+ * @param cls Closure (message type).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+size_t
+tmt_rdy (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *msg = buf;
+  uint32_t *data;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " tmt_rdy called\n");
+  if (size < size_payload || NULL == buf)
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "size %u, buf %p, data_sent %u, data_received %u\n",
+                size,
+                buf,
+                data_sent,
+                data_received);
+    return 0;
+  }
+  msg->size = htons (size);
+  msg->type = htons ((long) cls);
+  data = (uint32_t *) &msg[1];
+  *data = htonl (data_sent);
+  if (SPEED == test && GNUNET_YES == initialized)
+  {
+    data_sent++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Sent packet %d\n", data_sent);
+    if (data_sent < TOTAL_PACKETS)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Scheduling packet %d\n", data_sent + 1);
+      GNUNET_SCHEDULER_add_now(&data_task, NULL);
+    }
+  }
+  return size_payload;
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_MESH_connect)
+ * @param tunnel connection to the other end
+ * @param tunnel_ctx place to store local state associated with the tunnel
+ * @param message the actual message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx,
+               const struct GNUNET_MessageHeader *message)
+{
+  long client = (long) cls;
+  long expected_target_client;
+  uint32_t *data;
+
+  ok++;
+
+  GNUNET_MESH_receive_done (tunnel);
+
+  if ((ok % 20) == 0)
+  {
+    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    {
+      GNUNET_SCHEDULER_cancel (disconnect_task);
+      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                      &disconnect_mesh_peers,
+                                                      (void *) __LINE__);
+    }
+  }
+
+  switch (client)
+  {
+  case 0L:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
+    peers_responded++;
+    break;
+  case 4L:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Leaf client %li got a message.\n",
+                client);
+    client = 4L;
+    break;
+  default:
+    GNUNET_assert (0);
+    break;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
+  data = (uint32_t *) &message[1];
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
+  if (SPEED == test && GNUNET_YES == test_backwards)
+  {
+    expected_target_client = 0L;
+  }
+  else
+  {
+    expected_target_client = 4L;
+  }
+
+  if (GNUNET_NO == initialized)
+  {
+    initialized = GNUNET_YES;
+    start_time = GNUNET_TIME_absolute_get ();
+    if (SPEED == test)
+    {
+      GNUNET_assert (4L == client);
+      GNUNET_SCHEDULER_add_now (&data_task, NULL);
+      return GNUNET_OK;
+    }
+  }
+
+  if (client == expected_target_client) // Normally 3 or 4
+  {
+    data_received++;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                " received data %u\n", data_received);
+    if (SPEED != test || (ok_goal - 2) == ok)
+    {
+      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         size_payload, &tmt_rdy, (void *) 1L);
+      return GNUNET_OK;
+    }
+    else
+    {
+      if (data_received < TOTAL_PACKETS)
+        return GNUNET_OK;
+    }
+  }
+  else // Normally 0
+  {
+    if (test == SPEED_ACK || test == SPEED)
+    {
+      data_ack++;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              " received ack %u\n", data_ack);
+      GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         size_payload, &tmt_rdy, (void *) 1L);
+      if (data_ack < TOTAL_PACKETS && SPEED != test)
+        return GNUNET_OK;
+      if (ok == 2 && SPEED == test)
+        return GNUNET_OK;
+      show_end_data();
+    }
+    if (test == P2P_SIGNAL)
+    {
+      GNUNET_MESH_tunnel_destroy (incoming_t);
+      incoming_t = NULL;
+    }
+    else
+    {
+      GNUNET_MESH_tunnel_destroy (t);
+      t = NULL;
+    }
+  }
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                    &disconnect_mesh_peers,
+                                                    (void *) __LINE__);
+  }
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handlers, for diverse services
+ */
+static struct GNUNET_MESH_MessageHandler handlers[] = {
+  {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * Method called whenever another peer has added us to a tunnel
+ * the other peer initiated.
+ *
+ * @param cls Closure.
+ * @param tunnel New handle to the tunnel.
+ * @param initiator Peer that started the tunnel.
+ * @param port Port this tunnels is connected to.
+ * @return Initial tunnel context for the tunnel
+ *         (can be NULL -- that's not an error).
+ */
+static void *
+incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
+                 const struct GNUNET_PeerIdentity *initiator,
+                 uint32_t port)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming tunnel from %s to peer %d\n",
+              GNUNET_i2s (initiator), (long) cls);
+  ok++;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+  if ((long) cls == 4L)
+    incoming_t = tunnel;
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Incoming tunnel for unknown client %lu\n", (long) cls);
+    GNUNET_break(0);
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                    &disconnect_mesh_peers,
+                                                    (void *) __LINE__);
+  }
+
+  return NULL;
+}
+
+/**
+ * Function called whenever an inbound tunnel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from GNUNET_MESH_connect)
+ * @param tunnel connection to the other end (henceforth invalid)
+ * @param tunnel_ctx place where local state associated
+ *                   with the tunnel is stored
+ */
+static void
+tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
+                void *tunnel_ctx)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming tunnel disconnected at peer %d\n",
+              i);
+  if (4L == i)
+  {
+    ok++;
+    incoming_t = NULL;
+  }
+  else if (0L == i && P2P_SIGNAL == test)
+  {
+    ok ++;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Unknown peer! %d\n", i);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers,
+                                                (void *) __LINE__);
+  }
+
+  return;
+}
+
+
+/**
+ * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES.
+ * 
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ * 
+ * @param cls Closure (unsued).
+ * @param tc Task Context.
+ */
+static void
+do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n");
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "schedule timeout in TIMEOUT\n");
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  }
+  t = GNUNET_MESH_tunnel_create (h1, NULL, p_id[1], 1);
+  if (SPEED_NOBUF == test)
+  {
+    GNUNET_MESH_tunnel_buffer(t, GNUNET_NO);
+    test = SPEED;
+  }
+
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_mesh_peers,
+                                                  (void *) __LINE__);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending data initializer...\n");
+  peers_responded = 0;
+  data_ack = 0;
+  data_received = 0;
+  data_sent = 0;
+  GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL, 
+                                     size_payload, &tmt_rdy, (void *) 1L);
+}
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed;
+ *             NULL if the operation is successfull
+ */
+static void
+pi_cb (void *cls,
+       struct GNUNET_TESTBED_Operation *op,
+       const struct GNUNET_TESTBED_PeerInformation *pinfo,
+       const char *emsg)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
+
+  if (NULL == pinfo || NULL != emsg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
+    abort_test (__LINE__);
+    return;
+  }
+  p_id[i] = pinfo->result.id;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  id: %s\n", GNUNET_i2s (p_id[i]));
+  p_ids++;
+  if (p_ids < 2)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
+  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                            &do_test, NULL);
+}
+
+/**
+ * test main: start test when all peers are connected
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param peers Array of peers.
+ * @param meshes Handle to each of the MESHs of the peers.
+ */
+static void
+tmain (void *cls,
+       struct GNUNET_MESH_TEST_Context *ctx,
+       unsigned int num_peers,
+       struct GNUNET_TESTBED_Peer **peers,
+       struct GNUNET_MESH_Handle **meshes)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
+  ok = 0;
+  test_ctx = ctx;
+  peers_running = num_peers;
+  h1 = meshes[0];
+  h2 = meshes[num_peers - 1];
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_mesh_peers,
+                                                  (void *) __LINE__);
+  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                  &shutdown_task, NULL);
+  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb, (void *) 0L);
+  t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb, (void *) 1L);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
+}
+
+
+/**
+ * Main: start test
+ */
+int
+main (int argc, char *argv[])
+{
+  initialized = GNUNET_NO;
+  uint32_t ports[2];
+
+  GNUNET_log_setup ("test", "DEBUG", NULL);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
+  if (strstr (argv[0], "_small_forward") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
+    test = FORWARD;
+    test_name = "unicast2";
+    ok_goal = 4;
+  }
+  else if (strstr (argv[0], "_small_signal") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
+    test = P2P_SIGNAL;
+    test_name = "signal2";
+    ok_goal = 4;
+  }
+  else if (strstr (argv[0], "_small_speed_ack") != NULL)
+  {
+   /* Each peer is supposed to generate the following callbacks:
+    * 1 incoming tunnel (@dest)
+    * TOTAL_PACKETS received data packet (@dest)
+    * TOTAL_PACKETS received data packet (@orig)
+    * 1 received tunnel destroy (@dest)
+    * _________________________________
+    * 5 x ok expected per peer
+    */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
+    test = SPEED_ACK;
+    test_name = "speed2 ack";
+    ok_goal = TOTAL_PACKETS * 2 + 2;
+  }
+  else if (strstr (argv[0], "_small_speed") != NULL)
+  {
+   /* Each peer is supposed to generate the following callbacks:
+    * 1 incoming tunnel (@dest)
+    * 1 initial packet (@dest)
+    * TOTAL_PACKETS received data packet (@dest)
+    * 1 received data packet (@orig)
+    * 1 received tunnel destroy (@dest)
+    * _________________________________
+    */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
+    ok_goal = TOTAL_PACKETS + 4;
+    if (strstr (argv[0], "_nobuf") != NULL)
+    {
+      test = SPEED_NOBUF;
+      test_name = "speed2 nobuf";
+    }
+    else
+    {
+      test = SPEED;
+      test_name = "speed2";
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
+    test = SETUP;
+    ok_goal = 0;
+  }
+
+  if (strstr (argv[0], "backwards") != NULL)
+  {
+    char *aux;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
+    test_backwards = GNUNET_YES;
+    aux = GNUNET_malloc (32);
+    sprintf (aux, "backwards %s", test_name);
+    test_name = aux;
+  }
+
+  p_ids = 0;
+  ports[0] = 1;
+  ports[1] = 0;
+  GNUNET_MESH_TEST_run ("test_mesh_small",
+                        "test_mesh.conf",
+                        5,
+                        &tmain,
+                        NULL, /* tmain cls */
+                        &incoming_tunnel,
+                        &tunnel_cleaner,
+                        handlers,
+                        ports);
+
+  if (ok_goal > ok)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "FAILED! (%d/%d)\n", ok, ok_goal);
+    return 1;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
+  return 0;
+}
+
+/* end of test_mesh_small.c */
+

Deleted: gnunet/src/mesh/test_mesh_small.conf
===================================================================
--- gnunet/src/mesh/test_mesh_small.conf        2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/mesh/test_mesh_small.conf        2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,78 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/test_mesh_small/
-
-[mesh]
-PORT = 10005
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-REFRESH_PATH_TIME = 5 s
-APP_ANNOUNCE_TIME = 2 s
-ID_ANNOUNCE_TIME = 2 s
-CONNECT_TIMEOUT = 30 s
-DEFAULT_TTL = 64
-DHT_REPLICAITON_LEVEL = 3
-# PREFIX = valgrind --leak-check=full --suppressions=valgrind-mesh.supp
-# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
-
-[testbed]
-NUM_PEERS = 5
-OVERLAY_TOPOLOGY = LINE
-
-[arm]
-PORT = 10010
-DEFAULTSERVICES = core dht mesh
-
-[statistics]
-AUTOSTART = YES
-PORT = 10000
-
-[dht]
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 10001
-
-[nse]
-WORKBITS = 0
-INTERVAL = 60 s
-WORKDELAY = 500 ms
-
-[dns]
-AUTOSTART = NO
-PORT = 10011
-
-[vpn]
-AUTOSTART = NO
-PORT = 10012
-
-[transport]
-PORT = 10002
-AUTOSTART = YES
-
-[nat]
-DISABLEV6 = YES 
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-RETURN_LOCAL_ADDRESSES = YES
-USE_LOCALADDR = YES
-
-[ats]
-WAN_QUOTA_IN = 1 GB
-WAN_QUOTA_OUT = 1 GB
-
-[core]
-AUTOSTART = YES
-PORT = 10003
-
-[peerinfo]
-AUTOSTART = YES
-PORT = 10004
-
-[testing]
-WEAKRANDOM = YES
-

Deleted: gnunet/src/mesh/test_mesh_tree_api.c
===================================================================
--- gnunet/src/mesh/test_mesh_tree_api.c        2013-06-28 14:21:08 UTC (rev 
27680)
+++ gnunet/src/mesh/test_mesh_tree_api.c        2013-06-28 14:34:55 UTC (rev 
27681)
@@ -1,409 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file mesh/test_mesh_tree_api.c
- * @brief test mesh tree api: test of tree & path management api
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_mesh_service.h"
-#include "mesh.h"
-#ifndef MESH_TUNNEL_TREE_C
-#include "mesh_tunnel_tree.c"
-#define MESH_TUNNEL_TREE_C
-#endif
-
-static int failed;
-static int cb_call;
-static struct GNUNET_PeerIdentity *pi[10];
-static struct MeshTunnelTree *tree;
-
-
-/**
- * Whole tree iterator.
- *
- * @param cls Closure (unused).
- * @param peer_id Short ID of the node.
- * @param parent_id Short ID of the parent node.
- */
-static void
-tree_cb (void *cls, GNUNET_PEER_Id peer_id, GNUNET_PEER_Id parent_id)
-{
-  fprintf (stdout, "%u -> %u\n", peer_id, parent_id);;
-}
-
-
-/**
- * Node children iterator.
- *
- * @param cls Closure (unused).
- * @param peer_idShort ID of the child.
- */
-static void
-cb (void *cls, GNUNET_PEER_Id peer_id)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CB: Disconnected %u\n", peer_id);
-  if (0 == cb_call)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:      and it shouldn't!\n");
-    failed++;
-  }
-  cb_call--;
-}
-
-
-/**
- * Print debug information about the state of the tree.
- *
- * @param tree Tree to debug-print.
- */
-static void
-test_debug (struct MeshTunnelTree *tree)
-{
-  tree_debug (tree);
-  tree_iterate_all (tree, &tree_cb, NULL);
-}
-
-
-/**
- * Check if a node has all expected properties.
- *
- * @param peer_id Short ID of the peer to test.
- * @param status Expected status of the peer.
- * @param children Expected number of children of the peer.
- * @param first_hop Short ID of the expected first hop towards the peer.
- */
-static void
-test_assert (GNUNET_PEER_Id peer_id, enum MeshPeerState status,
-             unsigned int children, GNUNET_PEER_Id first_hop)
-{
-  struct MeshTunnelTreeNode *n;
-  struct MeshTunnelTreeNode *c;
-  unsigned int i;
-  int pre_failed;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Checking peer %u\n", peer_id);
-  pre_failed = failed;
-  n = tree_find_peer (tree, peer_id);
-  if (n->peer != peer_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Retrieved peer has wrong ID! (Got %u, expected %u)\n", 
n->peer,
-                peer_id);
-    failed++;
-  }
-  if (n->status != status)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Retrieved peer has wrong status! (Got %u, expected %u)\n",
-                n->status, status);
-    failed++;
-  }
-  for (c = n->children_head, i = 0; NULL != c; c = c->next, i++) ;
-  if (i != children)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Retrieved peer wrong has number of children! (Got %u, 
expected %u)\n",
-                i, children);
-    failed++;
-  }
-  if (0 != first_hop &&
-      GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)) != first_hop)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Wrong first hop! (Got %u, expected %u)\n",
-                GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)),
-                first_hop);
-    failed++;
-  }
-  if (pre_failed != failed)
-  {
-    struct GNUNET_PeerIdentity id;
-
-    GNUNET_PEER_resolve (peer_id, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "*** Peer %s (%u) has failed %d checks!\n", GNUNET_i2s (&id),
-                peer_id, failed - pre_failed);
-  }
-}
-
-
-/**
- * Clean up and free all memory.
- */
-static void
-finish (void)
-{
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Finishing...\n");
-  for (i = 0; i < 10; i++)
-  {
-    GNUNET_free (pi[i]);
-  }
-}
-
-/**
- * Convert an integer int to a peer identity
- */
-static struct GNUNET_PeerIdentity *
-get_pi (uint32_t id)
-{
-  struct GNUNET_PeerIdentity *pi;
-
-  pi = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
-  pi->hashPubKey.bits[0] = id + 1;
-  return pi;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  struct MeshTunnelTreeNode *node;
-  struct MeshPeerPath *path;
-  struct MeshPeerPath *path1;
-  unsigned int i;
-
-  failed = 0;
-  cb_call = 0;
-  GNUNET_log_setup ("test_mesh_api_tree",
-                    "WARNING",
-                    NULL);
-  for (i = 0; i < 10; i++)
-  {
-    pi[i] = get_pi (i);
-    GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i]));
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n", i + 1,
-                GNUNET_h2s (&pi[i]->hashPubKey));
-  }
-  tree = tree_new (1);
-  tree->me = tree->root;
-  path = path_new (5);
-  path->peers[0] = 1;
-  path->peers[1] = 2;
-  path->peers[2] = 3;
-  path->peers[3] = 4;
-  path->length = 4;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3 4\n");
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-  path1 = tree_get_path_to_peer (tree, 4);
-  if (NULL == path1 || path->length != path1->length ||
-      memcmp (path->peers, path1->peers, path->length) != 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved path != original\n");
-    failed++;
-  }
-  path_destroy (path1);
-  test_assert (4, MESH_PEER_SEARCHING, 0, 2);
-  test_assert (3, MESH_PEER_RELAY, 1, 0);
-  test_assert (2, MESH_PEER_RELAY, 1, 0);
-  test_assert (1, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding second path: 1 2 3\n");
-  path->length--;
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-
-  test_assert (4, MESH_PEER_SEARCHING, 0, 2);
-  test_assert (3, MESH_PEER_SEARCHING, 1, 2);
-  test_assert (2, MESH_PEER_RELAY, 1, 0);
-  test_assert (1, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding third path 1 2 3 5\n");
-  path->length++;
-  path->peers[3] = 5;
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-
-  test_assert (5, MESH_PEER_SEARCHING, 0, 2);
-  test_assert (4, MESH_PEER_SEARCHING, 0, 2);
-  test_assert (3, MESH_PEER_SEARCHING, 2, 2);
-  test_assert (2, MESH_PEER_RELAY, 1, 0);
-  test_assert (1, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Calculating costs...\n");
-  for (i = 1; i < 5; i++)
-  {
-    path->length = i;
-    if (tree_get_path_cost (tree, path) != 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n",
-                  i);
-      failed++;
-    }
-  }
-  path->length++;
-  path->peers[4] = 6;
-  if (tree_get_path_cost (tree, path) != 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", 
i);
-    failed++;
-  }
-  path->peers[3] = 7;
-  if (tree_get_path_cost (tree, path) != 2)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", 
i);
-    failed++;
-  }
-  path->length--;
-  if (tree_get_path_cost (tree, path) != 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", 
i);
-    failed++;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Deleting third path (5)\n");
-  tree_set_status (tree, 5, MESH_PEER_READY);
-  cb_call = 1;
-  node = tree_del_path (tree, 5, &cb, NULL);
-  test_debug (tree);
-  if (cb_call != 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
-    failed++;
-  }
-  if (node->peer != 5)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved peer != original\n");
-    failed++;
-  }
-
-  test_assert (4, MESH_PEER_SEARCHING, 0, 2);
-  test_assert (3, MESH_PEER_SEARCHING, 1, 2);
-  test_assert (2, MESH_PEER_RELAY, 1, 0);
-  test_assert (1, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Destroying node copy...\n");
-  GNUNET_free (node);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "test: Adding new shorter first path...\n");
-  path->length = 2;
-  path->peers[1] = 4;
-  cb_call = 1;
-  tree_find_peer (tree, 4)->status = MESH_PEER_READY;
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-  if (cb_call != 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
-    failed++;
-  }
-
-  test_assert (4, MESH_PEER_SEARCHING, 0, 4);
-  test_assert (3, MESH_PEER_SEARCHING, 0, 2);
-  test_assert (2, MESH_PEER_RELAY, 1, 0);
-  test_assert (1, MESH_PEER_ROOT, 2, 0);
-
-  GNUNET_free (path->peers);
-  GNUNET_free (path);
-  tree_destroy (tree);
-
-  
/****************************************************************************/
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Testing relay trees\n");
-  for (i = 0; i < 10; i++)
-  {
-    GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i]));
-  }
-  tree = tree_new (2);
-  path = path_new (8);
-  path->peers[0] = 2;
-  path->peers[1] = 1;
-  path->peers[2] = 3;
-  path->length = 3;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n");
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-
-  test_assert (3, MESH_PEER_SEARCHING, 0, 3);
-  test_assert (1, MESH_PEER_RELAY, 1, 0);
-  test_assert (2, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding long path: 2 1 4 5 3\n");
-  path->peers[2] = 4;
-  path->peers[3] = 5;
-  path->peers[4] = 3;
-  path->length = 5;
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-
-  test_assert (3, MESH_PEER_SEARCHING, 0, 4);
-  test_assert (5, MESH_PEER_RELAY, 1, 4);
-  test_assert (4, MESH_PEER_RELAY, 1, 4);
-  test_assert (1, MESH_PEER_RELAY, 1, 0);
-  test_assert (2, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "test: Even longer path: 2 6 1 7 8 4 5 3\n");
-  path->peers[0] = 2;
-  path->peers[1] = 6;
-  path->peers[2] = 1;
-  path->peers[3] = 7;
-  path->peers[4] = 8;
-  path->peers[5] = 4;
-  path->peers[6] = 5;
-  path->peers[7] = 3;
-  path->length = 8;
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-
-  test_assert (3, MESH_PEER_SEARCHING, 0, 7);
-  test_assert (5, MESH_PEER_RELAY, 1, 7);
-  test_assert (4, MESH_PEER_RELAY, 1, 7);
-  test_assert (8, MESH_PEER_RELAY, 1, 7);
-  test_assert (7, MESH_PEER_RELAY, 1, 7);
-  test_assert (1, MESH_PEER_RELAY, 1, 0);
-  test_assert (6, MESH_PEER_RELAY, 1, 0);
-  test_assert (2, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n");
-  path->peers[1] = 1;
-  path->peers[2] = 3;
-  path->length = 3;
-  tree_add_path (tree, path, &cb, NULL);
-  test_debug (tree);
-
-  test_assert (3, MESH_PEER_SEARCHING, 0, 3);
-  test_assert (1, MESH_PEER_RELAY, 1, 0);
-  test_assert (2, MESH_PEER_ROOT, 1, 0);
-
-  GNUNET_free (path->peers);
-  GNUNET_free (path);
-  tree_destroy (tree);
-  finish ();
-  if (failed > 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u tests failed\n", failed);
-    return 1;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: OK\n");
-
-  return 0;
-}

Modified: gnunet/src/pt/gnunet-daemon-pt.c
===================================================================
--- gnunet/src/pt/gnunet-daemon-pt.c    2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/pt/gnunet-daemon-pt.c    2013-06-28 14:34:55 UTC (rev 27681)
@@ -33,7 +33,9 @@
 #include "gnunet_statistics_service.h"
 #include "gnunet_applications.h"
 
+#define PORT_PT 4242 // FIXME
 
+
 /**
  * After how long do we time out if we could not get an IP from VPN or MESH?
  */
@@ -548,11 +550,11 @@
     return 0;
   mlen = ntohs (rc->mesh_message->size);
   if (mlen > size)
-  {    
+  {
     mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
                                                 GNUNET_NO,
                                                 TIMEOUT,
-                                                NULL, mlen,
+                                                mlen,
                                                 &transmit_dns_request_to_mesh,
                                                 NULL);
     return 0;
@@ -571,7 +573,7 @@
     mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
                                                 GNUNET_NO,
                                                 TIMEOUT,
-                                                NULL, ntohs 
(rc->mesh_message->size),
+                                                ntohs (rc->mesh_message->size),
                                                 &transmit_dns_request_to_mesh,
                                                 NULL);
   return mlen;
@@ -670,7 +672,7 @@
     mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
                                                 GNUNET_NO,
                                                 TIMEOUT,
-                                                NULL, mlen,
+                                                mlen,
                                                 &transmit_dns_request_to_mesh,
                                                 NULL);
 }
@@ -682,18 +684,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 receive_dns_response (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel 
*tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_TUN_DnsHeader dns;
   size_t mlen;
@@ -772,10 +771,12 @@
 /**
  * Method called whenever a peer has disconnected from the tunnel.
  *
+ * FIXME merge with inbound cleaner
+ * 
  * @param cls closure
  * @param peer peer identity the tunnel stopped working with
  */
-static void
+void
 mesh_disconnect_handler (void *cls,
                         const struct
                         GNUNET_PeerIdentity * peer)
@@ -797,11 +798,13 @@
 /**
  * Method called whenever a peer has connected to the tunnel.
  *
+ * FIXME find anouther way (in tmt_ready_callback ?)
+ * 
  * @param cls closure
  * @param peer peer identity the tunnel was created to, NULL on timeout
  * @param atsi performance data for the connection
  */
-static void
+void
 mesh_connect_handler (void *cls,
                      const struct GNUNET_PeerIdentity
                      * peer,
@@ -916,9 +919,6 @@
       {&receive_dns_response, GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET, 0},
       {NULL, 0, 0}
     };
-    static GNUNET_MESH_ApplicationType mesh_types[] = {
-      GNUNET_APPLICATION_TYPE_END
-    };
 
     dns_pre_handle 
       = GNUNET_DNS_connect (cfg, 
@@ -932,8 +932,8 @@
       GNUNET_SCHEDULER_shutdown ();
       return;
     }
-    mesh_handle = GNUNET_MESH_connect (cfg, NULL, NULL, NULL,
-                                      mesh_handlers, mesh_types);
+    mesh_handle = GNUNET_MESH_connect (cfg, NULL, NULL, NULL, // FIXME use end 
handler
+                                      mesh_handlers, NULL);
     if (NULL == mesh_handle)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -944,11 +944,10 @@
     }
     mesh_tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
                                             NULL,
-                                            &mesh_connect_handler,
-                                            &mesh_disconnect_handler,
-                                            NULL);
-    GNUNET_MESH_peer_request_connect_by_type (mesh_tunnel,
-                                             
GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER); 
+                                             NULL, /* FIXME peer ID*/
+                                            PORT_PT);
+//     GNUNET_MESH_peer_request_connect_by_type (mesh_tunnel, FIXME use regex
+//                                           
GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER); 
   }
 }
 

Modified: gnunet/src/set/Makefile.am
===================================================================
--- gnunet/src/set/Makefile.am  2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/set/Makefile.am  2013-06-28 14:34:55 UTC (rev 27681)
@@ -50,7 +50,7 @@
 gnunet_service_set_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/core/libgnunetcore.la \
-  $(top_builddir)/src/mesh/libgnunetmesh2.la \
+  $(top_builddir)/src/mesh/libgnunetmesh.la \
   $(GN_LIBINTL)
 
 libgnunetset_la_SOURCES = \

Modified: gnunet/src/set/gnunet-service-set.h
===================================================================
--- gnunet/src/set/gnunet-service-set.h 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/set/gnunet-service-set.h 2013-06-28 14:34:55 UTC (rev 27681)
@@ -33,7 +33,7 @@
 #include "gnunet_applications.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_core_service.h"
-#include "gnunet_mesh2_service.h"
+#include "gnunet_mesh_service.h"
 #include "gnunet_set_service.h"
 #include "set.h"
 

Modified: gnunet/src/stream/stream_api.c
===================================================================
--- gnunet/src/stream/stream_api.c      2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/stream/stream_api.c      2013-06-28 14:34:55 UTC (rev 27681)
@@ -42,6 +42,8 @@
 #include "gnunet_stream_lib.h"
 #include "stream.h"
 
+#define STREAM_PORT 4242
+
 /**
  * Generic logging shorthand
  */
@@ -311,9 +313,9 @@
   int transmit_closed;
 
   /**
-   * The application port number (type: uint32_t)
+   * The application port number
    */
-  GNUNET_MESH_ApplicationType port;
+  uint32_t port;
 
   /**
    * The write sequence number to be set incase of testing
@@ -416,7 +418,7 @@
   /**
    * The service port
    */
-  GNUNET_MESH_ApplicationType port;
+  uint32_t port;
   
   /**
    * The id of the lockmanager timeout task
@@ -651,7 +653,6 @@
         GNUNET_MESH_notify_transmit_ready (socket->tunnel,
                                            GNUNET_NO, /* Corking */
                                            socket->mesh_retry_timeout,
-                                           &socket->other_peer,
                                            ntohs (head->message->size),
                                            &send_message_notify,
                                            socket);
@@ -679,7 +680,6 @@
         GNUNET_MESH_notify_transmit_ready (socket->tunnel,
                                            GNUNET_NO, /* Corking */
                                            socket->mesh_retry_timeout,
-                                           &socket->other_peer,
                                            ntohs (head->message->size),
                                            &send_message_notify,
                                            socket);
@@ -739,7 +739,6 @@
        GNUNET_MESH_notify_transmit_ready (socket->tunnel,
                                           GNUNET_NO, /* Corking */
                                            socket->mesh_retry_timeout,
-                                          &socket->other_peer,
                                           ntohs (message->size),
                                           &send_message_notify,
                                           socket);
@@ -1159,18 +1158,14 @@
  *
  * @param socket the socket through which the ack was received
  * @param tunnel connection to the other end
- * @param sender who sent the message
  * @param msg the data message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_data (struct GNUNET_STREAM_Socket *socket,
              struct GNUNET_MESH_Tunnel *tunnel,
-             const struct GNUNET_PeerIdentity *sender,
-             const struct GNUNET_STREAM_DataMessage *msg,
-             const struct GNUNET_ATS_Information*atsi)
+             const struct GNUNET_STREAM_DataMessage *msg)
 {
   const void *payload;
   struct GNUNET_TIME_Relative ack_deadline_rel;
@@ -1185,14 +1180,6 @@
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  if (0 != memcmp (sender, &socket->other_peer,
-                  sizeof (struct GNUNET_PeerIdentity)))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "%s: Received DATA from non-confirming peer\n",
-        GNUNET_i2s (&socket->other_peer));
-    return GNUNET_YES;
-  }
   switch (socket->state)
   {
   case STATE_ESTABLISHED:
@@ -1333,9 +1320,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx place to store local state associated with the tunnel
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1343,14 +1328,12 @@
 client_handle_data (void *cls,
                     struct GNUNET_MESH_Tunnel *tunnel,
                     void **tunnel_ctx,
-                    const struct GNUNET_PeerIdentity *sender,
-                    const struct GNUNET_MessageHeader *message,
-                    const struct GNUNET_ATS_Information*atsi)
+                    const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
 
-  return handle_data (socket, tunnel, sender, 
-                      (const struct GNUNET_STREAM_DataMessage *) message, 
atsi);
+  return handle_data (socket, tunnel, 
+                      (const struct GNUNET_STREAM_DataMessage *) message);
 }
 
 
@@ -1598,9 +1581,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1608,22 +1589,12 @@
 client_handle_hello_ack (void *cls,
                          struct GNUNET_MESH_Tunnel *tunnel,
                          void **tunnel_ctx,
-                         const struct GNUNET_PeerIdentity *sender,
-                         const struct GNUNET_MessageHeader *message,
-                         const struct GNUNET_ATS_Information*atsi)
+                         const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
   const struct GNUNET_STREAM_HelloAckMessage *ack_msg;
   struct GNUNET_STREAM_HelloAckMessage *reply;
 
-  if (0 != memcmp (sender, &socket->other_peer,
-                  sizeof (struct GNUNET_PeerIdentity)))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "%s: Received HELLO_ACK from non-confirming peer\n",
-         GNUNET_i2s (&socket->other_peer));
-    return GNUNET_YES;
-  }
   ack_msg = (const struct GNUNET_STREAM_HelloAckMessage *) message;
   LOG (GNUNET_ERROR_TYPE_DEBUG, "%s: Received HELLO_ACK from %s\n",
        GNUNET_i2s (&socket->other_peer), GNUNET_i2s (&socket->other_peer));
@@ -1661,9 +1632,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1671,9 +1640,7 @@
 client_handle_reset (void *cls,
                      struct GNUNET_MESH_Tunnel *tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information*atsi)
+                     const struct GNUNET_MessageHeader *message)
 {
   // struct GNUNET_STREAM_Socket *socket = cls;
 
@@ -1743,18 +1710,14 @@
  *
  * @param socket the socket through which the ack was received
  * @param tunnel connection to the other end
- * @param sender who sent the message
  * @param msg the transmit close message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_transmit_close (struct GNUNET_STREAM_Socket *socket,
                        struct GNUNET_MESH_Tunnel *tunnel,
-                       const struct GNUNET_PeerIdentity *sender,
-                       const struct GNUNET_MessageHeader *msg,
-                       const struct GNUNET_ATS_Information*atsi)
+                       const struct GNUNET_MessageHeader *msg)
 {
   struct GNUNET_MessageHeader *reply;
 
@@ -1802,9 +1765,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1812,17 +1773,13 @@
 client_handle_transmit_close (void *cls,
                               struct GNUNET_MESH_Tunnel *tunnel,
                               void **tunnel_ctx,
-                              const struct GNUNET_PeerIdentity *sender,
-                              const struct GNUNET_MessageHeader *message,
-                              const struct GNUNET_ATS_Information*atsi)
+                              const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
   
   return handle_transmit_close (socket,
                                 tunnel,
-                                sender,
-                                (struct GNUNET_MessageHeader *)message,
-                                atsi);
+                                (struct GNUNET_MessageHeader *)message);
 }
 
 
@@ -1853,9 +1810,7 @@
  *
  * @param socket the socket
  * @param tunnel connection to the other end
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @param operation the close operation which is being ACK'ed
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
@@ -1863,9 +1818,7 @@
 static int
 handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket,
                           struct GNUNET_MESH_Tunnel *tunnel,
-                          const struct GNUNET_PeerIdentity *sender,
                           const struct GNUNET_MessageHeader *message,
-                          const struct GNUNET_ATS_Information *atsi,
                           int operation)
 {
   struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
@@ -1971,9 +1924,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1981,18 +1932,14 @@
 client_handle_transmit_close_ack (void *cls,
                                   struct GNUNET_MESH_Tunnel *tunnel,
                                   void **tunnel_ctx,
-                                  const struct GNUNET_PeerIdentity *sender,
-                                  const struct GNUNET_MessageHeader *message,
-                                  const struct GNUNET_ATS_Information*atsi)
+                                  const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
 
   return handle_generic_close_ack (socket,
                                    tunnel,
-                                   sender,
                                    (const struct GNUNET_MessageHeader *)
                                    message,
-                                   atsi,
                                    SHUT_WR);
 }
 
@@ -2002,18 +1949,14 @@
  *
  * @param socket the socket
  * @param tunnel connection to the other end
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_receive_close (struct GNUNET_STREAM_Socket *socket,
                       struct GNUNET_MESH_Tunnel *tunnel,
-                      const struct GNUNET_PeerIdentity *sender,
-                      const struct GNUNET_MessageHeader *message,
-                      const struct GNUNET_ATS_Information *atsi)
+                      const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_MessageHeader *receive_close_ack;
 
@@ -2061,9 +2004,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2071,18 +2012,14 @@
 client_handle_receive_close (void *cls,
                              struct GNUNET_MESH_Tunnel *tunnel,
                              void **tunnel_ctx,
-                             const struct GNUNET_PeerIdentity *sender,
-                             const struct GNUNET_MessageHeader *message,
-                             const struct GNUNET_ATS_Information*atsi)
+                             const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
 
   return
     handle_receive_close (socket,
                           tunnel,
-                          sender,
-                          (const struct GNUNET_MessageHeader *) message,
-                          atsi);
+                          (const struct GNUNET_MessageHeader *) message);
 }
 
 
@@ -2092,9 +2029,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2102,18 +2037,14 @@
 client_handle_receive_close_ack (void *cls,
                                  struct GNUNET_MESH_Tunnel *tunnel,
                                  void **tunnel_ctx,
-                                 const struct GNUNET_PeerIdentity *sender,
-                                 const struct GNUNET_MessageHeader *message,
-                                 const struct GNUNET_ATS_Information*atsi)
+                                 const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
 
   return handle_generic_close_ack (socket,
                                    tunnel,
-                                   sender,
                                    (const struct GNUNET_MessageHeader *)
                                    message,
-                                   atsi,
                                    SHUT_RD);
 }
 
@@ -2123,18 +2054,14 @@
  *
  * @param socket the socket
  * @param tunnel connection to the other end
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_close (struct GNUNET_STREAM_Socket *socket,
               struct GNUNET_MESH_Tunnel *tunnel,
-              const struct GNUNET_PeerIdentity *sender,
-              const struct GNUNET_MessageHeader *message,
-              const struct GNUNET_ATS_Information*atsi)
+              const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_MessageHeader *close_ack;
 
@@ -2172,9 +2099,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2182,17 +2107,13 @@
 client_handle_close (void *cls,
                      struct GNUNET_MESH_Tunnel *tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information*atsi)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
 
   return handle_close (socket,
                        tunnel,
-                       sender,
-                       (const struct GNUNET_MessageHeader *) message,
-                       atsi);
+                       (const struct GNUNET_MessageHeader *) message);
 }
 
 
@@ -2202,9 +2123,7 @@
  * @param cls the socket (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end
  * @param tunnel_ctx this is NULL
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2212,18 +2131,14 @@
 client_handle_close_ack (void *cls,
                          struct GNUNET_MESH_Tunnel *tunnel,
                          void **tunnel_ctx,
-                         const struct GNUNET_PeerIdentity *sender,
-                         const struct GNUNET_MessageHeader *message,
-                         const struct GNUNET_ATS_Information *atsi)
+                         const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
 
   return handle_generic_close_ack (socket,
                                    tunnel,
-                                   sender,
                                    (const struct GNUNET_MessageHeader *) 
                                    message,
-                                   atsi,
                                    SHUT_RDWR);
 }
 
@@ -2237,9 +2152,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2247,17 +2160,13 @@
 server_handle_data (void *cls,
                     struct GNUNET_MESH_Tunnel *tunnel,
                     void **tunnel_ctx,
-                    const struct GNUNET_PeerIdentity *sender,
-                    const struct GNUNET_MessageHeader *message,
-                    const struct GNUNET_ATS_Information*atsi)
+                    const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
 
   return handle_data (socket,
                       tunnel,
-                      sender,
-                      (const struct GNUNET_STREAM_DataMessage *)message,
-                      atsi);
+                      (const struct GNUNET_STREAM_DataMessage *)message);
 }
 
 
@@ -2267,9 +2176,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2277,9 +2184,7 @@
 server_handle_hello (void *cls,
                      struct GNUNET_MESH_Tunnel *tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information*atsi)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
   const struct GNUNET_STREAM_HelloMessage *hello;
@@ -2287,14 +2192,6 @@
   uint32_t port;
 
   hello = (const struct GNUNET_STREAM_HelloMessage *) message;
-  if (0 != memcmp (sender,
-                   &socket->other_peer,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    LOG_DEBUG ("%s: Received HELLO from non-confirming peer\n",
-               GNUNET_i2s (&socket->other_peer));
-    return GNUNET_YES;
-  }
   GNUNET_assert (GNUNET_MESSAGE_TYPE_STREAM_HELLO == ntohs (message->type));
   GNUNET_assert (socket->tunnel == tunnel);
   LOG_DEBUG ("%1$s: Received HELLO from %1$s\n", 
@@ -2342,9 +2239,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2352,9 +2247,7 @@
 server_handle_hello_ack (void *cls,
                          struct GNUNET_MESH_Tunnel *tunnel,
                          void **tunnel_ctx,
-                         const struct GNUNET_PeerIdentity *sender,
-                         const struct GNUNET_MessageHeader *message,
-                         const struct GNUNET_ATS_Information*atsi)
+                         const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
   const struct GNUNET_STREAM_HelloAckMessage *ack_message;
@@ -2393,9 +2286,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2403,9 +2294,7 @@
 server_handle_reset (void *cls,
                      struct GNUNET_MESH_Tunnel *tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information*atsi)
+                     const struct GNUNET_MessageHeader *message)
 {
   // struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
   /* FIXME */
@@ -2419,9 +2308,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2429,13 +2316,11 @@
 server_handle_transmit_close (void *cls,
                               struct GNUNET_MESH_Tunnel *tunnel,
                               void **tunnel_ctx,
-                              const struct GNUNET_PeerIdentity *sender,
-                              const struct GNUNET_MessageHeader *message,
-                              const struct GNUNET_ATS_Information*atsi)
+                              const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
 
-  return handle_transmit_close (socket, tunnel, sender, message, atsi);
+  return handle_transmit_close (socket, tunnel, message);
 }
 
 
@@ -2445,9 +2330,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2455,14 +2338,11 @@
 server_handle_transmit_close_ack (void *cls,
                                   struct GNUNET_MESH_Tunnel *tunnel,
                                   void **tunnel_ctx,
-                                  const struct GNUNET_PeerIdentity *sender,
-                                  const struct GNUNET_MessageHeader *message,
-                                  const struct GNUNET_ATS_Information*atsi)
+                                  const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
 
-  return handle_generic_close_ack (socket, tunnel, sender, message, atsi,
-                                   SHUT_WR);
+  return handle_generic_close_ack (socket, tunnel, message, SHUT_WR);
 }
 
 
@@ -2472,9 +2352,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2482,13 +2360,11 @@
 server_handle_receive_close (void *cls,
                              struct GNUNET_MESH_Tunnel *tunnel,
                              void **tunnel_ctx,
-                             const struct GNUNET_PeerIdentity *sender,
-                             const struct GNUNET_MessageHeader *message,
-                             const struct GNUNET_ATS_Information*atsi)
+                             const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
 
-  return handle_receive_close (socket, tunnel, sender, message, atsi);
+  return handle_receive_close (socket, tunnel, message);
 }
 
 
@@ -2498,9 +2374,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2508,14 +2382,11 @@
 server_handle_receive_close_ack (void *cls,
                                  struct GNUNET_MESH_Tunnel *tunnel,
                                  void **tunnel_ctx,
-                                 const struct GNUNET_PeerIdentity *sender,
-                                 const struct GNUNET_MessageHeader *message,
-                                 const struct GNUNET_ATS_Information*atsi)
+                                 const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
 
-  return handle_generic_close_ack (socket, tunnel, sender, message, atsi,
-                                   SHUT_RD);
+  return handle_generic_close_ack (socket, tunnel, message, SHUT_RD);
 }
 
 
@@ -2526,9 +2397,7 @@
  *          GNUNET_STREAM_listen) 
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2536,13 +2405,11 @@
 server_handle_close (void *cls,
                      struct GNUNET_MESH_Tunnel *tunnel,
                      void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information*atsi)
+                     const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
   
-  return handle_close (socket, tunnel, sender, message, atsi);
+  return handle_close (socket, tunnel, message);
 }
 
 
@@ -2552,9 +2419,7 @@
  * @param cls the closure
  * @param tunnel connection to the other end
  * @param tunnel_ctx the socket
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2562,14 +2427,11 @@
 server_handle_close_ack (void *cls,
                          struct GNUNET_MESH_Tunnel *tunnel,
                          void **tunnel_ctx,
-                         const struct GNUNET_PeerIdentity *sender,
-                         const struct GNUNET_MessageHeader *message,
-                         const struct GNUNET_ATS_Information*atsi)
+                         const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
 
-  return handle_generic_close_ack (socket, tunnel, sender, message, atsi,
-                                   SHUT_RDWR);
+  return handle_generic_close_ack (socket, tunnel, message, SHUT_RDWR);
 }
 
 
@@ -2578,18 +2440,14 @@
  *
  * @param socket the socket through which the ack was received
  * @param tunnel connection to the other end
- * @param sender who sent the message
  * @param ack the acknowledgment message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handle_ack (struct GNUNET_STREAM_Socket *socket,
            struct GNUNET_MESH_Tunnel *tunnel,
-           const struct GNUNET_PeerIdentity *sender,
-           const struct GNUNET_STREAM_AckMessage *ack,
-           const struct GNUNET_ATS_Information*atsi)
+           const struct GNUNET_STREAM_AckMessage *ack)
 {
   struct GNUNET_STREAM_WriteHandle *write_handle;
   uint64_t ack_bitmap;
@@ -2597,15 +2455,6 @@
   int need_retransmission;
   uint32_t sequence_difference;
 
-  if (0 != memcmp (sender,
-                   &socket->other_peer,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "%s: Received ACK from non-confirming peer\n",
-         GNUNET_i2s (&socket->other_peer));
-    return GNUNET_YES;
-  }
   switch (socket->state)
   {
   case (STATE_ESTABLISHED):
@@ -2734,9 +2583,7 @@
  * @param cls the 'struct GNUNET_STREAM_Socket'
  * @param tunnel connection to the other end
  * @param tunnel_ctx unused
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2744,15 +2591,13 @@
 client_handle_ack (void *cls,
                   struct GNUNET_MESH_Tunnel *tunnel,
                   void **tunnel_ctx,
-                  const struct GNUNET_PeerIdentity *sender,
-                  const struct GNUNET_MessageHeader *message,
-                  const struct GNUNET_ATS_Information*atsi)
+                  const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = cls;
   const struct GNUNET_STREAM_AckMessage *ack;
 
   ack = (const struct GNUNET_STREAM_AckMessage *) message; 
-  return handle_ack (socket, tunnel, sender, ack, atsi);
+  return handle_ack (socket, tunnel, ack);
 }
 
 
@@ -2762,9 +2607,7 @@
  * @param cls the server's listen socket
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to the 'struct GNUNET_STREAM_Socket*'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -2772,14 +2615,12 @@
 server_handle_ack (void *cls,
                   struct GNUNET_MESH_Tunnel *tunnel,
                   void **tunnel_ctx,
-                  const struct GNUNET_PeerIdentity *sender,
-                  const struct GNUNET_MessageHeader *message,
-                  const struct GNUNET_ATS_Information*atsi)
+                  const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
   const struct GNUNET_STREAM_AckMessage *ack = (const struct 
GNUNET_STREAM_AckMessage *) message;
  
-  return handle_ack (socket, tunnel, sender, ack, atsi);
+  return handle_ack (socket, tunnel, ack);
 }
 
 
@@ -2847,8 +2688,10 @@
  * @param cls the socket for which this tunnel is created
  * @param peer the peer identity of the target
  * @param atsi performance data for the connection
+ * 
+ * FIXME static
  */
-static void
+void
 mesh_peer_connect_callback (void *cls,
                             const struct GNUNET_PeerIdentity *peer,
                             const struct GNUNET_ATS_Information * atsi)
@@ -2887,8 +2730,10 @@
  *
  * @param cls the socket associated which this tunnel
  * @param peer the peer identity of the target
+ * 
+ * FIXME static
  */
-static void
+void
 mesh_peer_disconnect_callback (void *cls,
                                const struct GNUNET_PeerIdentity *peer)
 {
@@ -2906,7 +2751,7 @@
  * @param cls closure
  * @param tunnel new handle to the tunnel
  * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
+ * @param port incoming port
  * @return initial tunnel context for the tunnel
  *         (can be NULL -- that's not an error)
  */
@@ -2914,7 +2759,7 @@
 new_tunnel_notify (void *cls,
                    struct GNUNET_MESH_Tunnel *tunnel,
                    const struct GNUNET_PeerIdentity *initiator,
-                   const struct GNUNET_ATS_Information *atsi)
+                   uint32_t port)
 {
   struct GNUNET_STREAM_ListenSocket *lsocket = cls;
   struct GNUNET_STREAM_Socket *socket;
@@ -3067,7 +2912,7 @@
     }
     if (NULL == lsocket->mesh)
     {
-      GNUNET_MESH_ApplicationType ports[] = {lsocket->port, 0};
+      uint32_t ports[] = {lsocket->port, 0};
 
       lsocket->mesh = GNUNET_MESH_connect (lsocket->cfg,
                                            lsocket, /* Closure */
@@ -3109,7 +2954,7 @@
 struct GNUNET_STREAM_Socket *
 GNUNET_STREAM_open (const struct GNUNET_CONFIGURATION_Handle *cfg,
                     const struct GNUNET_PeerIdentity *target,
-                    GNUNET_MESH_ApplicationType app_port,
+                    uint32_t app_port,
                     GNUNET_STREAM_OpenCallback open_cb,
                     void *open_cb_cls,
                     ...)
@@ -3177,13 +3022,10 @@
   /* Now create the mesh tunnel to target */
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating MESH Tunnel\n");
   socket->tunnel = GNUNET_MESH_tunnel_create (socket->mesh,
-                                              NULL, /* Tunnel context */
-                                              &mesh_peer_connect_callback,
-                                              &mesh_peer_disconnect_callback,
-                                              socket);
+                                              socket, /* Tunnel context */
+                                              &socket->other_peer,
+                                              STREAM_PORT);
   GNUNET_assert (NULL != socket->tunnel);
-  GNUNET_MESH_peer_request_connect_add (socket->tunnel,
-                                        &socket->other_peer);
   socket->stat_handle = GNUNET_STATISTICS_create ("stream", cfg);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "%s() END\n", __func__);
   return socket;
@@ -3388,7 +3230,7 @@
  */
 struct GNUNET_STREAM_ListenSocket *
 GNUNET_STREAM_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                      GNUNET_MESH_ApplicationType app_port,
+                      uint32_t app_port,
                       GNUNET_STREAM_ListenCallback listen_cb,
                       void *listen_cb_cls,
                       ...)

Modified: gnunet/src/vpn/gnunet-service-vpn.c
===================================================================
--- gnunet/src/vpn/gnunet-service-vpn.c 2013-06-28 14:21:08 UTC (rev 27680)
+++ gnunet/src/vpn/gnunet-service-vpn.c 2013-06-28 14:34:55 UTC (rev 27681)
@@ -50,6 +50,8 @@
 #define MAX_MESSAGE_QUEUE_SIZE 4
 
 
+#define PORT_VPN 42
+
 /**
  * State we keep for each of our tunnels.
  */
@@ -601,10 +603,12 @@
 /**
  * Method called whenever a peer has disconnected from the tunnel.
  *
+ * FIXME merge with inbound_cleaner
+ * 
  * @param cls closure
  * @param peer peer identity the tunnel stopped working with
  */
-static void
+void
 tunnel_peer_disconnect_handler (void *cls,
                                const struct
                                GNUNET_PeerIdentity * peer)
@@ -635,11 +639,13 @@
  * Method called whenever a peer has connected to the tunnel.  Notifies
  * the waiting client that the tunnel is now up.
  *
+ * FIXME merge with tunnel_create
+ * 
  * @param cls closure
  * @param peer peer identity the tunnel was created to, NULL on timeout
  * @param atsi performance data for the connection
  */
-static void
+void
 tunnel_peer_connect_handler (void *cls,
                             const struct GNUNET_PeerIdentity
                             * peer,
@@ -699,7 +705,6 @@
     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
                                                GNUNET_NO /* cork */, 
                                                GNUNET_TIME_UNIT_FOREVER_REL,
-                                               NULL, 
                                                tnq->len,
                                                &send_to_peer_notify_callback,
                                                ts);
@@ -751,7 +756,6 @@
     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
                                                GNUNET_NO /* cork */,
                                                GNUNET_TIME_UNIT_FOREVER_REL,
-                                               NULL, 
                                                tnq->len,
                                                &send_to_peer_notify_callback,
                                                ts);
@@ -782,11 +786,8 @@
   ts->search = NULL;
   ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
                                          ts,
-                                         &tunnel_peer_connect_handler,
-                                         &tunnel_peer_disconnect_handler,
-                                         ts);
-  GNUNET_MESH_peer_request_connect_add (ts->tunnel,
-                                       id);
+                                          id,
+                                         PORT_VPN);
 }
 
 
@@ -826,9 +827,8 @@
   {
     ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
                                            ts,
-                                           &tunnel_peer_connect_handler,
-                                           &tunnel_peer_disconnect_handler,
-                                           ts);
+                                            
&de->details.service_destination.target,
+                                           PORT_VPN);
     if (NULL == ts->tunnel)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -840,8 +840,6 @@
                "Creating tunnel to peer %s offering service %s\n",
                GNUNET_i2s (&de->details.service_destination.target),
                GNUNET_h2s 
(&de->details.service_destination.service_descriptor));
-    GNUNET_MESH_peer_request_connect_add (ts->tunnel,
-                                         
&de->details.service_destination.target);  
   }
   else
   {
@@ -1741,17 +1739,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */ 
 static int
 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
-                  void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
-                  const struct GNUNET_MessageHeader *message,
-                  const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                  void **tunnel_ctx,
+                  const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *ts = *tunnel_ctx;
   const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
@@ -2082,17 +2078,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */ 
 static int
 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
-                  void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
-                  const struct GNUNET_MessageHeader *message,
-                  const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                  void **tunnel_ctx,
+                  const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *ts = *tunnel_ctx;
   const struct GNUNET_EXIT_UdpReplyMessage *reply;
@@ -2239,18 +2233,15 @@
  * @param cls closure, NULL
  * @param tunnel connection to the other end
  * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
  * @param message the actual message
- * @param atsi performance data for the connection
+ * 
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */ 
 static int
 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
                   void **tunnel_ctx,
-                  const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                  const struct GNUNET_MessageHeader *message,
-                  const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
+                  const struct GNUNET_MessageHeader *message)
 {
   struct TunnelState *ts = *tunnel_ctx;
   const struct GNUNET_EXIT_TcpDataMessage *data;
@@ -2842,32 +2833,11 @@
 }
 
 
-
 /**
- * Function called for inbound tunnels.  As we don't offer
- * any mesh services, this function should never be called.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param atsi performance information for the tunnel
- * @return initial tunnel context for the tunnel
- *         (can be NULL -- that's not an error)
- */ 
-static void *
-inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                  const struct GNUNET_PeerIdentity *initiator,
-                  const struct GNUNET_ATS_Information *atsi)
-{
-  /* How can and why should anyone open an inbound tunnel to vpn? */
-  GNUNET_break (0);
-  return NULL;
-}
-
-
-/**
  * Function called whenever an inbound tunnel is destroyed.  Should clean up
  * any associated state.
+ * 
+ * FIXME now its also user for disconnections
  *
  * @param cls closure (set from GNUNET_MESH_connect)
  * @param tunnel connection to the other end (henceforth invalid)
@@ -3081,9 +3051,6 @@
     { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
     {NULL, 0, 0}
   };
-  static const GNUNET_MESH_ApplicationType types[] = {
-    GNUNET_APPLICATION_TYPE_END
-  };
   char *ifname;
   char *ipv6addr;
   char *ipv6prefix_s;
@@ -3209,10 +3176,10 @@
 
   mesh_handle =
     GNUNET_MESH_connect (cfg_, NULL, 
-                        &inbound_tunnel_cb, 
+                        NULL, 
                         &tunnel_cleaner, 
                         mesh_handlers,
-                        types);
+                        NULL);
   helper_handle = GNUNET_HELPER_start (GNUNET_NO,
                                       "gnunet-helper-vpn", vpn_argv,
                                       &message_token, NULL, NULL);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]