- make sure to free all memory in possible luibgcrypt leak
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh-enc.c
index a5670fff3c989aa50d43bcaa9a490b6688bbc41d..3d1238a3653dfaa3c8c24eef1459ff0cd41ba491 100644 (file)
  * - relay corking down to core
  * - set ttl relative to path length
  * TODO END
- * 
- * Dictionary:
- * - peer: other mesh instance. If there is direct connection it's a neighbor.
- * - tunnel: encrypted connection to a peer, neighbor or not.
- * - channel: connection between two clients, on the same or different peers.
- *            have properties like reliability.
- * - path: series of directly connected peer from one peer to another.
- * - connection: path which is being used in a tunnel.
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "mesh_enc.h"
-#include "mesh_protocol_enc.h"
-#include "mesh_path.h"
-#include "block_mesh.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_statistics_service.h"
-
-#include "gnunet-service-mesh_local.h"
-#include "gnunet-service-mesh_channel.h"
-#include "gnunet-service-mesh_connection.h"
-
-#define MESH_BLOOM_SIZE         128
-#define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
-                                  GNUNET_TIME_UNIT_MINUTES,\
-                                  10)
-#define MESH_RETRANSMIT_TIME    GNUNET_TIME_UNIT_SECONDS
-#define MESH_RETRANSMIT_MARGIN  4
-
-#define MESH_DEBUG_DHT          GNUNET_NO
-#define MESH_DEBUG_CONNECTION   GNUNET_NO
-#define MESH_DEBUG_TIMING       __LINUX__ && GNUNET_NO
-
-#if MESH_DEBUG_DHT
-#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_DHT(...)
-#endif
-
-#if MESH_DEBUG_CONNECTION
-#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
-#else
-#define DEBUG_CONN(...)
-#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
-
-/**
- * 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
-};
-
-
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     ****************************/
-/******************************************************************************/
-
-/** FWD declaration */
-struct MeshClient;
-struct MeshPeer;
-struct MeshTunnel2;
-struct MeshConnection;
-
-
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct MeshPeer
-{
-    /**
-     * ID of the peer
-     */
-  GNUNET_PEER_Id id;
-
-    /**
-     * Last time we heard from this peer
-     */
-  struct GNUNET_TIME_Absolute last_contact;
-
-    /**
-     * 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 paths to this peer
-     */
-  struct GNUNET_DHT_GetHandle *dhtget;
-
-    /**
-     * Tunnel to this peer, if any.
-     */
-  struct MeshTunnel2 *tunnel;
-
-    /**
-     * Connections that go through this peer, indexed by tid;
-     */
-  struct GNUNET_CONTAINER_MultiHashMap *connections;
-
-    /**
-     * Handle for queued transmissions
-     */
-  struct GNUNET_CORE_TransmitHandle *core_transmit;
-
-  /**
-   * 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;
-};
-
-
-
-
-/**
- * Struct used to queue messages in a tunnel.
- */
-struct MeshTunnelQueue
-{
-  /**
-   * DLL
-   */
-  struct MeshTunnelQueue *next;
-  struct MeshTunnelQueue *prev;
-
-  /**
-   * Channel.
-   */
-  struct MeshChannel *ch;
-
-  /**
-   * Message to send.
-   */
-  /* struct GNUNET_MessageHeader *msg; */
-};
-
-
-/**
- * Struct containing all information regarding a tunnel to a peer.
- */
-struct MeshTunnel2
-{
-    /**
-     * Endpoint of the tunnel.
-     */
-  struct MeshPeer *peer;
-
-    /**
-     * State of the tunnel.
-     */
-  enum MeshTunnelState state;
-
-  /**
-   * Local peer ephemeral private key
-   */
-  struct GNUNET_CRYPTO_EccPrivateKey *my_eph_key;
-
-  /**
-   * Local peer ephemeral public key
-   */
-  struct GNUNET_CRYPTO_EccPublicSignKey *my_eph;
-
-  /**
-   * Remote peer's public key.
-   */
-  struct GNUNET_CRYPTO_EccPublicSignKey *peers_eph;
-
-  /**
-   * Encryption ("our") key.
-   */
-  struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
-
-  /**
-   * Decryption ("their") key.
-   */
-  struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
-
-  /**
-   * Paths that are actively used to reach the destination peer.
-   */
-  struct MeshConnection *connection_head;
-  struct MeshConnection *connection_tail;
-
-  /**
-   * Next connection number.
-   */
-  uint32_t next_cid;
-
-  /**
-   * Channels inside this tunnel.
-   */
-  struct MeshChannel *channel_head;
-  struct MeshChannel *channel_tail;
-
-  /**
-   * Channel ID for the next created channel.
-   */
-  MESH_ChannelNumber next_chid;
-
-  /**
-   * Channel ID for the next incoming channel.
-   */
-  MESH_ChannelNumber next_local_chid;
-
-  /**
-   * Pending message count.
-   */
-  int pending_messages;
-
-  /**
-   * Destroy flag: if true, destroy on last message.
-   */
-  int destroy;
-
-  /**
-   * Queued messages, to transmit once tunnel gets connected.
-   */
-  struct MeshTunnelQueue *tq_head;
-  struct MeshTunnelQueue *tq_tail;
-};
-
-
-
-/******************************************************************************/
-/************************      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
-
-#endif
-
-/******************************************************************************/
-/***********************      GLOBAL VARIABLES     ****************************/
-/******************************************************************************/
-
-/************************** Configuration parameters **************************/
-
-/**
- * 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 peers do we want to remember?
- */
-static unsigned long long max_peers;
-
-/**
- * Percentage of messages that will be dropped (for test purposes only).
- */
-static unsigned long long drop_percent;
-
-/*************************** Static global variables **************************/
-
-/**
- * Peers known, indexed by PeerIdentity (MeshPeer).
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *peers;
-
-/**
- * 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 the statistics service.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * 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;
-
-/**
- * Task to periodically announce itself in the network.
- */
-GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
-
-
-/******************************************************************************/
-/***********************         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 MeshPeer 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 MeshPeer *
-peer_get (const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Retrieve the MeshPeer 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 MeshPeer *
-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 data structs 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);
-
-
-/**
- * Change the tunnel state.
- *
- * @param t Tunnel whose state to change.
- * @param state New state.
- */
-static void
-tunnel_change_state (struct MeshTunnel2 *t, enum MeshTunnelState state);
-
-
-/**
- * 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 MeshTunnel2 *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.
- *
- * @return Connection created.
- */
-static struct MeshConnection *
-tunnel_use_path (struct MeshTunnel2 *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 MeshTunnel2 *t);
-
-/**
- * Destroy the tunnel.
- *
- * This function does not generate any warning traffic to clients or peers.
- *
- * Tasks:
- * Cancel messages belonging to this tunnel queued to neighbors.
- * Free any allocated resources linked to the tunnel.
- *
- * @param t The tunnel to destroy.
- */
-static void
-tunnel_destroy (struct MeshTunnel2 *t);
-
-
-/**
- * Demultiplex by message type and call appropriate handler for a message
- * towards a channel of a local tunnel.
- *
- * @param t Tunnel this message came on.
- * @param msgh Message header.
- * @param fwd Is this message fwd?
- */
-static void
-handle_decrypted (struct MeshTunnel2 *t,
-                  const struct GNUNET_MessageHeader *msgh,
-                  int fwd);
-
-
-/**
- * Dummy function to separate declarations from definitions in function list.
- */
-void
-__mesh_divider______________________________________________________________();
-
-
-/**
- * Get string description for tunnel state.
- *
- * @param s Tunnel state.
- *
- * @return String representation. 
- */
-static const char *
-GNUNET_MESH_DEBUG_TS2S (enum MeshTunnelState s)
-{
-  static char buf[128];
-
-  switch (s)
-  {
-    case MESH_TUNNEL_NEW:
-      return "MESH_TUNNEL_NEW";
-    case MESH_TUNNEL_SEARCHING:
-      return "MESH_TUNNEL_SEARCHING";
-    case MESH_TUNNEL_WAITING:
-      return "MESH_TUNNEL_WAITING";
-    case MESH_TUNNEL_READY:
-      return "MESH_TUNNEL_READY";
-    case MESH_TUNNEL_RECONNECTING:
-      return "MESH_TUNNEL_RECONNECTING";
-
-    default:
-      sprintf (buf, "%u (UNKNOWN STATE)", s);
-      return buf;
-  }
-}
-
-
-/**
- * Get string description for tunnel state.
- *
- * @param s Tunnel state.
- *
- * @return String representation. 
- */
-static const char *
-GNUNET_MESH_DEBUG_CS2S (enum MeshTunnelState s)
-{
-  switch (s) 
-  {
-    case MESH_CONNECTION_NEW:
-      return "MESH_CONNECTION_NEW";
-    case MESH_CONNECTION_SENT:
-      return "MESH_CONNECTION_SENT";
-    case MESH_CONNECTION_ACK:
-      return "MESH_CONNECTION_ACK";
-    case MESH_CONNECTION_READY:
-      return "MESH_CONNECTION_READY";
-    default:
-      return "MESH_CONNECTION_STATE_ERROR";
-  }
-}
-
-
-
-/******************************************************************************/
-/************************    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;
-  struct GNUNET_HashCode phash;
-
-  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_CRYPTO_hash (&my_full_id, sizeof (struct GNUNET_PeerIdentity), &phash);
-  GNUNET_DHT_put (dht_handle,   /* DHT handle */
-                  &phash,       /* 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      ************************/
-/******************************************************************************/
-
-
-/**
- * Get the static string for a peer ID.
- *
- * @param peer Peer.
- *
- * @return Static string for it's ID.
- */
-static const char *
-peer2s (const struct MeshPeer *peer)
-{
-  if (NULL == peer)
-    return "(NULL)";
-  return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
-}
-
-
-
-/**
- * Count established (ready) connections of a tunnel.
- *
- * @param t Tunnel on which to send the message.
- *
- * @return Number of connections.
- */
-static unsigned int
-tunnel_count_connections (struct MeshTunnel2 *t)
-{
-  struct MeshConnection *c;
-  unsigned int i;
-
-  for (c = t->connection_head, i = 0; NULL != c; c = c->next, i++);
-
-  return i;
-}
-
-
-/**
- * Pick a connection on which send the next data message.
- *
- * @param t Tunnel on which to send the message.
- * @param fwd Is this a fwd message?
- *
- * @return The connection on which to send the next message.
- */
-static struct MeshConnection *
-tunnel_get_connection (struct MeshTunnel2 *t, int fwd)
-{
-  struct MeshConnection *c;
-  struct MeshConnection *best;
-  struct MeshFlowControl *fc;
-  unsigned int lowest_q;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n",
-              peer2s (t->peer));
-  best = NULL;
-  lowest_q = UINT_MAX;
-  for (c = t->connection_head; NULL != c; c = c->next)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  connection %s: %u\n",
-                GNUNET_h2s (&c->id), c->state);
-    if (MESH_CONNECTION_READY == c->state)
-    {
-      fc = fwd ? &c->fwd_fc : &c->bck_fc;
-      if (NULL == fc)
-      {
-        GNUNET_break (0);
-        continue;
-      }
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    q_n %u, \n", fc->queue_n);
-      if (fc->queue_n < lowest_q)
-      {
-        best = c;
-        lowest_q = fc->queue_n;
-      }
-    }
-  }
-  return best;
-}
-
-
-
-
-/**
- * Get the total buffer space for a tunnel.
- *
- * @param t Tunnel.
- * @param fwd Is this for FWD traffic?
- *
- * @return Buffer space offered by all connections in the tunnel.
- */
-static unsigned int
-tunnel_get_buffer (struct MeshTunnel2 *t, int fwd)
-{
-  struct MeshConnection *c;
-  struct MeshFlowControl *fc;
-  unsigned int buffer;
-
-  c = t->connection_head;
-  buffer = 0;
-
-  /* If terminal, return biggest channel buffer */
-  if (NULL == c || GMC_is_terminal (c, fwd))
-  {
-    struct MeshChannel *ch;
-    unsigned int ch_buf;
-
-    if (NULL == t->channel_head)
-      return 64;
-
-    for (ch = t->channel_head; NULL != ch; ch = ch->next)
-    {
-      ch_buf = channel_get_buffer (ch, fwd);
-      if (ch_buf > buffer)
-        buffer = ch_buf;
-    }
-    return buffer;
-  }
-
-  /* If not terminal, return sum of connection buffers */
-  while (NULL != c)
-  {
-    if (c->state != MESH_CONNECTION_READY)
-    {
-      c = c->next;
-      continue;
-    }
-
-    fc = fwd ? &c->fwd_fc : &c->bck_fc;
-    buffer += fc->queue_max - fc->queue_n;
-    c = c->next;
-  }
-
-  return buffer;
-}
-
-
-/**
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME 
- * Encrypt data with the tunnel key.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the encrypted data.
- * @param src Source of the plaintext.
- * @param size Size of the plaintext.
- * @param iv Initialization Vector to use.
- * @param fwd Is this a fwd message?
- */
-static void
-tunnel_encrypt (struct MeshTunnel2 *t,
-                void *dst, const void *src,
-                size_t size, uint64_t iv, int fwd)
-{
-  memcpy (dst, src, size);
-}
-
-
-/**
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME 
- * Decrypt data with the tunnel key.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the plaintext.
- * @param src Source of the encrypted data.
- * @param size Size of the encrypted data.
- * @param iv Initialization Vector to use.
- * @param fwd Is this a fwd message?
- */
-static void
-tunnel_decrypt (struct MeshTunnel2 *t,
-                void *dst, const void *src,
-                size_t size, uint64_t iv, int fwd)
-{
-  memcpy (dst, src, size);
-}
-
-
-/**
- * Sends an already built message on a tunnel, choosing the best connection.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param ch Channel on which this message is transmitted.
- * @param fwd Is this a fwd message?
- */
-static void
-send_prebuilt_message_tunnel (struct GNUNET_MESH_Encrypted *msg,
-                              struct MeshTunnel2 *t,
-                              struct MeshChannel *ch,
-                              int fwd)
-{
-  struct MeshConnection *c;
-  uint16_t type;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send on Tunnel %s\n",
-              peer2s (t->peer));
-  c = tunnel_get_connection (t, fwd);
-  if (NULL == c)
-  {
-    GNUNET_break (GNUNET_YES == t->destroy);
-    return;
-  }
-  type = ntohs (msg->header.type);
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_FWD:
-    case GNUNET_MESSAGE_TYPE_MESH_BCK:
-    case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
-      msg->cid = c->id;
-      msg->ttl = htonl (default_ttl);
-      break;
-    default:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
-                  GNUNET_MESH_DEBUG_M2S (type));
-      GNUNET_break (0);
-  }
-  msg->reserved = 0;
-
-  send_prebuilt_message_connection (&msg->header, c, ch, fwd);
-}
-
-
-
-/**
- * Sends a CREATE CONNECTION message for a path to a peer.
- * Changes the connection and tunnel states if necessary.
- *
- * @param connection Connection to create.
- */
-static void
-send_connection_create (struct MeshConnection *connection)
-{
-  struct MeshTunnel2 *t;
-
-  t = connection->t;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
-  queue_add (NULL,
-             GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
-             sizeof (struct GNUNET_MESH_ConnectionCreate) +
-                (connection->path->length *
-                 sizeof (struct GNUNET_PeerIdentity)),
-             connection,
-             NULL,
-             GNUNET_YES);
-  if (NULL != t &&
-      (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
-    tunnel_change_state (t, MESH_TUNNEL_WAITING);
-  if (MESH_CONNECTION_NEW == connection->state)
-    connection_change_state (connection, MESH_CONNECTION_SENT);
-}
-
-
-/**
- * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
- * directed to us.
- *
- * @param connection Connection to confirm.
- * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
- */
-static void
-send_connection_ack (struct MeshConnection *connection, int fwd) 
-{
-  struct MeshTunnel2 *t;
-
-  t = connection->t;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
-  queue_add (NULL,
-             GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
-             sizeof (struct GNUNET_MESH_ConnectionACK),
-             connection,
-             NULL,
-             fwd);
-  if (MESH_TUNNEL_NEW == t->state)
-    tunnel_change_state (t, MESH_TUNNEL_WAITING);
-  if (MESH_CONNECTION_READY != connection->state)
-    connection_change_state (connection, MESH_CONNECTION_SENT);
-}
-
-
-/**
-  * 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;
-}
-
-
-/**
- * Function to send a create connection message to a peer.
- *
- * @param c Connection to create.
- * @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_connection_create (struct MeshConnection *c, size_t size, void *buf)
-{
-  struct GNUNET_MESH_ConnectionCreate *msg;
-  struct GNUNET_PeerIdentity *peer_ptr;
-  struct MeshPeerPath *p = c->path;
-  size_t size_needed;
-  int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
-  size_needed =
-      sizeof (struct GNUNET_MESH_ConnectionCreate) +
-      p->length * sizeof (struct GNUNET_PeerIdentity);
-
-  if (size < size_needed || NULL == buf)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg = (struct GNUNET_MESH_ConnectionCreate *) buf;
-  msg->header.size = htons (size_needed);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE);
-  msg->cid = c->id;
-
-  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,
-              "CONNECTION CREATE (%u bytes long) sent!\n", size_needed);
-  return size_needed;
-}
-
-
-/**
- * Creates a path ack message in buf and frees all unused resources.
- *
- * @param c Connection to send an ACK on.
- * @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_connection_ack (struct MeshConnection *c, size_t size, void *buf)
-{
-  struct GNUNET_MESH_ConnectionACK *msg = buf;
-  struct MeshTunnel2 *t = c->t;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
-  GNUNET_assert (NULL != t);
-  if (sizeof (struct GNUNET_MESH_ConnectionACK) > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK);
-  msg->cid = c->id;
-  msg->reserved = 0;
-
-  /* TODO add signature */
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
-  return sizeof (struct GNUNET_MESH_ConnectionACK);
-}
-
-
-/**
- * Destroy the peer_info and free any allocated resources linked to it
- *
- * @param peer The peer_info to destroy.
- *
- * @return GNUNET_OK on success
- */
-static int
-peer_destroy (struct MeshPeer *peer)
-{
-  struct GNUNET_PeerIdentity id;
-  struct MeshPeerPath *p;
-  struct MeshPeerPath *nextp;
-
-  GNUNET_PEER_resolve (peer->id, &id);
-  GNUNET_PEER_change_rc (peer->id, -1);
-
-  if (GNUNET_YES !=
-      GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
-  {
-    GNUNET_break (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "removing peer %s, not in peermap\n", GNUNET_i2s (&id));
-  }
-  if (NULL != peer->dhtget)
-  {
-    GNUNET_DHT_get_stop (peer->dhtget);
-  }
-  p = peer->path_head;
-  while (NULL != p)
-  {
-    nextp = p->next;
-    GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
-    path_destroy (p);
-    p = nextp;
-  }
-  tunnel_destroy_empty (peer->tunnel);
-  GNUNET_free (peer);
-  return GNUNET_OK;
-}
-
-
-/**
- * Returns if peer is used (has a tunnel, is neighbor).
- *
- * @peer Peer to check.
- *
- * @return GNUNET_YES if peer is in use.
- */
-static int
-peer_is_used (struct MeshPeer *peer)
-{
-  struct MeshPeerPath *p;
-
-  if (NULL != peer->tunnel)
-    return GNUNET_YES;
-
-  for (p = peer->path_head; NULL != p; p = p->next)
-  {
-    if (p->length < 3)
-      return GNUNET_YES;
-  }
-  return GNUNET_NO;
-}
-
-
-/**
- * Iterator over all the peers to get the oldest timestamp.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- */
-static int
-peer_get_oldest (void *cls,
-                 const struct GNUNET_PeerIdentity *key,
-                 void *value)
-{
-  struct MeshPeer *p = value;
-  struct GNUNET_TIME_Absolute *abs = cls;
-
-  /* Don't count active peers */
-  if (GNUNET_YES == peer_is_used (p))
-    return GNUNET_YES;
-
-  if (abs->abs_value_us < p->last_contact.abs_value_us)
-    abs->abs_value_us = p->last_contact.abs_value_us;
-
-  return GNUNET_YES;
-}
-
-
-/**
- * Iterator over all the peers to remove the oldest entry.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- */
-static int
-peer_timeout (void *cls,
-              const struct GNUNET_PeerIdentity *key,
-              void *value)
-{
-  struct MeshPeer *p = value;
-  struct GNUNET_TIME_Absolute *abs = cls;
-
-  if (p->last_contact.abs_value_us == abs->abs_value_us &&
-      GNUNET_NO == peer_is_used (p))
-  {
-    peer_destroy (p);
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-
-
-/**
- * Delete oldest unused peer.
- */
-static void
-peer_delete_oldest (void)
-{
-  struct GNUNET_TIME_Absolute abs;
-
-  abs = GNUNET_TIME_UNIT_FOREVER_ABS;
-
-  GNUNET_CONTAINER_multipeermap_iterate (peers,
-                                         &peer_get_oldest,
-                                         &abs);
-  GNUNET_CONTAINER_multipeermap_iterate (peers,
-                                         &peer_timeout,
-                                         &abs);
-}
-
-
-/**
- * Retrieve the MeshPeer 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 MeshPeer *
-peer_get (const struct GNUNET_PeerIdentity *peer_id)
-{
-  struct MeshPeer *peer;
-
-  peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
-  if (NULL == peer)
-  {
-    peer = GNUNET_new (struct MeshPeer);
-    if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
-    {
-      peer_delete_oldest ();
-    }
-    GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
-                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-    peer->id = GNUNET_PEER_intern (peer_id);
-  }
-  peer->last_contact = GNUNET_TIME_absolute_get();
-
-  return peer;
-}
-
-
-/**
- * Retrieve the MeshPeer 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 MeshPeer *
-peer_get_short (const GNUNET_PEER_Id peer)
-{
-  return peer_get (GNUNET_PEER_resolve2 (peer));
-}
-
-
-/**
- * Get a cost of a path for a peer considering existing tunnel connections.
- *
- * @param peer Peer towards which the path is considered.
- * @param path Candidate path.
- *
- * @return Cost of the path (path length + number of overlapping nodes)
- */
-static unsigned int
-peer_get_path_cost (const struct MeshPeer *peer,
-                    const struct MeshPeerPath *path)
-{
-  struct MeshConnection *c;
-  unsigned int overlap;
-  unsigned int i;
-  unsigned int j;
-
-  if (NULL == path)
-    return 0;
-
-  overlap = 0;
-  GNUNET_assert (NULL != peer->tunnel);
-
-  for (i = 0; i < path->length; i++)
-  {
-    for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
-    {
-      for (j = 0; j < c->path->length; j++)
-      {
-        if (path->peers[i] == c->path->peers[j])
-        {
-          overlap++;
-          break;
-        }
-      }
-    }
-  }
-  return (path->length + overlap) * (path->score * -1);
-}
-
-
-/**
- * Choose the best path towards a peer considering the tunnel properties.
- *
- * @param peer The destination peer.
- *
- * @return Best current known path towards the peer, if any.
- */
-static struct MeshPeerPath *
-peer_get_best_path (const struct MeshPeer *peer)
-{
-  struct MeshPeerPath *best_p;
-  struct MeshPeerPath *p;
-  struct MeshConnection *c;
-  unsigned int best_cost;
-  unsigned int cost;
-
-  best_cost = UINT_MAX;
-  best_p = NULL;
-  for (p = peer->path_head; NULL != p; p = p->next)
-  {
-    for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
-      if (c->path == p)
-        break;
-    if (NULL != c)
-      continue; /* If path is in use in a connection, skip it. */
-
-    if ((cost = peer_get_path_cost (peer, p)) < best_cost)
-    {
-      best_cost = cost;
-      best_p = p;
-    }
-  }
-  return best_p;
-}
-
-
-
-/**
- * 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 CONNECTION towards it.
- *
- * @param peer PeerInfo of the peer.
- */
-static void
-peer_connect (struct MeshPeer *peer)
-{
-  struct MeshTunnel2 *t;
-  struct MeshPeerPath *p;
-  struct MeshConnection *c;
-  int rerun_dhtget;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "peer_connect towards %s\n",
-              peer2s (peer));
-  t = peer->tunnel;
-  c = NULL;
-  rerun_dhtget = GNUNET_NO;
-
-  if (NULL != peer->path_head)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "path exists\n");
-    p = peer_get_best_path (peer);
-    if (NULL != p)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %u hops\n", p->length);
-      c = tunnel_use_path (t, p);
-      if (NULL == c)
-      {
-        /* This case can happen when the path includes a first hop that is
-         * not yet known to be connected.
-         * 
-         * This happens quite often during testing when running mesh
-         * under valgrind: core connect notifications come very late and the
-         * DHT result has already come and created a valid path.
-         * In this case, the peer->connections hashmap will be NULL and
-         * tunnel_use_path will not be able to create a connection from that
-         * path.
-         *
-         * Re-running the DHT GET should give core time to callback.
-         */
-        GNUNET_break(0);
-        rerun_dhtget = GNUNET_YES;
-      }
-      else
-      {
-        send_connection_create (c);
-        return;
-      }
-    }
-  }
-
-  if (NULL != peer->dhtget && GNUNET_YES == rerun_dhtget)
-  {
-    GNUNET_DHT_get_stop (peer->dhtget);
-    peer->dhtget = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Stopping DHT GET for peer %s\n", peer2s (peer));
-  }
-
-  if (NULL == peer->dhtget)
-  {
-    const struct GNUNET_PeerIdentity *id;
-    struct GNUNET_HashCode phash;
-
-    id = GNUNET_PEER_resolve2 (peer->id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "  Starting DHT GET for peer %s\n", peer2s (peer));
-    GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &phash);
-    peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
-                                         GNUNET_BLOCK_TYPE_MESH_PEER, /* type */
-                                         &phash,     /* 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);
-    if (MESH_TUNNEL_NEW == t->state)
-      tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
-  }
-}
-
-
-
-/**
- * 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_add_path (struct MeshPeer *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));
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
-              path->length, peer2s (peer_info));
-
-  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_add_path_to_origin (struct MeshPeer *peer_info,
-                         struct MeshPeerPath *path, int trusted)
-{
-  if (NULL == path)
-    return;
-  path_invert (path);
-  peer_add_path (peer_info, path, trusted);
-}
-
-/**
- * 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 MeshPeer *aux;
-    struct MeshPeerPath *copy;
-
-    aux = peer_get_short (p->peers[i]);
-    copy = path_duplicate (p);
-    copy->length = i + 1;
-    peer_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
-  }
-}
-
-
-#if 0
-static void
-fc_debug (struct MeshFlowControl *fc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
-              fc->last_pid_recv, fc->last_ack_sent);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
-              fc->last_pid_sent, fc->last_ack_recv);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
-              fc->queue_n, fc->queue_max);
-}
-
-static void
-connection_debug (struct MeshConnection *c)
-{
-  if (NULL == c)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
-              peer2s (c->t->peer), GNUNET_h2s (&c->id));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n", 
-              c->state, c->pending_messages);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
-  fc_debug (&c->fwd_fc);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
-  fc_debug (&c->bck_fc);
-}
-
-#endif
-
-
-/**
- * Change the tunnel state.
- *
- * @param t Tunnel whose state to change.
- * @param state New state.
- */
-static void
-tunnel_change_state (struct MeshTunnel2* t, enum MeshTunnelState state)
-{
-  if (NULL == t)
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Tunnel %s state was %s\n",
-              peer2s (t->peer),
-              GNUNET_MESH_DEBUG_TS2S (t->state));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Tunnel %s state is now %s\n",
-              peer2s (t->peer),
-              GNUNET_MESH_DEBUG_TS2S (state));
-  t->state = state;
-}
-
-
-/**
- * Send all cached messages that we can, tunnel is online.
- *
- * @param t Tunnel that holds the messages.
- * @param fwd Is this fwd?
- */
-static void
-tunnel_send_queued_data (struct MeshTunnel2 *t, int fwd)
-{
-  struct MeshTunnelQueue *tq;
-  struct MeshTunnelQueue *next;
-  unsigned int room;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "tunnel_send_queued_data on tunnel %s\n",
-              peer2s (t->peer));
-  room = tunnel_get_buffer (t, fwd);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  buffer space: %u\n", room);
-  for (tq = t->tq_head; NULL != tq && room > 0; tq = next)
-  {
-    next = tq->next;
-    room--;
-    GNUNET_CONTAINER_DLL_remove (t->tq_head, t->tq_tail, tq);
-    send_prebuilt_message_channel ((struct GNUNET_MessageHeader *) &tq[1],
-                                   tq->ch, fwd);
-
-    GNUNET_free (tq);
-  }
-}
-
-
-/**
- * Cache a message to be sent once tunnel is online.
- *
- * @param t Tunnel to hold the message.
- * @param ch Channel the message is about.
- * @param msg Message itself (copy will be made).
- * @param fwd Is this fwd?
- */
-static void
-tunnel_queue_data (struct MeshTunnel2 *t,
-                   struct MeshChannel *ch,
-                   struct GNUNET_MessageHeader *msg,
-                   int fwd)
-{
-  struct MeshTunnelQueue *tq;
-  uint16_t size = ntohs (msg->size);
-
-  tq = GNUNET_malloc (sizeof (struct MeshTunnelQueue) + size);
-
-  tq->ch = ch;
-  memcpy (&tq[1], msg, size);
-  GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tq);
-
-  if (MESH_TUNNEL_READY == t->state)
-    tunnel_send_queued_data (t, fwd);
-}
-
-
-
-
-
-static struct MeshConnection *
-tunnel_use_path (struct MeshTunnel2 *t, struct MeshPeerPath *p)
-{
-  struct MeshConnection *c;
-  struct GNUNET_HashCode cid;
-  struct MeshPeer *peer;
-  unsigned int own_pos;
-
-  if (NULL == t || NULL == p)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE, &cid);
-
-  c = connection_new (&cid);
-  c->t = t;
-  GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, c);
-  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);
-    connection_destroy (c);
-    return NULL;
-  }
-  c->own_pos = own_pos;
-  c->path = p;
-
-  if (0 == own_pos)
-  {
-    c->fwd_maintenance_task =
-        GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
-                                      &connection_fwd_keepalive, c);
-  }
-
-  peer = connection_get_next_hop (c);
-  if (NULL == peer->connections)
-  {
-    connection_destroy (c);
-    return NULL;
-  }
-  GNUNET_CONTAINER_multihashmap_put (peer->connections, &c->id, c,
-                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-  peer = connection_get_prev_hop (c);
-  if (NULL == peer->connections)
-  {
-    connection_destroy (c);
-    return NULL;
-  }
-  GNUNET_CONTAINER_multihashmap_put (peer->connections, &c->id, c,
-                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-  return c;
-}
-
-
-/**
- * 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.
- * 
- * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME 
- *
- * @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 MeshTunnel2* 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;
-}
-
-
-
-
-/**
- * Send an ACK on the appropriate connection/channel, depending on
- * the direction and the position of the peer.
- *
- * @param c Which connection to send the hop-by-hop ACK.
- * @param ch Channel, if any.
- * @param fwd Is this a fwd ACK? (will go dest->root)
- */
-static void
-send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
-{
-  unsigned int buffer;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "send ack %s on %p %p\n",
-              fwd ? "FWD" : "BCK", c, ch);
-  if (NULL == c || GMC_is_terminal (c, fwd))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  getting from all connections\n");
-    buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
-    buffer = connection_get_buffer (c, fwd);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
-
-  if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
-       (NULL != c && connection_is_origin (c, fwd)) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
-    if (0 < buffer)
-    {
-      GNUNET_assert (NULL != ch);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  really sending!\n");
-      send_local_ack (ch, fwd);
-    }
-  }
-  else if (NULL == c)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  sending on all connections\n");
-    GNUNET_assert (NULL != ch);
-    channel_send_connections_ack (ch, buffer, fwd);
-  }
-  else 
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
-    connection_send_ack (c, buffer, fwd);
-  }
-}
-
-
-
-
-/**
- * Confirm we got a channel create.
- *
- * @param ch The channel to confirm.
- * @param fwd Should we send the ACK fwd?
- */
-static void
-channel_send_ack (struct MeshChannel *ch, int fwd)
-{
-  struct GNUNET_MESH_ChannelManage msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  sending channel %s ack for channel %s:%X\n",
-              fwd ? "FWD" : "BCK", peer2s (ch->t->peer),
-              ch->gid);
-
-  msg.chid = htonl (ch->gid);
-  send_prebuilt_message_channel (&msg.header, ch, !fwd);
-}
-
-
-/**
- * Send a message to all clients (local and remote) of this channel
- * notifying that the channel is no longer valid.
- *
- * If some peer or client should not receive the message,
- * should be zero'ed out before calling this function.
- *
- * @param ch The channel whose clients to notify.
- */
-static void
-channel_send_destroy (struct MeshChannel *ch)
-{
-  struct GNUNET_MESH_ChannelManage msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  sending channel destroy for channel %s:%X\n",
-              peer2s (ch->t->peer),
-              ch->gid);
-
-  if (channel_is_terminal (ch, GNUNET_NO))
-  {
-    if (NULL != ch->root && GNUNET_NO == ch->root->shutting_down)
-    {
-      msg.chid = htonl (ch->lid_root);
-      send_local_channel_destroy (ch, GNUNET_NO);
-    }
-  }
-  else
-  {
-    msg.chid = htonl (ch->gid);
-    send_prebuilt_message_channel (&msg.header, ch, GNUNET_NO);
-  }
-
-  if (channel_is_terminal (ch, GNUNET_YES))
-  {
-    if (NULL != ch->dest && GNUNET_NO == ch->dest->shutting_down)
-    {
-      msg.chid = htonl (ch->lid_dest);
-      send_local_channel_destroy (ch, GNUNET_YES);
-    }
-  }
-  else
-  {
-    msg.chid = htonl (ch->gid);
-    send_prebuilt_message_channel (&msg.header, ch, GNUNET_YES);
-  }
-}
-
-
-/**
- * Create a tunnel.
- */
-static struct MeshTunnel2 *
-tunnel_new (void)
-{
-  struct MeshTunnel2 *t;
-
-  t = GNUNET_new (struct MeshTunnel2);
-  t->next_chid = 0;
-  t->next_local_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
-//   if (GNUNET_OK !=
-//       GNUNET_CONTAINER_multihashmap_put (tunnels, tid, t,
-//                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-//   {
-//     GNUNET_break (0);
-//     tunnel_destroy (t);
-//     return NULL;
-//   }
-
-//   char salt[] = "salt";
-//   GNUNET_CRYPTO_kdf (&t->e_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-//                      salt, sizeof (salt),
-//                      &t->e_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-//                      &my_full_id, sizeof (struct GNUNET_PeerIdentity),
-//                      GNUNET_PEER_resolve2 (t->peer->id), sizeof (struct GNUNET_PeerIdentity),
-//                      NULL);
-//   GNUNET_CRYPTO_kdf (&t->d_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-//                      salt, sizeof (salt),
-//                      &t->d_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-//                      GNUNET_PEER_resolve2 (t->peer->id), sizeof (struct GNUNET_PeerIdentity),
-//                      &my_full_id, sizeof (struct GNUNET_PeerIdentity),
-//                      NULL);
-
-  return t;
-}
-
-
-/**
- * Add a connection to a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-static void
-tunnel_add_connection (struct MeshTunnel2 *t, struct MeshConnection *c)
-{
-  struct MeshConnection *aux;
-  c->t = t;
-  for (aux = t->connection_head; aux != NULL; aux = aux->next)
-    if (aux == c)
-      return;
-  GNUNET_CONTAINER_DLL_insert_tail (t->connection_head, t->connection_tail, c);
-}
-
-
-
-static void
-tunnel_destroy (struct MeshTunnel2 *t)
-{
-  struct MeshConnection *c;
-  struct MeshConnection *next;
-
-  if (NULL == t)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n",
-              peer2s (t->peer));
-
-//   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &t->id, t))
-//     GNUNET_break (0);
-
-  for (c = t->connection_head; NULL != c; c = next)
-  {
-    next = c->next;
-    connection_destroy (c);
-  }
-
-  GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
-  t->peer->tunnel = NULL;
-
-  GNUNET_free (t);
-}
-
-
-/**
- * Tunnel is empty: destroy it.
- *
- * Notifies all connections about the destruction.
- *
- * @param t Tunnel to destroy. 
- */
-static void
-tunnel_destroy_empty (struct MeshTunnel2 *t)
-{
-  struct MeshConnection *c;
-
-  for (c = t->connection_head; NULL != c; c = c->next)
-  {
-    if (GNUNET_NO == c->destroy)
-      connection_send_destroy (c);
-  }
-
-  if (0 == t->pending_messages)
-    tunnel_destroy (t);
-  else
-    t->destroy = GNUNET_YES;
-}
-
-
-/**
- * Destroy tunnel if empty (no more channels).
- *
- * @param t Tunnel to destroy if empty.
- */
-static void
-tunnel_destroy_if_empty (struct MeshTunnel2 *t)
-{
-  if (NULL != t->channel_head)
-    return;
-
-  tunnel_destroy_empty (t);
-}
-
-
-/******************************************************************************/
-/****************      MESH NETWORK HANDLER HELPERS     ***********************/
-/******************************************************************************/
-
-
-
-
-
-
-/******************************************************************************/
-/********************      MESH NETWORK HANDLERS     **************************/
-/******************************************************************************/
-
-
-/**
- * Generic handler for mesh network payload traffic.
- *
- * @param t Tunnel on which we got this message.
- * @param message Unencryted data message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
- */
-static void
-handle_data (struct MeshTunnel2 *t, const struct GNUNET_MESH_Data *msg, int fwd)
-{
-  struct MeshChannelReliability *rel;
-  struct MeshChannel *ch;
-  struct MeshClient *c;
-  uint32_t mid;
-  uint16_t type;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size <
-      sizeof (struct GNUNET_MESH_Data) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  type = ntohs (msg->header.type);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message\n",
-              GNUNET_MESH_DEBUG_M2S (type));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n",
-              GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
-
-  /* Check channel */
-  ch = channel_get (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats, "# data on unknown channel", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-                ntohl (msg->chid));
-    return;
-  }
-
-  /*  Initialize FWD/BCK data */
-  c   = fwd ? ch->dest     : ch->root;
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  tunnel_change_state (t, MESH_TUNNEL_READY);
-
-  GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO);
-
-  mid = ntohl (msg->mid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " mid %u\n", mid);
-
-  if (GNUNET_NO == ch->reliable ||
-      ( !GMC_is_pid_bigger (rel->mid_recv, mid) &&
-        GMC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! RECV %u\n", mid);
-    if (GNUNET_YES == ch->reliable)
-    {
-      /* Is this the exact next expected messasge? */
-      if (mid == rel->mid_recv)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "as expected\n");
-        rel->mid_recv++;
-        channel_send_client_data (ch, msg, fwd);
-      }
-      else
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
-        channel_rel_add_buffered_data (msg, rel);
-      }
-    }
-    else
-    {
-      /* Tunnel is unreliable: send to clients directly */
-      /* FIXME: accept Out Of Order traffic */
-      rel->mid_recv = mid + 1;
-      channel_send_client_data (ch, msg, fwd);
-    }
-  }
-  else
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " MID %u not expected (%u - %u), dropping!\n",
-                mid, rel->mid_recv, rel->mid_recv + 64);
-  }
-
-  channel_send_data_ack (ch, fwd);
-}
-
-/**
- * Handler for mesh network traffic end-to-end ACKs.
- *
- * @param t Tunnel on which we got this message.
- * @param message Data message.
- * @param fwd Is this a fwd ACK? (dest->orig)
- */
-static void
-handle_data_ack (struct MeshTunnel2 *t,
-                 const struct GNUNET_MESH_DataACK *msg, int fwd)
-{
-  struct MeshChannelReliability *rel;
-  struct MeshReliableMessage *copy;
-  struct MeshReliableMessage *next;
-  struct MeshChannel *ch;
-  uint32_t ack;
-  uint16_t type;
-  int work;
-
-  type = ntohs (msg->header.type);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a %s message!\n",
-              GNUNET_MESH_DEBUG_M2S (type));
-  ch = channel_get (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats, "# ack on unknown channel", 1, GNUNET_NO);
-    return;
-  }
-  ack = ntohl (msg->mid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! %s ACK %u\n",
-              (GNUNET_YES == fwd) ? "FWD" : "BCK", ack);
-
-  if (GNUNET_YES == fwd)
-  {
-    rel = ch->root_rel;
-  }
-  else
-  {
-    rel = ch->dest_rel;
-  }
-  if (NULL == rel)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
-  {
-    if (GMC_is_pid_bigger (copy->mid, ack))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!!  head %u, out!\n", copy->mid);
-      channel_rel_free_sent (rel, msg);
-      break;
-    }
-    work = GNUNET_YES;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!!  id %u\n", copy->mid);
-    next = copy->next;
-    rel_message_free (copy);
-  }
-  /* ACK client if needed */
-//   channel_send_ack (t, type, GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK == type);
-
-  /* If some message was free'd, update the retransmission delay*/
-  if (GNUNET_YES == work)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
-    {
-      GNUNET_SCHEDULER_cancel (rel->retry_task);
-      if (NULL == rel->head_sent)
-      {
-        rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-      }
-      else
-      {
-        struct GNUNET_TIME_Absolute new_target;
-        struct GNUNET_TIME_Relative delay;
-
-        delay = GNUNET_TIME_relative_multiply (rel->retry_timer,
-                                               MESH_RETRANSMIT_MARGIN);
-        new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp,
-                                               delay);
-        delay = GNUNET_TIME_absolute_get_remaining (new_target);
-        rel->retry_task =
-            GNUNET_SCHEDULER_add_delayed (delay,
-                                          &channel_retransmit_message,
-                                          rel);
-      }
-    }
-    else
-      GNUNET_break (0);
-  }
-}
-
-
-/**
- * Core handler for connection creation.
  *
- * @param cls Closure (unused).
- * @param peer Sender (neighbor).
- * @param message Message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_connection_create (void *cls,
-                               const struct GNUNET_PeerIdentity *peer,
-                               const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectionCreate *msg;
-  struct GNUNET_PeerIdentity *id;
-  struct GNUNET_HashCode *cid;
-  struct MeshPeerPath *path;
-  struct MeshPeer *dest_peer;
-  struct MeshPeer *orig_peer;
-  struct MeshConnection *c;
-  unsigned int own_pos;
-  uint16_t size;
-  uint16_t i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
-
-  /* Check size */
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Calculate hops */
-  size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
-  if (size % sizeof (struct GNUNET_PeerIdentity))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  size /= sizeof (struct GNUNET_PeerIdentity);
-  if (1 > size)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
-
-  /* Get parameters */
-  msg = (struct GNUNET_MESH_ConnectionCreate *) message;
-  cid = &msg->cid;
-  id = (struct GNUNET_PeerIdentity *) &msg[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "    connection %s (%s).\n",
-              GNUNET_h2s (cid), GNUNET_i2s (id));
-
-  /* Create connection */
-  c = connection_get (cid);
-  if (NULL == c)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
-    c = connection_new (cid);
-    if (NULL == c)
-      return GNUNET_OK;
-    connection_reset_timeout (c, GNUNET_YES);
-
-    /* Create path */
-    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 (&id[i]));
-      path->peers[i] = GNUNET_PEER_intern (&id[i]);
-      if (path->peers[i] == myid)
-        own_pos = i;
-    }
-    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);
-      connection_destroy (c);
-      return GNUNET_OK;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
-    path_add_to_peers (path, GNUNET_NO);
-    c->path = path_duplicate (path);
-    c->own_pos = own_pos;
-  }
-  else
-  {
-    path = NULL;
-  }
-  if (MESH_CONNECTION_NEW == c->state)
-    connection_change_state (c, MESH_CONNECTION_SENT);
-
-  /* Remember peers */
-  dest_peer = peer_get (&id[size - 1]);
-  orig_peer = peer_get (&id[0]);
-
-  /* Is it a connection to us? */
-  if (c->own_pos == size - 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
-    peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
-
-    if (NULL == orig_peer->tunnel)
-    {
-      orig_peer->tunnel = tunnel_new ();
-      orig_peer->tunnel->peer = orig_peer;
-    }
-    tunnel_add_connection (orig_peer->tunnel, c);
-    if (MESH_TUNNEL_NEW == c->t->state)
-      tunnel_change_state (c->t,  MESH_TUNNEL_WAITING);
-
-    send_connection_ack (c, GNUNET_NO);
-    if (MESH_CONNECTION_SENT == c->state)
-      connection_change_state (c, MESH_CONNECTION_ACK);
-
-    /* Keep tunnel alive in direction dest->owner*/
-    connection_reset_timeout (c, GNUNET_NO);
-  }
-  else
-  {
-    /* It's for somebody else! Retransmit. */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
-    peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
-    peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
-    send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
-  }
-  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_connection_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectionACK *msg;
-  struct MeshConnection *c;
-  struct MeshPeerPath *p;
-  struct MeshPeer *pi;
-  int fwd;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
-  msg = (struct GNUNET_MESH_ConnectionACK *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s\n",
-              GNUNET_h2s (&msg->cid));
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# control on unknown connection",
-                              1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
-    return GNUNET_OK;
-  }
-
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
-              GNUNET_i2s (peer));
-  pi = peer_get (peer);
-  if (connection_get_next_hop (c) == pi)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
-    fwd = GNUNET_NO;
-    if (MESH_CONNECTION_SENT == c->state)
-      connection_change_state (c, MESH_CONNECTION_ACK);
-  }
-  else if (connection_get_prev_hop (c) == pi)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
-    fwd = GNUNET_YES;
-    connection_change_state (c, MESH_CONNECTION_READY);
-  }
-  else
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  connection_reset_timeout (c, fwd);
-
-  /* Add path to peers? */
-  p = c->path;
-  if (NULL != p)
-  {
-    path_add_to_peers (p, GNUNET_YES);
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-
-  /* Message for us as creator? */
-  if (connection_is_origin (c, GNUNET_YES))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
-    connection_change_state (c, MESH_CONNECTION_READY);
-    if (MESH_TUNNEL_READY != c->t->state)
-      tunnel_change_state (c->t, MESH_TUNNEL_READY);
-    send_connection_ack (c, GNUNET_YES);
-    tunnel_send_queued_data (c->t, GNUNET_YES);
-    if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
-    {
-      GNUNET_DHT_get_stop (c->t->peer->dhtget);
-      c->t->peer->dhtget = NULL;
-    }
-    return GNUNET_OK;
-  }
-
-  /* Message for us as destination? */
-  if (GMC_is_terminal (c, GNUNET_YES))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
-    if (MESH_TUNNEL_READY != c->t->state)
-      tunnel_change_state (c->t, MESH_TUNNEL_READY);
-    connection_change_state (c, MESH_CONNECTION_READY);
-    tunnel_send_queued_data (c->t, GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-  send_prebuilt_message_connection (message, c, NULL, fwd);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for notifications of broken paths
- *
- * @param cls Closure (unused).
- * @param peer Peer identity of sending neighbor.
- * @param message Message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_connection_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
-                               const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectionBroken *msg;
-  struct MeshConnection *c;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
-  msg = (struct GNUNET_MESH_ConnectionBroken *) 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));
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
-                                   GNUNET_PEER_search (&msg->peer2));
-  return GNUNET_OK;
-
-}
-
-
-/**
- * Core handler for tunnel destruction
- *
- * @param cls Closure (unused).
- * @param peer Peer identity of sending neighbor.
- * @param message Message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_connection_destroy (void *cls,
-                                const struct GNUNET_PeerIdentity *peer,
-                                const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectionDestroy *msg;
-  struct MeshConnection *c;
-  GNUNET_PEER_Id id;
-  int fwd;
-
-  msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Got a CONNECTION DESTROY message from %s\n",
-              GNUNET_i2s (peer));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  for connection %s\n",
-              GNUNET_h2s (&msg->cid));
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    /* 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;
-  }
-  id = GNUNET_PEER_search (peer);
-  if (id == connection_get_prev_hop (c)->id)
-    fwd = GNUNET_YES;
-  else if (id == connection_get_next_hop (c)->id)
-    fwd = GNUNET_NO;
-  else
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  send_prebuilt_message_connection (message, c, NULL, fwd);
-  c->destroy = GNUNET_YES;
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Handler for channel create messages.
- *
- * @param t Tunnel this channel is to be created in.
- * @param msg Message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
- */
-static void
-handle_channel_create (struct MeshTunnel2 *t,
-                       struct GNUNET_MESH_ChannelCreate *msg,
-                       int fwd)
-{
-  MESH_ChannelNumber chid;
-  struct MeshChannel *ch;
-  struct MeshClient *c;
-  uint32_t port;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Channel Create\n");
-  /* Check message size */
-  if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_ChannelCreate))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-
-  /* Check if channel exists */
-  chid = ntohl (msg->chid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   chid %u\n", chid);
-  ch = channel_get (t, chid);
-  if (NULL != ch)
-  {
-    /* Probably a retransmission, safe to ignore */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   already exists...\n");
-    if (NULL != ch->dest)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   duplicate CC!!\n");
-      channel_send_ack (ch, !fwd);
-      return;
-    }
-  }
-  else
-  {
-    /* Create channel */
-    ch = channel_new (t, NULL, 0);
-    ch->gid = chid;
-    channel_set_options (ch, ntohl (msg->opt));
-  }
-
-  /* Find a destination client */
-  port = ntohl (msg->port);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   port %u\n", port);
-  c = GNUNET_CONTAINER_multihashmap32_get (ports, port);
-  if (NULL == c)
-  {
-    /* TODO send reject */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  no client has port registered\n");
-    /* TODO free ch */
-    return;
-  }
-
-  channel_add_client (ch, c);
-  if (GNUNET_YES == ch->reliable)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n");
-
-  send_local_channel_create (ch);
-  channel_send_ack (ch, fwd);
-  send_local_ack (ch, !fwd);
-}
-
-
-/**
- * Handler for channel ack messages.
- *
- * @param t Tunnel this channel is to be created in.
- * @param msg Message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
- */
-static void
-handle_channel_ack (struct MeshTunnel2 *t,
-                    struct GNUNET_MESH_ChannelManage *msg,
-                    int fwd)
-{
-  MESH_ChannelNumber chid;
-  struct MeshChannel *ch;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Channel ACK\n");
-  /* Check message size */
-  if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_ChannelManage))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-
-  /* Check if channel exists */
-  chid = ntohl (msg->chid);
-  ch = channel_get (t, chid);
-  if (NULL == ch)
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   channel %u unknown!!\n", chid);
-    return;
-  }
-
-  channel_confirm (ch, !fwd);
-}
-
-
-/**
- * Handler for channel destroy messages.
- *
- * @param t Tunnel this channel is to be destroyed of.
- * @param msg Message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
- */
-static void
-handle_channel_destroy (struct MeshTunnel2 *t,
-                        struct GNUNET_MESH_ChannelManage *msg,
-                        int fwd)
-{
-  MESH_ChannelNumber chid;
-  struct MeshChannel *ch;
-
-  /* Check message size */
-  if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_ChannelManage))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-
-  /* Check if channel exists */
-  chid = ntohl (msg->chid);
-  ch = channel_get (t, chid);
-  if (NULL == ch)
-  {
-    /* Probably a retransmission, safe to ignore */
-    return;
-  }
-  if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
-  {
-    /* Not for us (don't destroy twice a half-open loopback channel) */
-    return;
-  }
-
-  send_local_channel_destroy (ch, fwd);
-  channel_destroy (ch);
-}
-
-
-static void
-handle_decrypted (struct MeshTunnel2 *t,
-                  const struct GNUNET_MessageHeader *msgh,
-                  int fwd)
-{
-  switch (ntohs (msgh->type))
-  {
-    case GNUNET_MESSAGE_TYPE_MESH_DATA:
-      /* Don't send hop ACK, wait for client to ACK */
-      handle_data (t, (struct GNUNET_MESH_Data *) msgh, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
-      handle_data_ack (t, (struct GNUNET_MESH_DataACK *) msgh, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
-      handle_channel_create (t,
-                             (struct GNUNET_MESH_ChannelCreate *) msgh,
-                             fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
-      handle_channel_ack (t,
-                          (struct GNUNET_MESH_ChannelManage *) msgh,
-                          fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
-      handle_channel_destroy (t,
-                              (struct GNUNET_MESH_ChannelManage *) msgh,
-                              fwd);
-      break;
-
-    default:
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "end-to-end message not known (%u)\n",
-                  ntohs (msgh->type));
-  }
-}
-
-
-/**
- * Generic handler for mesh network encrypted traffic.
- *
- * @param peer Peer identity this notification is about.
- * @param message Encrypted message.
- * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_MESH_Encrypted *msg,
-                       int fwd)
-{
-  struct MeshConnection *c;
-  struct MeshTunnel2 *t;
-  struct MeshPeer *neighbor;
-  struct MeshFlowControl *fc;
-  uint32_t pid;
-  uint32_t ttl;
-  uint16_t type;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size <
-      sizeof (struct GNUNET_MESH_Encrypted) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-  type = ntohs (msg->header.type);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
-              GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
-
-  /* Check connection */
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
-    return GNUNET_OK;
-  }
-  t = c->t;
-  fc = fwd ? &c->bck_fc : &c->fwd_fc;
-
-  /* Check if origin is as expected */
-  neighbor = connection_get_hop (c, !fwd);
-  if (peer_get (peer)->id != neighbor->id)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Check PID */
-  pid = ntohl (msg->pid);
-  if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
-  {
-    GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "WARNING Received PID %u, (prev %u), ACK %u\n",
-                pid, fc->last_pid_recv, fc->last_ack_sent);
-    return GNUNET_OK;
-  }
-  if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
-  {
-    GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                " Pid %u not expected (%u+), dropping!\n",
-                pid, fc->last_pid_recv + 1);
-    return GNUNET_OK;
-  }
-  if (MESH_CONNECTION_SENT == c->state)
-    connection_change_state (c, MESH_CONNECTION_READY);
-  connection_reset_timeout (c, fwd);
-  fc->last_pid_recv = pid;
-
-  /* Is this message for us? */
-  if (GMC_is_terminal (c, fwd))
-  {
-    size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
-    char cbuf[dsize];
-    struct GNUNET_MessageHeader *msgh;
-    unsigned int off;
-
-    /* TODO signature verification */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
-    GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
-
-    fc->last_pid_recv = pid;
-    tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
-    off = 0;
-    while (off < dsize)
-    {
-      msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
-      handle_decrypted (t, msgh, fwd);
-      off += ntohs (msgh->size);
-    }
-    send_ack (c, NULL, fwd);
-    return GNUNET_OK;
-  }
-
-  /* Message not for us: forward to next hop */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-  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");
-    send_ack (c, NULL, fwd);
-    return GNUNET_OK;
-  }
-  GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-
-  send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for mesh network traffic going orig->dest.
- *
- * @param cls Closure (unused).
- * @param message Message received.
- * @param peer Peer who sent the message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
-                     const struct GNUNET_MessageHeader *message)
-{
-  return handle_mesh_encrypted (peer,
-                                (struct GNUNET_MESH_Encrypted *)message,
-                                GNUNET_YES);
-}
-
-/**
- * Core handler for mesh network traffic going dest->orig.
- *
- * @param cls Closure (unused).
- * @param message Message received.
- * @param peer Peer who sent the message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_mesh_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
-                     const struct GNUNET_MessageHeader *message)
-{
-  return handle_mesh_encrypted (peer,
-                                (struct GNUNET_MESH_Encrypted *)message,
-                                GNUNET_NO);
-}
-
-
-/**
- * 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)
+ * Dictionary:
+ * - peer: other mesh instance. If there is direct connection it's a neighbor.
+ * - tunnel: encrypted connection to a peer, neighbor or not.
+ * - channel: connection between two clients, on the same or different peers.
+ *            have properties like reliability.
+ * - path: series of directly connected peer from one peer to another.
+ * - connection: path which is being used in a tunnel.
  */
-static int
-handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                 const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ACK *msg;
-  struct MeshConnection *c;
-  struct MeshFlowControl *fc;
-  GNUNET_PEER_Id id;
-  uint32_t ack;
-  int fwd;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
-              GNUNET_i2s (peer));
-  msg = (struct GNUNET_MESH_ACK *) message;
-
-  c = connection_get (&msg->cid);
-
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
-                              GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  /* Is this a forward or backward ACK? */
-  id = GNUNET_PEER_search (peer);
-  if (connection_get_next_hop (c)->id == id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
-    fc = &c->fwd_fc;
-    fwd = GNUNET_YES;
-  }
-  else if (connection_get_prev_hop (c)->id == id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
-    fc = &c->bck_fc;
-    fwd = GNUNET_NO;
-  }
-  else
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  ack = ntohl (msg->ack);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
-              ack, fc->last_ack_recv);
-  if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
-    fc->last_ack_recv = ack;
-
-  /* Cancel polling if the ACK is big enough. */
-  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
-      GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
-    GNUNET_SCHEDULER_cancel (fc->poll_task);
-    fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-    fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
-  }
-
-  connection_unlock_queue (c, fwd);
-
-  return GNUNET_OK;
-}
 
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "mesh_enc.h"
+#include "gnunet_statistics_service.h"
 
-/**
- * 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 MeshConnection *c;
-  struct MeshFlowControl *fc;
-  GNUNET_PEER_Id id;
-  uint32_t pid;
-  int fwd;
+#include "gnunet-service-mesh_local.h"
+#include "gnunet-service-mesh_channel.h"
+#include "gnunet-service-mesh_connection.h"
+#include "gnunet-service-mesh_tunnel.h"
+#include "gnunet-service-mesh_dht.h"
+#include "gnunet-service-mesh_peer.h"
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
-              GNUNET_i2s (peer));
 
-  msg = (struct GNUNET_MESH_Poll *) message;
+/******************************************************************************/
+/************************      DATA STRUCTURES     ****************************/
+/******************************************************************************/
 
-  c = connection_get (&msg->cid);
 
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
-                              GNUNET_NO);
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
 
-  /* Is this a forward or backward ACK?
-   * Note: a poll should never be needed in a loopback case,
-   * since there is no possiblility of packet loss there, so
-   * this way of discerining FWD/BCK should not be a problem.
-   */
-  id = GNUNET_PEER_search (peer);
-  if (connection_get_next_hop (c)->id == id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
-    fc = &c->fwd_fc;
-  }
-  else if (connection_get_prev_hop (c)->id == id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
-    fc = &c->bck_fc;
-  }
-  else
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
+/******************************************************************************/
+/************************      DEBUG FUNCTIONS     ****************************/
+/******************************************************************************/
 
-  pid = ntohl (msg->pid);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n",
-              pid, fc->last_pid_recv);
-  fc->last_pid_recv = pid;
-  fwd = fc == &c->fwd_fc;
-  send_ack (c, NULL, fwd);
 
-  return GNUNET_OK;
-}
+/******************************************************************************/
+/***********************      GLOBAL VARIABLES     ****************************/
+/******************************************************************************/
 
+/****************************** Global variables ******************************/
 
 /**
- * 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.
+ * Handle to the statistics service.
  */
-static int
-handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_MESH_ConnectionKeepAlive *msg;
-  struct MeshConnection *c;
-  struct MeshPeer *neighbor;
-  int fwd;
-
-  msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
-              GNUNET_i2s (peer));
-
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
-                              GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ? 
-        GNUNET_YES : GNUNET_NO;
-
-  /* Check if origin is as expected */
-  neighbor = connection_get_hop (c, fwd);
-  if (peer_get (peer)->id != neighbor->id)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  connection_change_state (c, MESH_CONNECTION_READY);
-  connection_reset_timeout (c, fwd);
-
-  if (GMC_is_terminal (c, fwd))
-    return GNUNET_OK;
-
-  GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
-  send_prebuilt_message_connection (message, c, NULL, fwd);
-
-  return GNUNET_OK;
-}
-
-
+struct GNUNET_STATISTICS_Handle *stats;
 
 /**
- * Functions to handle messages from core
+ * Local peer own ID (memory efficient handle).
  */
-static struct GNUNET_CORE_MessageHandler core_handlers[] = {
-  {&handle_mesh_connection_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
-    0},
-  {&handle_mesh_connection_ack, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
-    sizeof (struct GNUNET_MESH_ConnectionACK)},
-  {&handle_mesh_connection_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
-    sizeof (struct GNUNET_MESH_ConnectionBroken)},
-  {&handle_mesh_connection_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
-    sizeof (struct GNUNET_MESH_ConnectionDestroy)},
-  {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE,
-    sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
-  {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE,
-    sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
-  {&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_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0},
-  {&handle_mesh_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0},
-  {NULL, 0, 0}
-};
-
+GNUNET_PEER_Id myid;
 
 /**
- * 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
+ * Local peer own ID (full value).
  */
-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 MeshPeer *peer = cls;
-  struct MeshPeerPath *p;
-  struct MeshConnection *c;
-  struct GNUNET_PeerIdentity pi;
-  unsigned int connection_count;
-
-  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);
-
-  /* Count connections */
-  connection_count = GMC_count (peer->tunnel->connection_head);
-
-  /* If we already have 3 (or more (?!)) connections, it's enough */
-  if (3 <= connection_count)
-    return;
-
-  if (peer->tunnel->state == MESH_TUNNEL_SEARCHING)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
-    peer_connect (peer);
-  }
-  return;
-}
-
+struct GNUNET_PeerIdentity my_full_id;
 
+/*************************** Static global variables **************************/
 
 /**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
+ * Own private key.
  */
-static void
-core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct MeshPeer *pi;
-  struct MeshPeerPath *path;
-
-  DEBUG_CONN ("Peer connected\n");
-  DEBUG_CONN ("     %s\n", GNUNET_i2s (&my_full_id));
-  pi = peer_get (peer);
-  if (myid == pi->id)
-  {
-    DEBUG_CONN ("     (self)\n");
-    path = path_new (1);
-  }
-  else
-  {
-    DEBUG_CONN ("     %s\n", GNUNET_i2s (peer));
-    path = path_new (2);
-    path->peers[1] = pi->id;
-    GNUNET_PEER_change_rc (pi->id, 1);
-    GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
-  }
-  path->peers[0] = myid;
-  GNUNET_PEER_change_rc (myid, 1);
-  peer_add_path (pi, path, GNUNET_YES);
+static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
 
-  pi->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
-  return;
-}
 
+/******************************************************************************/
+/***********************         DECLARATIONS        **************************/
+/******************************************************************************/
 
-/**
- * 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 MeshPeer *pi;
 
-  DEBUG_CONN ("Peer disconnected\n");
-  pi = GNUNET_CONTAINER_multipeermap_get (peers, peer);
-  if (NULL == pi)
-  {
-    GNUNET_break (0);
-    return;
-  }
+/******************************************************************************/
+/******************      GENERAL HELPER FUNCTIONS      ************************/
+/******************************************************************************/
 
-  GNUNET_CONTAINER_multihashmap_iterate (pi->connections,
-                                         GMC_notify_broken,
-                                         pi);
-  GNUNET_CONTAINER_multihashmap_destroy (pi->connections);
-  pi->connections = NULL;
-  if (NULL != pi->core_transmit)
-    {
-      GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit);
-      pi->core_transmit = NULL;
-    }
-  if (myid == pi->id)
-  {
-    DEBUG_CONN ("     (self)\n");
-  }
-  GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
 
-  return;
-}
 
+/******************************************************************************/
+/****************      MESH NETWORK HANDLER HELPERS     ***********************/
+/******************************************************************************/
 
 
-/**
- * To be called on core init/fail.
- *
- * @param cls Closure (config)
- * @param identity the public identity of this peer
- */
-static void
-core_init (void *cls, 
-           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");
-  if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
-  {
-    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;
-}
+/******************************************************************************/
+/********************      MESH NETWORK HANDLERS     **************************/
+/******************************************************************************/
 
 
 /******************************************************************************/
 /************************      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_PeerIdentity *key, 
-                void *value)
-{
-  struct MeshPeer *p = value;
-  struct MeshTunnel2 *t = p->tunnel;
-
-  if (NULL != t)
-    tunnel_destroy (t);
-  return GNUNET_YES;
-}
-
 
 /**
  * Task run during shutdown.
@@ -3462,23 +134,12 @@ 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;
-  }
-  GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
-  if (dht_handle != NULL)
-  {
-    GNUNET_DHT_disconnect (dht_handle);
-    dht_handle = NULL;
-  }
   GML_shutdown ();
-  if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
-  {
-    GNUNET_SCHEDULER_cancel (announce_id_task);
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-  }
+  GMD_shutdown ();
+  GMP_shutdown ();
+  GMC_shutdown ();
+  GMT_shutdown ();
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
 }
 
@@ -3494,116 +155,28 @@ static void
 run (void *cls, struct GNUNET_SERVER_Handle *server,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  struct GNUNET_CRYPTO_EccPrivateKey *pk;
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
 
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
-                                           &id_announce_time))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "MESH", "ID_ANNOUNCE_TIME", "MISSING");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
-                                           &connect_timeout))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "MESH", "CONNECT_TIMEOUT", "MISSING");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
-                                             &default_ttl))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "MESH", "DEFAULT_TTL", "USING DEFAULT");
-    default_ttl = 64;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
-                                             &max_peers))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "MESH", "MAX_PEERS", "USING DEFAULT");
-    max_peers = 1000;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT",
-                                             &drop_percent))
-  {
-    drop_percent = 0;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "\n***************************************\n"
-                "Mesh is running with drop mode enabled.\n"
-                "This is NOT a good idea!\n"
-                "Remove the DROP_PERCENT option from your configuration.\n"
-                "***************************************\n");
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL",
-                                             &dht_replication_level))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "MESH", "DHT_REPLICATION_LEVEL", "USING DEFAULT");
-    dht_replication_level = 3;
-  }
-
-  peers = GNUNET_CONTAINER_multipeermap_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);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n");
-  pk = GNUNET_CRYPTO_ecc_key_create_from_configuration (c);
-  GNUNET_assert (NULL != pk);
-  my_private_key = pk;
-  GNUNET_CRYPTO_ecc_key_get_public_for_signature (my_private_key, 
-                                                 &my_full_id.public_key);
+  my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
+  GNUNET_assert (NULL != my_private_key);
+  GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_full_id.public_key);
   myid = GNUNET_PEER_intern (&my_full_id);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Mesh for peer [%s] starting\n",
-              GNUNET_i2s(&my_full_id));
+              GNUNET_i2s (&my_full_id));
 
-  GML_init (server);
-  GMC_init (c);
+  GML_init (server);    /* Local clients */
+  GMC_init (c);         /* Connections */
+  GMP_init (c);         /* Peers */
+  GMD_init (c);         /* DHT */
+  GMT_init (c, my_private_key); /* Tunnels */
 
-  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 (NULL == core_handle)
-  {
-    GNUNET_break (0);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
 }
 
@@ -3621,13 +194,12 @@ main (int argc, char *const *argv)
   int ret;
   int r;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
+  fprintf (stderr, "main()\n");
   r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
                           NULL);
+  GNUNET_free (my_private_key);
   ret = (GNUNET_OK == r) ? 0 : 1;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");
-
-  INTERVAL_SHOW;
+  fprintf (stderr, "main() END\n");
 
   return ret;
 }