gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r33186 - in gnunet/src: . cadet mesh


From: gnunet
Subject: [GNUnet-SVN] r33186 - in gnunet/src: . cadet mesh
Date: Wed, 7 May 2014 14:07:16 +0200

Author: bartpolot
Date: 2014-05-07 14:07:16 +0200 (Wed, 07 May 2014)
New Revision: 33186

Added:
   gnunet/src/cadet/
   gnunet/src/cadet/Makefile.am
   gnunet/src/cadet/beautify_log.sh
   gnunet/src/cadet/cadet.h
   gnunet/src/cadet/cadet_api.c
   gnunet/src/cadet/cadet_common.c
   gnunet/src/cadet/cadet_path.c
   gnunet/src/cadet/cadet_path.h
   gnunet/src/cadet/cadet_protocol.h
   gnunet/src/cadet/cadet_test_lib.c
   gnunet/src/cadet/cadet_test_lib.h
   gnunet/src/cadet/cadet_tunnel_tree.c
   gnunet/src/cadet/cadet_tunnel_tree.h
   gnunet/src/cadet/gnunet-cadet-profiler.c
   gnunet/src/cadet/gnunet-cadet.c
   gnunet/src/cadet/gnunet-service-cadet.c
   gnunet/src/cadet/gnunet-service-cadet_channel.c
   gnunet/src/cadet/gnunet-service-cadet_channel.h
   gnunet/src/cadet/gnunet-service-cadet_connection.c
   gnunet/src/cadet/gnunet-service-cadet_connection.h
   gnunet/src/cadet/gnunet-service-cadet_dht.c
   gnunet/src/cadet/gnunet-service-cadet_dht.h
   gnunet/src/cadet/gnunet-service-cadet_hello.c
   gnunet/src/cadet/gnunet-service-cadet_hello.h
   gnunet/src/cadet/gnunet-service-cadet_local.c
   gnunet/src/cadet/gnunet-service-cadet_local.h
   gnunet/src/cadet/gnunet-service-cadet_peer.c
   gnunet/src/cadet/gnunet-service-cadet_peer.h
   gnunet/src/cadet/gnunet-service-cadet_tunnel.c
   gnunet/src/cadet/gnunet-service-cadet_tunnel.h
   gnunet/src/cadet/loopcheck.sh
   gnunet/src/cadet/mesh.conf.in
   gnunet/src/cadet/profiler.conf
   gnunet/src/cadet/run_profiler.sh
   gnunet/src/cadet/small.dat
   gnunet/src/cadet/test_cadet.c
   gnunet/src/cadet/test_cadet.conf
   gnunet/src/cadet/test_cadet_drop.conf
   gnunet/src/cadet/test_cadet_local.c
   gnunet/src/cadet/test_cadet_single.c
   gnunet/src/cadet/valgrind-mesh.supp
Removed:
   gnunet/src/mesh/Makefile.am
   gnunet/src/mesh/beautify_log.sh
   gnunet/src/mesh/cadet.h
   gnunet/src/mesh/cadet_api.c
   gnunet/src/mesh/cadet_common.c
   gnunet/src/mesh/cadet_path.c
   gnunet/src/mesh/cadet_path.h
   gnunet/src/mesh/cadet_protocol.h
   gnunet/src/mesh/cadet_test_lib.c
   gnunet/src/mesh/cadet_test_lib.h
   gnunet/src/mesh/cadet_tunnel_tree.c
   gnunet/src/mesh/cadet_tunnel_tree.h
   gnunet/src/mesh/gnunet-cadet-profiler.c
   gnunet/src/mesh/gnunet-cadet.c
   gnunet/src/mesh/gnunet-service-cadet.c
   gnunet/src/mesh/gnunet-service-cadet_channel.c
   gnunet/src/mesh/gnunet-service-cadet_channel.h
   gnunet/src/mesh/gnunet-service-cadet_connection.c
   gnunet/src/mesh/gnunet-service-cadet_connection.h
   gnunet/src/mesh/gnunet-service-cadet_dht.c
   gnunet/src/mesh/gnunet-service-cadet_dht.h
   gnunet/src/mesh/gnunet-service-cadet_hello.c
   gnunet/src/mesh/gnunet-service-cadet_hello.h
   gnunet/src/mesh/gnunet-service-cadet_local.c
   gnunet/src/mesh/gnunet-service-cadet_local.h
   gnunet/src/mesh/gnunet-service-cadet_peer.c
   gnunet/src/mesh/gnunet-service-cadet_peer.h
   gnunet/src/mesh/gnunet-service-cadet_tunnel.c
   gnunet/src/mesh/gnunet-service-cadet_tunnel.h
   gnunet/src/mesh/loopcheck.sh
   gnunet/src/mesh/mesh.conf.in
   gnunet/src/mesh/profiler.conf
   gnunet/src/mesh/run_profiler.sh
   gnunet/src/mesh/small.dat
   gnunet/src/mesh/test_cadet.c
   gnunet/src/mesh/test_cadet.conf
   gnunet/src/mesh/test_cadet_drop.conf
   gnunet/src/mesh/test_cadet_local.c
   gnunet/src/mesh/test_cadet_single.c
   gnunet/src/mesh/valgrind-mesh.supp
Log:
Renamed directory

Copied: gnunet/src/cadet/Makefile.am (from rev 33185, 
gnunet/src/mesh/Makefile.am)
===================================================================
--- gnunet/src/cadet/Makefile.am                                (rev 0)
+++ gnunet/src/cadet/Makefile.am        2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,194 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfg_DATA = \
+  cadet.conf
+
+plugindir = $(libdir)/gnunet
+
+AM_CLFAGS = -g
+
+libexec_PROGRAMS = \
+ gnunet-service-cadet $(EXP_LIBEXEC)
+
+bin_PROGRAMS = \
+ gnunet-cadet
+
+lib_LTLIBRARIES = \
+  libgnunetcadet.la $(EXP_LIB)
+
+libgnunetcadet_la_SOURCES = \
+  cadet_api.c cadet_common.c
+libgnunetcadet_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(XLIB) \
+  $(LTLIBINTL)
+libgnunetcadet_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+  -version-info 5:0:0
+
+gnunet_cadet_SOURCES = \
+  gnunet-cadet.c
+gnunet_cadet_LDADD = \
+  $(top_builddir)/src/cadet/libgnunetcadet.la \
+  $(top_builddir)/src/util/libgnunetutil.la
+gnunet_cadet_DEPENDENCIES = \
+  libgnunetcadet.la
+
+gnunet_service_cadet_SOURCES = \
+ gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \
+ gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
+ gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \
+ gnunet-service-cadet_local.c gnunet-service-cadet_local.h \
+ gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \
+ gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \
+ gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \
+ cadet_path.c cadet_path.h \
+ cadet_common.c \
+ gnunet-service-cadet.c
+gnunet_service_cadet_CFLAGS = $(AM_CFLAGS)
+gnunet_service_cadet_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/transport/libgnunettransport.la \
+  $(top_builddir)/src/core/libgnunetcore.la \
+  $(top_builddir)/src/dht/libgnunetdht.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
+  $(top_builddir)/src/hello/libgnunethello.la \
+  $(top_builddir)/src/block/libgnunetblock.la
+gnunet_service_cadet_DEPENDENCIES = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/transport/libgnunettransport.la \
+  $(top_builddir)/src/core/libgnunetcore.la \
+  $(top_builddir)/src/dht/libgnunetdht.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
+  $(top_builddir)/src/hello/libgnunethello.la \
+  $(top_builddir)/src/block/libgnunetblock.la
+if LINUX
+  gnunet_service_cadet_LDFLAGS = -lrt
+endif
+
+
+if HAVE_TESTING
+ noinst_LIBRARIES = libgnunetcadettest.a $(noinst_LIB_EXP)
+ noinst_PROGRAMS = gnunet-cadet-profiler
+endif
+
+libgnunetcadettest_a_SOURCES = \
+  cadet_test_lib.c cadet_test_lib.h
+libgnunetcadettest_a_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/testbed/libgnunettestbed.la \
+ $(top_builddir)/src/cadet/libgnunetcadet.la
+libgnunetcadettest_a_DEPENDENCIES = \
+  libgnunetcadet.la
+
+if HAVE_TESTING
+check_PROGRAMS = \
+  test_cadet_single \
+  test_cadet_local \
+  test_cadet_forward \
+  test_cadet_signal \
+  test_cadet_keepalive \
+  test_cadet_speed \
+  test_cadet_speed_ack \
+  test_cadet_speed_backwards \
+  test_cadet_speed_reliable \
+  test_cadet_speed_reliable_backwards
+endif
+
+ld_cadet_test_lib = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/cadet/libgnunetcadettest.a \
+  $(top_builddir)/src/cadet/libgnunetcadet.la \
+  $(top_builddir)/src/testbed/libgnunettestbed.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la
+
+dep_cadet_test_lib = \
+  libgnunetcadet.la \
+  libgnunetcadettest.a \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la
+
+
+gnunet_cadet_profiler_SOURCES = \
+  gnunet-cadet-profiler.c
+gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib)
+gnunet_cadet_profiler_DEPENDENCIES = $(dep_cadet_test_lib)
+
+
+test_cadet_single_SOURCES = \
+  test_cadet_single.c
+test_cadet_single_LDADD = $(ld_cadet_test_lib)
+test_cadet_single_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_local_SOURCES = \
+  test_cadet_local.c
+test_cadet_local_LDADD = $(ld_cadet_test_lib)
+test_cadet_local_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_forward_SOURCES = \
+  test_cadet.c
+test_cadet_forward_LDADD = $(ld_cadet_test_lib)
+test_cadet_forward_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_signal_SOURCES = \
+  test_cadet.c
+test_cadet_signal_LDADD = $(ld_cadet_test_lib)
+test_cadet_signal_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_keepalive_SOURCES = \
+  test_cadet.c
+test_cadet_keepalive_LDADD = $(ld_cadet_test_lib)
+test_cadet_keepalive_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_speed_SOURCES = \
+  test_cadet.c
+test_cadet_speed_LDADD = $(ld_cadet_test_lib)
+test_cadet_speed_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_speed_ack_SOURCES = \
+  test_cadet.c
+test_cadet_speed_ack_LDADD = $(ld_cadet_test_lib)
+test_cadet_speed_ack_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_speed_backwards_SOURCES = \
+  test_cadet.c
+test_cadet_speed_backwards_LDADD = $(ld_cadet_test_lib)
+test_cadet_speed_backwards_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_speed_reliable_SOURCES = \
+  test_cadet.c
+test_cadet_speed_reliable_LDADD = $(ld_cadet_test_lib)
+test_cadet_speed_reliable_DEPENDENCIES = $(dep_cadet_test_lib)
+
+test_cadet_speed_reliable_backwards_SOURCES = \
+  test_cadet.c
+test_cadet_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
+test_cadet_speed_reliable_backwards_DEPENDENCIES = $(dep_cadet_test_lib)
+
+
+if ENABLE_TEST_RUN
+AM_TESTS_ENVIRONMENT=export 
GNUNET_PREFIX=$${GNUNET_PREFIX:address@hidden@};export 
PATH=$${GNUNET_PREFIX:address@hidden@}/bin:$$PATH;
+TESTS = \
+ $(check_PROGRAMS)
+endif
+
+EXTRA_DIST = \
+  cadet.h cadet_protocol.h \
+  test_cadet.conf \
+  test_cadet_drop.conf
+

Copied: gnunet/src/cadet/beautify_log.sh (from rev 33185, 
gnunet/src/mesh/beautify_log.sh)
===================================================================
--- gnunet/src/cadet/beautify_log.sh                            (rev 0)
+++ gnunet/src/cadet/beautify_log.sh    2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,18 @@
+#!/bin/sh
+grep "STARTING SERVICE " log > __tmp_peers
+SED_EXPR=""
+while read -r line; do
+    PEER=`echo $line | sed -e 's/.*\[\(....\)\].*/\1/'`
+    PID=`echo $line | sed -e 's/.*mesh-\([0-9]*\).*/\1/'`
+    echo "$PID => $PEER"
+    SED_EXPR="${SED_EXPR}s/mesh-\([a-z2]*\)-$PID/MESH \1 $PEER/;"
+    SED_EXPR="${SED_EXPR}s/mesh-$PID/MESH XXX $PEER/;"
+done < __tmp_peers
+rm __tmp_peers
+
+SED_EXPR="${SED_EXPR}s/mesh-api-/mesh-api-                                     
       /g"
+sed -e "$SED_EXPR" log > .log
+
+if [[ "`ps aux | grep "kwrite .lo[g]"`" = "" ]]; then
+    kwrite .log --geometry 960x1140-960 &
+fi

Copied: gnunet/src/cadet/cadet.h (from rev 33185, gnunet/src/mesh/cadet.h)
===================================================================
--- gnunet/src/cadet/cadet.h                            (rev 0)
+++ gnunet/src/cadet/cadet.h    2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,351 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @author Bartlomiej Polot
+ * @file cadet/cadet.h
+ */
+
+#ifndef CADET_H_
+#define CADET_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include <stdint.h>
+
+#define CADET_DEBUG              GNUNET_YES
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_peer_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_protocols.h"
+#include <gnunet_cadet_service.h>
+
+/******************************************************************************/
+/**************************       CONSTANTS      
******************************/
+/******************************************************************************/
+
+#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI        0x80000000
+#define GNUNET_CADET_LOCAL_CHANNEL_ID_SERV       0xB0000000
+
+#define HIGH_PID                                0xFFFF0000
+#define LOW_PID                                 0x0000FFFF
+
+#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
+
+/******************************************************************************/
+/**************************        MESSAGES      
******************************/
+/******************************************************************************/
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message for a client to register to the service
+ */
+struct GNUNET_CADET_ClientConnect
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT
+     *
+     * Size: sizeof(struct GNUNET_CADET_ClientConnect) +
+     *       sizeof(CADET_ApplicationType) * applications +
+     *       sizeof(uint16_t) * types
+     */
+  struct GNUNET_MessageHeader header;
+  /* uint32_t                 list_ports[]           */
+};
+
+
+/**
+ * Type for channel numbering.
+ * - Local channel numbers given by the service (incoming) are >= 0xB0000000
+ * - Local channel numbers given by the client (created) are >= 0x80000000
+ * - Global channel numbers are < 0x80000000
+ */
+typedef uint32_t CADET_ChannelNumber;
+
+
+/**
+ * Message for a client to create and destroy channels.
+ */
+struct GNUNET_CADET_ChannelMessage
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_[CREATE|DESTROY]
+     *
+     * Size: sizeof(struct GNUNET_CADET_ChannelMessage)
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of a channel controlled by this client.
+     */
+  CADET_ChannelNumber channel_id GNUNET_PACKED;
+
+    /**
+     * Channel's peer
+     */
+  struct GNUNET_PeerIdentity peer;
+
+    /**
+     * Port of the channel.
+     */
+  uint32_t port GNUNET_PACKED;
+
+    /**
+     * Options.
+     */
+  uint32_t opt GNUNET_PACKED;
+};
+
+
+/**
+ * Message for cadet data traffic.
+ */
+struct GNUNET_CADET_LocalData
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the channel
+     */
+  uint32_t id GNUNET_PACKED;
+
+    /**
+     * Payload follows
+     */
+};
+
+
+/**
+ * Message to allow the client send more data to the service
+ * (always service -> client).
+ */
+struct GNUNET_CADET_LocalAck
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the channel allowed to send more data.
+     */
+  CADET_ChannelNumber channel_id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Message to inform the client about channels in the service.
+ */
+struct GNUNET_CADET_LocalInfo
+{
+  /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO[_TUNNEL,_PEER]
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the channel allowed to send more data.
+   */
+  CADET_ChannelNumber channel_id GNUNET_PACKED;
+
+  /**
+   * ID of the owner of the channel (can be local peer).
+   */
+//   struct GNUNET_PeerIdentity owner;
+
+  /**
+   * ID of the destination of the channel (can be local peer).
+   */
+  struct GNUNET_PeerIdentity peer;
+};
+
+
+/**
+ * Message to inform the client about one of the peers in the service.
+ */
+struct GNUNET_CADET_LocalInfoPeer
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER[S]
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Number of paths.
+   */
+  uint16_t paths GNUNET_PACKED;
+
+  /**
+   * Do we have a tunnel toward this peer?
+   */
+  int16_t tunnel GNUNET_PACKED;
+
+  /**
+   * ID of the destination of the tunnel (can be local peer).
+   */
+  struct GNUNET_PeerIdentity destination;
+
+  /* If type == PEER (no 'S'): GNUNET_PeerIdentity paths[]
+   * (each path ends in destination) */
+};
+
+/**
+ * Message to inform the client about one of the tunnels in the service.
+ */
+struct GNUNET_CADET_LocalInfoTunnel
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL[S]
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Number of channels.
+   */
+  uint32_t channels GNUNET_PACKED;
+
+  /**
+   * ID of the destination of the tunnel (can be local peer).
+   */
+  struct GNUNET_PeerIdentity destination;
+
+  /**
+   * Number of connections.
+   */
+  uint32_t connections GNUNET_PACKED;
+
+  /**
+   * Encryption state.
+   */
+  uint16_t estate GNUNET_PACKED;
+
+  /**
+   * Connection state.
+   */
+  uint16_t cstate GNUNET_PACKED;
+
+  /* If TUNNEL (no 'S'): GNUNET_PeerIdentity connection_ids[connections] */
+  /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+
+
+/**
+ * @brief Translate a fwd variable into a string representation, for logging.
+ *
+ * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO)
+ *
+ * @return String representing FWD or BCK.
+ */
+char *
+GM_f2s (int fwd);
+
+
+/**
+ * Check if one pid is bigger than other, accounting for overflow.
+ *
+ * @param bigger Argument that should be bigger.
+ * @param smaller Argument that should be smaller.
+ *
+ * @return True if bigger (arg1) has a higher value than smaller (arg 2).
+ */
+int
+GM_is_pid_bigger (uint32_t bigger, uint32_t smaller);
+
+
+/**
+ * Get the higher ACK value out of two values, taking in account overflow.
+ *
+ * @param a First ACK value.
+ * @param b Second ACK value.
+ *
+ * @return Highest ACK value from the two.
+ */
+uint32_t
+GM_max_pid (uint32_t a, uint32_t b);
+
+
+/**
+ * Get the lower ACK value out of two values, taking in account overflow.
+ *
+ * @param a First ACK value.
+ * @param b Second ACK value.
+ *
+ * @return Lowest ACK value from the two.
+ */
+uint32_t
+GM_min_pid (uint32_t a, uint32_t b);
+
+
+/**
+ * Convert a 256 bit CadetHash into a 512 HashCode to use in GNUNET_h2s,
+ * multihashmap, and other HashCode-based functions.
+ *
+ * @param id A 256 bit hash to expand.
+ *
+ * @return A HashCode containing the original 256 bit hash right-padded with 0.
+ */
+const struct GNUNET_HashCode *
+GM_h2hc (const struct GNUNET_CADET_Hash *id);
+
+/**
+ * Get a string from a Cadet Hash (256 bits).
+ * WARNING: Not reentrant (based on GNUNET_h2s).
+ */
+const char *
+GM_h2s (const struct GNUNET_CADET_Hash *id);
+
+/**
+ * Convert a message type into a string to help debug
+ * Generated with:
+ * FIND:        "#define ([^ ]+)[ ]*([0-9]+)"
+ * REPLACE:     "    case \2: return "\1"; break;"
+ *
+ * @param m Message type.
+ *
+ * @return Human readable string description.
+ */
+const char *
+GM_m2s (uint16_t m);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Copied: gnunet/src/cadet/cadet_api.c (from rev 33185, 
gnunet/src/mesh/cadet_api.c)
===================================================================
--- gnunet/src/cadet/cadet_api.c                                (rev 0)
+++ gnunet/src/cadet/cadet_api.c        2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,2141 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/cadet_api.c
+ * @brief cadet api: client implementation of new cadet service
+ * @author Bartlomiej Polot
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_cadet_service.h"
+#include "cadet.h"
+#include "cadet_protocol.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__)
+
+/******************************************************************************/
+/************************      DATA STRUCTURES     
****************************/
+/******************************************************************************/
+
+/**
+ * Transmission queue to the service
+ */
+struct GNUNET_CADET_TransmitHandle
+{
+
+    /**
+     * Double Linked list
+     */
+  struct GNUNET_CADET_TransmitHandle *next;
+
+    /**
+     * Double Linked list
+     */
+  struct GNUNET_CADET_TransmitHandle *prev;
+
+    /**
+     * Channel this message is sent on / for (may be NULL for control 
messages).
+     */
+  struct GNUNET_CADET_Channel *channel;
+
+    /**
+     * Callback to obtain the message to transmit, or NULL if we
+     * got the message in 'data'.  Notice that messages built
+     * by 'notify' need to be encapsulated with information about
+     * the 'target'.
+     */
+  GNUNET_CONNECTION_TransmitReadyNotify notify;
+
+    /**
+     * Closure for 'notify'
+     */
+  void *notify_cls;
+
+    /**
+     * How long is this message valid.  Once the timeout has been
+     * reached, the message must no longer be sent.  If this
+     * is a message with a 'notify' callback set, the 'notify'
+     * function should be called with 'buf' NULL and size 0.
+     */
+  struct GNUNET_TIME_Absolute timeout;
+
+    /**
+     * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
+     */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+    /**
+     * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
+     */
+  size_t size;
+};
+
+union CadetInfoCB {
+
+  /**
+   * Channel callback.
+   */
+  GNUNET_CADET_ChannelCB channel_cb;
+
+  /**
+   * Monitor callback
+   */
+  GNUNET_CADET_PeersCB peers_cb;
+
+  /**
+   * Monitor callback
+   */
+  GNUNET_CADET_PeerCB peer_cb;
+
+  /**
+   * Monitor callback
+   */
+  GNUNET_CADET_TunnelsCB tunnels_cb;
+
+  /**
+   * Tunnel callback.
+   */
+  GNUNET_CADET_TunnelCB tunnel_cb;
+};
+
+
+/**
+ * Opaque handle to the service.
+ */
+struct GNUNET_CADET_Handle
+{
+
+    /**
+     * Handle to the server connection, to send messages later
+     */
+  struct GNUNET_CLIENT_Connection *client;
+
+    /**
+     * Set of handlers used for processing incoming messages in the channels
+     */
+  const struct GNUNET_CADET_MessageHandler *message_handlers;
+
+  /**
+   * Number of handlers in the handlers array.
+   */
+  unsigned int n_handlers;
+
+  /**
+   * Ports open.
+   */
+  const uint32_t *ports;
+
+  /**
+   * Number of ports.
+   */
+  unsigned int n_ports;
+
+    /**
+     * Double linked list of the channels this client is connected to, head.
+     */
+  struct GNUNET_CADET_Channel *channels_head;
+
+    /**
+     * Double linked list of the channels this client is connected to, tail.
+     */
+  struct GNUNET_CADET_Channel *channels_tail;
+
+    /**
+     * Callback for inbound channel creation
+     */
+  GNUNET_CADET_InboundChannelNotificationHandler *new_channel;
+
+    /**
+     * Callback for inbound channel disconnection
+     */
+  GNUNET_CADET_ChannelEndHandler *cleaner;
+
+    /**
+     * Handle to cancel pending transmissions in case of disconnection
+     */
+  struct GNUNET_CLIENT_TransmitHandle *th;
+
+    /**
+     * Closure for all the handlers given by the client
+     */
+  void *cls;
+
+    /**
+     * Messages to send to the service, head.
+     */
+  struct GNUNET_CADET_TransmitHandle *th_head;
+
+    /**
+     * Messages to send to the service, tail.
+     */
+  struct GNUNET_CADET_TransmitHandle *th_tail;
+
+    /**
+     * chid of the next channel to create (to avoid reusing IDs often)
+     */
+  CADET_ChannelNumber next_chid;
+
+    /**
+     * Have we started the task to receive messages from the service
+     * yet? We do this after we send the 'CADET_LOCAL_CONNECT' message.
+     */
+  int in_receive;
+
+  /**
+   * Configuration given by the client, in case of reconnection
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Time to the next reconnect in case one reconnect fails
+   */
+  struct GNUNET_TIME_Relative reconnect_time;
+
+  /**
+   * Task for trying to reconnect.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
+
+  /**
+   * Callback for an info task (only one active at a time).
+   */
+  union CadetInfoCB info_cb;
+
+  /**
+   * Info callback closure for @c info_cb.
+   */
+  void *info_cls;
+};
+
+
+/**
+ * Description of a peer
+ */
+struct GNUNET_CADET_Peer
+{
+    /**
+     * ID of the peer in short form
+     */
+  GNUNET_PEER_Id id;
+
+  /**
+   * Channel this peer belongs to
+   */
+  struct GNUNET_CADET_Channel *t;
+};
+
+
+/**
+ * Opaque handle to a channel.
+ */
+struct GNUNET_CADET_Channel
+{
+
+    /**
+     * DLL next
+     */
+  struct GNUNET_CADET_Channel *next;
+
+    /**
+     * DLL prev
+     */
+  struct GNUNET_CADET_Channel *prev;
+
+    /**
+     * Handle to the cadet this channel belongs to
+     */
+  struct GNUNET_CADET_Handle *cadet;
+
+    /**
+     * Local ID of the channel
+     */
+  CADET_ChannelNumber chid;
+
+    /**
+     * Port number.
+     */
+  uint32_t port;
+
+    /**
+     * Other end of the channel.
+     */
+  GNUNET_PEER_Id peer;
+
+  /**
+   * Any data the caller wants to put in here
+   */
+  void *ctx;
+
+    /**
+     * Size of packet queued in this channel
+     */
+  unsigned int packet_size;
+
+    /**
+     * Channel options: reliability, etc.
+     */
+  enum GNUNET_CADET_ChannelOption options;
+
+    /**
+     * Are we allowed to send to the service?
+     */
+  int allow_send;
+
+};
+
+
+/**
+ * Implementation state for cadet's message queue.
+ */
+struct CadetMQState
+{
+  /**
+   * The current transmit handle, or NULL
+   * if no transmit is active.
+   */
+  struct GNUNET_CADET_TransmitHandle *th;
+
+  /**
+   * Channel to send the data over.
+   */
+  struct GNUNET_CADET_Channel *channel;
+};
+
+
+/******************************************************************************/
+/***********************         DECLARATIONS         
*************************/
+/******************************************************************************/
+
+/**
+ * Function called to send a message to the service.
+ * "buf" will be NULL and "size" zero if the socket was closed for writing in
+ * the meantime.
+ *
+ * @param cls closure, the cadet handle
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the connect message
+ * @return number of bytes written to buf
+ */
+static size_t
+send_callback (void *cls, size_t size, void *buf);
+
+
+/******************************************************************************/
+/***********************     AUXILIARY FUNCTIONS      
*************************/
+/******************************************************************************/
+
+/**
+ * Check if transmission is a payload packet.
+ *
+ * @param th Transmission handle.
+ *
+ * @return GNUNET_YES if it is a payload packet,
+ *         GNUNET_NO if it is a cadet management packet.
+ */
+static int
+th_is_payload (struct GNUNET_CADET_TransmitHandle *th)
+{
+  return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Check whether there is any message ready in the queue and find the size.
+ *
+ * @param h Cadet handle.
+ *
+ * @return The size of the first ready message in the queue,
+ *         0 if there is none.
+ */
+static size_t
+message_ready_size (struct GNUNET_CADET_Handle *h)
+{
+  struct GNUNET_CADET_TransmitHandle *th;
+  struct GNUNET_CADET_Channel *ch;
+
+  for (th = h->th_head; NULL != th; th = th->next)
+  {
+    ch = th->channel;
+    if (GNUNET_NO == th_is_payload (th))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message internal\n");
+      return th->size;
+    }
+    if (GNUNET_YES == ch->allow_send)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message payload ok\n");
+      return th->size;
+    }
+  }
+  return 0;
+}
+
+
+/**
+ * Get the channel handler for the channel specified by id from the given 
handle
+ * @param h Cadet handle
+ * @param chid ID of the wanted channel
+ * @return handle to the required channel or NULL if not found
+ */
+static struct GNUNET_CADET_Channel *
+retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
+{
+  struct GNUNET_CADET_Channel *ch;
+
+  ch = h->channels_head;
+  while (ch != NULL)
+  {
+    if (ch->chid == chid)
+      return ch;
+    ch = ch->next;
+  }
+  return NULL;
+}
+
+
+/**
+ * Create a new channel and insert it in the channel list of the cadet handle
+ *
+ * @param h Cadet handle
+ * @param chid Desired chid of the channel, 0 to assign one automatically.
+ *
+ * @return Handle to the created channel.
+ */
+static struct GNUNET_CADET_Channel *
+create_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
+{
+  struct GNUNET_CADET_Channel *ch;
+
+  ch = GNUNET_new (struct GNUNET_CADET_Channel);
+  GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch);
+  ch->cadet = h;
+  if (0 == chid)
+  {
+    ch->chid = h->next_chid;
+    while (NULL != retrieve_channel (h, h->next_chid))
+    {
+      h->next_chid++;
+      h->next_chid &= ~GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+      h->next_chid |= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+    }
+  }
+  else
+  {
+    ch->chid = chid;
+  }
+  ch->allow_send = GNUNET_NO;
+  return ch;
+}
+
+
+/**
+ * Destroy the specified channel.
+ * - Destroys all peers, calling the disconnect callback on each if needed
+ * - Cancels all outgoing traffic for that channel, calling respective notifys
+ * - Calls cleaner if channel was inbound
+ * - Frees all memory used
+ *
+ * @param ch Pointer to the channel.
+ * @param call_cleaner Whether to call the cleaner handler.
+ *
+ * @return Handle to the required channel or NULL if not found.
+ */
+static void
+destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner)
+{
+  struct GNUNET_CADET_Handle *h;
+  struct GNUNET_CADET_TransmitHandle *th;
+  struct GNUNET_CADET_TransmitHandle *next;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " destroy_channel %X\n", ch->chid);
+
+  if (NULL == ch)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  h = ch->cadet;
+
+  GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch);
+
+  /* signal channel destruction */
+  if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) 
)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cleaner\n");
+    h->cleaner (h->cls, ch, ch->ctx);
+  }
+
+  /* check that clients did not leave messages behind in the queue */
+  for (th = h->th_head; NULL != th; th = next)
+  {
+    next = th->next;
+    if (th->channel != ch)
+      continue;
+    /* Clients should have aborted their requests already.
+     * Management traffic should be ok, as clients can't cancel that.
+     * If the service crashed and we are reconnecting, it's ok.
+     */
+    GNUNET_break (GNUNET_NO == th_is_payload (th)
+                  || GNUNET_NO == h->in_receive);
+    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
+
+    /* clean up request */
+    if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
+      GNUNET_SCHEDULER_cancel (th->timeout_task);
+    GNUNET_free (th);
+  }
+
+  /* if there are no more pending requests with cadet service, cancel active 
request */
+  /* Note: this should be unnecessary... */
+  if ((0 == message_ready_size (h)) && (NULL != h->th))
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+  }
+
+  if (0 != ch->peer)
+    GNUNET_PEER_change_rc (ch->peer, -1);
+  GNUNET_free (ch);
+  return;
+}
+
+
+/**
+ * Notify client that the transmission has timed out
+ *
+ * @param cls closure
+ * @param tc task context
+ */
+static void
+timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_CADET_TransmitHandle *th = cls;
+  struct GNUNET_CADET_Handle *cadet;
+
+  cadet = th->channel->cadet;
+  GNUNET_CONTAINER_DLL_remove (cadet->th_head, cadet->th_tail, th);
+  th->channel->packet_size = 0;
+  if (GNUNET_YES == th_is_payload (th))
+    th->notify (th->notify_cls, 0, NULL);
+  GNUNET_free (th);
+  if ((0 == message_ready_size (cadet)) && (NULL != cadet->th))
+  {
+    /* nothing ready to transmit, no point in asking for transmission */
+    GNUNET_CLIENT_notify_transmit_ready_cancel (cadet->th);
+    cadet->th = NULL;
+  }
+}
+
+
+/**
+ * Add a transmit handle to the transmission queue and set the
+ * timeout if needed.
+ *
+ * @param h cadet handle with the queue head and tail
+ * @param th handle to the packet to be transmitted
+ */
+static void
+add_to_queue (struct GNUNET_CADET_Handle *h,
+              struct GNUNET_CADET_TransmitHandle *th)
+{
+  GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
+  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == th->timeout.abs_value_us)
+    return;
+  th->timeout_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                    (th->timeout), &timeout_transmission, th);
+}
+
+
+/**
+ * Auxiliary function to send an already constructed packet to the service.
+ * Takes care of creating a new queue element, copying the message and
+ * calling the tmt_rdy function if necessary.
+ *
+ * @param h cadet handle
+ * @param msg message to transmit
+ * @param channel channel this send is related to (NULL if N/A)
+ */
+static void
+send_packet (struct GNUNET_CADET_Handle *h,
+             const struct GNUNET_MessageHeader *msg,
+             struct GNUNET_CADET_Channel *channel);
+
+
+/**
+ * Send an ack on the channel to confirm the processing of a message.
+ *
+ * @param ch Channel on which to send the ACK.
+ */
+static void
+send_ack (struct GNUNET_CADET_Channel *ch)
+{
+  struct GNUNET_CADET_LocalAck msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
+  msg.header.size = htons (sizeof (msg));
+  msg.channel_id = htonl (ch->chid);
+
+  send_packet (ch->cadet, &msg.header, ch);
+  return;
+}
+
+
+
+/**
+ * Reconnect callback: tries to reconnect again after a failer previous
+ * reconnecttion
+ * @param cls closure (cadet handle)
+ * @param tc task context
+ */
+static void
+reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Send a connect packet to the service with the applications and types
+ * requested by the user.
+ *
+ * @param h The cadet handle.
+ *
+ */
+static void
+send_connect (struct GNUNET_CADET_Handle *h)
+{
+  size_t size;
+
+  size = sizeof (struct GNUNET_CADET_ClientConnect);
+  size += h->n_ports * sizeof (uint32_t);
+  {
+    char buf[size] GNUNET_ALIGN;
+    struct GNUNET_CADET_ClientConnect *msg;
+    uint32_t *ports;
+    uint16_t i;
+
+    /* build connection packet */
+    msg = (struct GNUNET_CADET_ClientConnect *) buf;
+    msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT);
+    msg->header.size = htons (size);
+    ports = (uint32_t *) &msg[1];
+    for (i = 0; i < h->n_ports; i++)
+    {
+      ports[i] = htonl (h->ports[i]);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
+           h->ports[i]);
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Sending %lu bytes long message with %u ports\n",
+         ntohs (msg->header.size), h->n_ports);
+    send_packet (h, &msg->header, NULL);
+  }
+}
+
+
+/**
+ * Reconnect to the service, retransmit all infomation to try to restore the
+ * original state.
+ *
+ * @param h handle to the cadet
+ *
+ * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
+ */
+static int
+do_reconnect (struct GNUNET_CADET_Handle *h)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
+
+  /* disconnect */
+  if (NULL != h->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+    h->th = NULL;
+  }
+  if (NULL != h->client)
+  {
+    GNUNET_CLIENT_disconnect (h->client);
+  }
+
+  /* connect again */
+  h->client = GNUNET_CLIENT_connect ("cadet", h->cfg);
+  if (h->client == NULL)
+  {
+    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
+                                                      &reconnect_cbk, h);
+    h->reconnect_time =
+        GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
+                                  GNUNET_TIME_relative_multiply
+                                  (h->reconnect_time, 2));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Next retry in %s\n",
+         GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
+                                                 GNUNET_NO));
+    GNUNET_break (0);
+    return GNUNET_NO;
+  }
+  else
+  {
+    h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
+  }
+  send_connect (h);
+  return GNUNET_YES;
+}
+
+/**
+ * Reconnect callback: tries to reconnect again after a failer previous
+ * reconnecttion
+ * @param cls closure (cadet handle)
+ * @param tc task context
+ */
+static void
+reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_CADET_Handle *h = cls;
+
+  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  do_reconnect (h);
+}
+
+
+/**
+ * Reconnect to the service, retransmit all infomation to try to restore the
+ * original state.
+ *
+ * @param h handle to the cadet
+ *
+ * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
+ */
+static void
+reconnect (struct GNUNET_CADET_Handle *h)
+{
+  struct GNUNET_CADET_Channel *ch;
+  struct GNUNET_CADET_Channel *next;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Requested RECONNECT, destroying all channels\n");
+  h->in_receive = GNUNET_NO;
+  for (ch = h->channels_head; NULL != ch; ch = next)
+  {
+    next = ch->next;
+    destroy_channel (ch, GNUNET_YES);
+  }
+  if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
+    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
+                                                      &reconnect_cbk, h);
+}
+
+
+/******************************************************************************/
+/***********************      RECEIVE HANDLERS     
****************************/
+/******************************************************************************/
+
+/**
+ * Process the new channel notification and add it to the channels in the 
handle
+ *
+ * @param h     The cadet handle
+ * @param msg   A message with the details of the new incoming channel
+ */
+static void
+process_channel_created (struct GNUNET_CADET_Handle *h,
+                        const struct GNUNET_CADET_ChannelMessage *msg)
+{
+  struct GNUNET_CADET_Channel *ch;
+  CADET_ChannelNumber chid;
+  uint32_t port;
+
+  chid = ntohl (msg->channel_id);
+  port = ntohl (msg->port);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X:%u\n", chid, 
port);
+  if (chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  if (NULL != h->new_channel)
+  {
+    void *ctx;
+
+    ch = create_channel (h, chid);
+    ch->allow_send = GNUNET_NO;
+    ch->peer = GNUNET_PEER_intern (&msg->peer);
+    ch->cadet = h;
+    ch->chid = chid;
+    ch->port = port;
+    ch->options = ntohl (msg->opt);
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  created channel %p\n", ch);
+    ctx = h->new_channel (h->cls, ch, &msg->peer, ch->port, ch->options);
+    if (NULL != ctx)
+      ch->ctx = ctx;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
+  }
+  else
+  {
+    struct GNUNET_CADET_ChannelMessage d_msg;
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming channels\n");
+
+    d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
+    d_msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
+    d_msg.channel_id = msg->channel_id;
+    memset (&d_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
+    d_msg.port = 0;
+    d_msg.opt = 0;
+
+    send_packet (h, &d_msg.header, NULL);
+  }
+  return;
+}
+
+
+/**
+ * Process the channel destroy notification and free associated resources
+ *
+ * @param h     The cadet handle
+ * @param msg   A message with the details of the channel being destroyed
+ */
+static void
+process_channel_destroy (struct GNUNET_CADET_Handle *h,
+                         const struct GNUNET_CADET_ChannelMessage *msg)
+{
+  struct GNUNET_CADET_Channel *ch;
+  CADET_ChannelNumber chid;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel Destroy received from service\n");
+  chid = ntohl (msg->channel_id);
+  ch = retrieve_channel (h, chid);
+
+  if (NULL == ch)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " destroying channel %X\n", ch->chid);
+  destroy_channel (ch, GNUNET_YES);
+}
+
+
+/**
+ * Process the incoming data packets, call appropriate handlers.
+ *
+ * @param h         The cadet handle
+ * @param message   A message encapsulating the data
+ */
+static void
+process_incoming_data (struct GNUNET_CADET_Handle *h,
+                       const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_MessageHeader *payload;
+  const struct GNUNET_CADET_MessageHandler *handler;
+  struct GNUNET_CADET_LocalData *dmsg;
+  struct GNUNET_CADET_Channel *ch;
+  size_t size;
+  unsigned int i;
+  uint16_t type;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
+  dmsg = (struct GNUNET_CADET_LocalData *) message;
+  ch = retrieve_channel (h, ntohl (dmsg->id));
+  if (NULL == ch)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  payload = (struct GNUNET_MessageHeader *) &dmsg[1];
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s data on channel %s [%X]\n",
+       GM_f2s (ch->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV),
+       GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (dmsg->id));
+
+  size = ntohs (message->size);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  %u bytes\n", size);
+
+  if (NULL == ch)
+  {
+    /* Channel was ignored/destroyed, probably service didn't get it yet */
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
+    return;
+  }
+  type = ntohs (payload->type);
+  size = ntohs (payload->size);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  payload type %s\n", GM_m2s (type));
+  for (i = 0; i < h->n_handlers; i++)
+  {
+    handler = &h->message_handlers[i];
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    checking handler for type %u\n",
+         handler->type);
+    if (handler->type == type)
+    {
+      if (GNUNET_OK !=
+          handler->callback (h->cls, ch, &ch->ctx, payload))
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
+        GNUNET_CADET_channel_destroy (ch);
+        return;
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "callback completed successfully\n");
+        return;
+      }
+    }
+  }
+}
+
+
+/**
+ * Process a local ACK message, enabling the client to send
+ * more data to the service.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+static void
+process_ack (struct GNUNET_CADET_Handle *h,
+             const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalAck *msg;
+  struct GNUNET_CADET_Channel *ch;
+  CADET_ChannelNumber chid;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
+  msg = (struct GNUNET_CADET_LocalAck *) message;
+  chid = ntohl (msg->channel_id);
+  ch = retrieve_channel (h, chid);
+  if (NULL == ch)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X!\n", ch->chid);
+  ch->allow_send = GNUNET_YES;
+  if (NULL == h->th && 0 < ch->packet_size)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n");
+    h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ch->packet_size,
+                                                 GNUNET_TIME_UNIT_FOREVER_REL,
+                                                 GNUNET_YES, &send_callback, 
h);
+  }
+}
+
+
+/*
+ * Process a local reply about info on all channels, pass info to the user.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+// static void
+// process_get_channels (struct GNUNET_CADET_Handle *h,
+//                      const struct GNUNET_MessageHeader *message)
+// {
+//   struct GNUNET_CADET_LocalInfo *msg;
+//
+//   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n");
+//
+//   if (NULL == h->channels_cb)
+//   {
+//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
+//     return;
+//   }
+//
+//   msg = (struct GNUNET_CADET_LocalInfo *) message;
+//   if (ntohs (message->size) !=
+//       (sizeof (struct GNUNET_CADET_LocalInfo) +
+//        sizeof (struct GNUNET_PeerIdentity)))
+//   {
+//     GNUNET_break_op (0);
+//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+//                 "Get channels message: size %hu - expected %u\n",
+//                 ntohs (message->size),
+//                 sizeof (struct GNUNET_CADET_LocalInfo));
+//     return;
+//   }
+//   h->channels_cb (h->channels_cls,
+//                   ntohl (msg->channel_id),
+//                   &msg->owner,
+//                   &msg->destination);
+// }
+
+
+
+/*
+ * Process a local monitor_channel reply, pass info to the user.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+// static void
+// process_show_channel (struct GNUNET_CADET_Handle *h,
+//                      const struct GNUNET_MessageHeader *message)
+// {
+//   struct GNUNET_CADET_LocalInfo *msg;
+//   size_t esize;
+//
+//   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n");
+//
+//   if (NULL == h->channel_cb)
+//   {
+//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
+//     return;
+//   }
+//
+//   /* Verify message sanity */
+//   msg = (struct GNUNET_CADET_LocalInfo *) message;
+//   esize = sizeof (struct GNUNET_CADET_LocalInfo);
+//   if (ntohs (message->size) != esize)
+//   {
+//     GNUNET_break_op (0);
+//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+//                 "Show channel message: size %hu - expected %u\n",
+//                 ntohs (message->size),
+//                 esize);
+//
+//     h->channel_cb (h->channel_cls, NULL, NULL);
+//     h->channel_cb = NULL;
+//     h->channel_cls = NULL;
+//
+//     return;
+//   }
+//
+//   h->channel_cb (h->channel_cls,
+//                  &msg->destination,
+//                  &msg->owner);
+// }
+
+
+
+/**
+ * Process a local reply about info on all tunnels, pass info to the user.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+static void
+process_get_peers (struct GNUNET_CADET_Handle *h,
+                     const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalInfoPeer *msg;
+  uint16_t size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Peer messasge received\n");
+
+  if (NULL == h->info_cb.peers_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
+    return;
+  }
+
+  size = ntohs (message->size);
+  if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size)
+  {
+    h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0);
+    h->info_cb.peers_cb = NULL;
+    h->info_cls = NULL;
+    return;
+  }
+
+  msg = (struct GNUNET_CADET_LocalInfoPeer *) message;
+  h->info_cb.peers_cb (h->info_cls, &msg->destination,
+                       (int) ntohs (msg->tunnel),
+                       (unsigned int ) ntohs (msg->paths),
+                       0);
+}
+
+
+/**
+ * Process a local peer info reply, pass info to the user.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+static void
+process_get_peer (struct GNUNET_CADET_Handle *h,
+                  const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg;
+  size_t esize;
+  size_t msize;
+  unsigned int ch_n;
+  unsigned int c_n;
+  struct GNUNET_CADET_Hash *conns;
+  CADET_ChannelNumber *chns;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n");
+  if (NULL == h->info_cb.tunnel_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
+    return;
+  }
+
+  /* Verify message sanity */
+  msg = (struct GNUNET_CADET_LocalInfoTunnel *) message;
+  msize = ntohs (message->size);
+  esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
+  if (esize > msize)
+  {
+    GNUNET_break_op (0);
+    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
+    goto clean_cls;
+  }
+  ch_n = ntohl (msg->channels);
+  c_n = ntohl (msg->connections);
+  esize += ch_n * sizeof (CADET_ChannelNumber);
+  esize += c_n * sizeof (struct GNUNET_CADET_Hash);
+  if (msize != esize)
+  {
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n",
+                msize, esize, ch_n, c_n);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n",
+                sizeof (struct GNUNET_CADET_LocalInfoTunnel),
+                sizeof (CADET_ChannelNumber), sizeof (struct GNUNET_HashCode));
+    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
+    goto clean_cls;
+  }
+
+  /* Call Callback with tunnel info. */
+  conns = (struct GNUNET_CADET_Hash *) &msg[1];
+  chns = (CADET_ChannelNumber *) &conns[c_n];
+  h->info_cb.tunnel_cb (h->info_cls, &msg->destination,
+                        ch_n, c_n, chns, conns,
+                        ntohs (msg->estate), ntohs (msg->cstate));
+
+  clean_cls:
+  h->info_cb.tunnel_cb = NULL;
+  h->info_cls = NULL;
+}
+
+
+/**
+ * Process a local reply about info on all tunnels, pass info to the user.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+static void
+process_get_tunnels (struct GNUNET_CADET_Handle *h,
+                     const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg;
+  uint16_t size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnels messasge received\n");
+
+  if (NULL == h->info_cb.tunnels_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
+    return;
+  }
+
+  size = ntohs (message->size);
+  if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size)
+  {
+    h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0);
+    h->info_cb.tunnels_cb = NULL;
+    h->info_cls = NULL;
+    return;
+  }
+
+  msg = (struct GNUNET_CADET_LocalInfoTunnel *) message;
+  h->info_cb.tunnels_cb (h->info_cls, &msg->destination,
+                         ntohl (msg->channels), ntohl (msg->connections),
+                         ntohs (msg->estate), ntohs (msg->cstate));
+
+}
+
+
+/**
+ * Process a local tunnel info reply, pass info to the user.
+ *
+ * @param h Cadet handle.
+ * @param message Message itself.
+ */
+static void
+process_get_tunnel (struct GNUNET_CADET_Handle *h,
+                    const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg;
+  size_t esize;
+  size_t msize;
+  unsigned int ch_n;
+  unsigned int c_n;
+  struct GNUNET_CADET_Hash *conns;
+  CADET_ChannelNumber *chns;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n");
+  if (NULL == h->info_cb.tunnel_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
+    return;
+  }
+
+  /* Verify message sanity */
+  msg = (struct GNUNET_CADET_LocalInfoTunnel *) message;
+  msize = ntohs (message->size);
+  esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
+  if (esize > msize)
+  {
+    GNUNET_break_op (0);
+    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
+    goto clean_cls;
+  }
+  ch_n = ntohl (msg->channels);
+  c_n = ntohl (msg->connections);
+  esize += ch_n * sizeof (CADET_ChannelNumber);
+  esize += c_n * sizeof (struct GNUNET_CADET_Hash);
+  if (msize != esize)
+  {
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n",
+                msize, esize, ch_n, c_n);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n",
+                sizeof (struct GNUNET_CADET_LocalInfoTunnel),
+                sizeof (CADET_ChannelNumber), sizeof (struct GNUNET_HashCode));
+    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
+    goto clean_cls;
+  }
+
+  /* Call Callback with tunnel info. */
+  conns = (struct GNUNET_CADET_Hash *) &msg[1];
+  chns = (CADET_ChannelNumber *) &conns[c_n];
+  h->info_cb.tunnel_cb (h->info_cls, &msg->destination,
+                ch_n, c_n, chns, conns,
+                ntohs (msg->estate), ntohs (msg->cstate));
+
+clean_cls:
+  h->info_cb.tunnel_cb = NULL;
+  h->info_cls = NULL;
+}
+
+
+/**
+ * Function to process all messages received from the service
+ *
+ * @param cls closure
+ * @param msg message received, NULL on timeout or fatal error
+ */
+static void
+msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CADET_Handle *h = cls;
+  uint16_t type;
+
+  if (msg == NULL)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Cadet service disconnected, reconnecting\n", h);
+    reconnect (h);
+    return;
+  }
+  type = ntohs (msg->type);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
+       GM_m2s (type));
+  switch (type)
+  {
+    /* Notify of a new incoming channel */
+  case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    process_channel_created (h, (struct GNUNET_CADET_ChannelMessage *) msg);
+    break;
+    /* Notify of a channel disconnection */
+  case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: /* TODO separate(gid 
problem)*/
+  case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+    process_channel_destroy (h, (struct GNUNET_CADET_ChannelMessage *) msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA:
+    process_incoming_data (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK:
+    process_ack (h, msg);
+    break;
+//   case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
+//     process_get_channels (h, msg);
+//     break;
+//   case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
+//     process_show_channel (h, msg);
+//     break;
+  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
+    process_get_peers (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
+    process_get_peer (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
+    process_get_tunnels (h, msg);
+    break;
+  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
+    process_get_tunnel (h, msg);
+    break;
+//   case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
+//     process_show_channel (h, msg);
+//     break;
+  default:
+    /* We shouldn't get any other packages, log and ignore */
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "unsolicited message form service (type %s)\n",
+         GM_m2s (ntohs (msg->type)));
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
+  if (GNUNET_YES == h->in_receive)
+  {
+    GNUNET_CLIENT_receive (h->client, &msg_received, h,
+                           GNUNET_TIME_UNIT_FOREVER_REL);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "in receive off, not calling CLIENT_receive\n");
+  }
+}
+
+
+/******************************************************************************/
+/************************       SEND FUNCTIONS     
****************************/
+/******************************************************************************/
+
+/**
+ * Function called to send a message to the service.
+ * "buf" will be NULL and "size" zero if the socket was closed for writing in
+ * the meantime.
+ *
+ * @param cls closure, the cadet handle
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the connect message
+ * @return number of bytes written to buf
+ */
+static size_t
+send_callback (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_CADET_Handle *h = cls;
+  struct GNUNET_CADET_TransmitHandle *th;
+  struct GNUNET_CADET_TransmitHandle *next;
+  struct GNUNET_CADET_Channel *ch;
+  char *cbuf = buf;
+  size_t tsize;
+  size_t psize;
+  size_t nsize;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
+  if ((0 == size) || (NULL == buf))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
+    reconnect (h);
+    h->th = NULL;
+    return 0;
+  }
+  tsize = 0;
+  next = h->th_head;
+  nsize = message_ready_size (h);
+  while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
+  {
+    ch = th->channel;
+    if (GNUNET_YES == th_is_payload (th))
+    {
+      struct GNUNET_CADET_LocalData *dmsg;
+      struct GNUNET_MessageHeader *mh;
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload\n");
+      if (GNUNET_NO == ch->allow_send)
+      {
+        /* This channel is not ready to transmit yet, try next message */
+        next = th->next;
+        continue;
+      }
+      ch->packet_size = 0;
+      GNUNET_assert (size >= th->size);
+      dmsg = (struct GNUNET_CADET_LocalData *) cbuf;
+      mh = (struct GNUNET_MessageHeader *) &dmsg[1];
+      psize = th->notify (th->notify_cls,
+                          size - sizeof (struct GNUNET_CADET_LocalData),
+                          mh);
+      if (psize > 0)
+      {
+        psize += sizeof (struct GNUNET_CADET_LocalData);
+        GNUNET_assert (size >= psize);
+        dmsg->header.size = htons (psize);
+        dmsg->id = htonl (ch->chid);
+        dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload type %s\n",
+             GM_m2s (ntohs (mh->type)));
+                ch->allow_send = GNUNET_NO;
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "#  callback returned size 0, "
+             "application canceled transmission\n");
+      }
+    }
+    else
+    {
+      struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  cadet internal traffic, type %s\n",
+           GM_m2s (ntohs (mh->type)));
+      memcpy (cbuf, &th[1], th->size);
+      psize = th->size;
+    }
+    if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel (th->timeout_task);
+    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
+    GNUNET_free (th);
+    next = h->th_head;
+    nsize = message_ready_size (h);
+    cbuf += psize;
+    size -= psize;
+    tsize += psize;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "#  total size: %u\n", tsize);
+  h->th = NULL;
+  size = message_ready_size (h);
+  if (0 != size)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "#  next size: %u\n", size);
+    h->th =
+        GNUNET_CLIENT_notify_transmit_ready (h->client, size,
+                                             GNUNET_TIME_UNIT_FOREVER_REL,
+                                             GNUNET_YES, &send_callback, h);
+  }
+  else
+  {
+    if (NULL != h->th_head)
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  can't transmit any more\n");
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  nothing left to transmit\n");
+  }
+  if (GNUNET_NO == h->in_receive)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
+    h->in_receive = GNUNET_YES;
+    GNUNET_CLIENT_receive (h->client, &msg_received, h,
+                           GNUNET_TIME_UNIT_FOREVER_REL);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
+  return tsize;
+}
+
+
+/**
+ * Auxiliary function to send an already constructed packet to the service.
+ * Takes care of creating a new queue element, copying the message and
+ * calling the tmt_rdy function if necessary.
+ *
+ * @param h cadet handle
+ * @param msg message to transmit
+ * @param channel channel this send is related to (NULL if N/A)
+ */
+static void
+send_packet (struct GNUNET_CADET_Handle *h,
+             const struct GNUNET_MessageHeader *msg,
+             struct GNUNET_CADET_Channel *channel)
+{
+  struct GNUNET_CADET_TransmitHandle *th;
+  size_t msize;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
+       GM_m2s(ntohs(msg->type)));
+  msize = ntohs (msg->size);
+  th = GNUNET_malloc (sizeof (struct GNUNET_CADET_TransmitHandle) + msize);
+  th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
+  th->size = msize;
+  th->channel = channel;
+  memcpy (&th[1], msg, msize);
+  add_to_queue (h, th);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
+  if (NULL != h->th)
+    return;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", 
msize);
+  h->th =
+      GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_YES, &send_callback, h);
+}
+
+
+/******************************************************************************/
+/**********************      API CALL DEFINITIONS     
*************************/
+/******************************************************************************/
+
+struct GNUNET_CADET_Handle *
+GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
+                     GNUNET_CADET_InboundChannelNotificationHandler 
new_channel,
+                     GNUNET_CADET_ChannelEndHandler cleaner,
+                     const struct GNUNET_CADET_MessageHandler *handlers,
+                     const uint32_t *ports)
+{
+  struct GNUNET_CADET_Handle *h;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n");
+  h = GNUNET_new (struct GNUNET_CADET_Handle);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
+  h->cfg = cfg;
+  h->new_channel = new_channel;
+  h->cleaner = cleaner;
+  h->client = GNUNET_CLIENT_connect ("cadet", cfg);
+  if (h->client == NULL)
+  {
+    GNUNET_break (0);
+    GNUNET_free (h);
+    return NULL;
+  }
+  h->cls = cls;
+  h->message_handlers = handlers;
+  h->ports = ports;
+  h->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+  h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
+  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if (NULL != ports && ports[0] != 0 && NULL == new_channel)
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "no new channel handler given, ports parameter is useless!!\n");
+  }
+  if ((NULL == ports || ports[0] == 0) && NULL != new_channel)
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "no ports given, new channel handler will never be called!!\n");
+  }
+  /* count handlers */
+  for (h->n_handlers = 0;
+       handlers && handlers[h->n_handlers].type;
+       h->n_handlers++) ;
+  for (h->n_ports = 0;
+       ports && ports[h->n_ports];
+       h->n_ports++) ;
+  send_connect (h);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect() END\n");
+  return h;
+}
+
+
+void
+GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
+{
+  struct GNUNET_CADET_Channel *ch;
+  struct GNUNET_CADET_Channel *aux;
+  struct GNUNET_CADET_TransmitHandle *th;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET DISCONNECT\n");
+
+  ch = handle->channels_head;
+  while (NULL != ch)
+  {
+    aux = ch->next;
+    if (ch->chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+    {
+      GNUNET_break (0);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid);
+    }
+    destroy_channel (ch, GNUNET_YES);
+    ch = aux;
+  }
+  while ( (th = handle->th_head) != NULL)
+  {
+    struct GNUNET_MessageHeader *msg;
+
+    /* Make sure it is an allowed packet (everything else should have been
+     * already canceled).
+     */
+    GNUNET_break (GNUNET_NO == th_is_payload (th));
+    msg = (struct GNUNET_MessageHeader *) &th[1];
+    switch (ntohs(msg->type))
+    {
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT:
+      case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+      case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
+      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
+        break;
+      default:
+        GNUNET_break (0);
+        LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
+             ntohs(msg->type));
+    }
+
+    GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
+    GNUNET_free (th);
+  }
+
+  if (NULL != handle->th)
+  {
+    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
+    handle->th = NULL;
+  }
+  if (NULL != handle->client)
+  {
+    GNUNET_CLIENT_disconnect (handle->client);
+    handle->client = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel(handle->reconnect_task);
+    handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Create a new channel towards a remote peer.
+ *
+ * If the destination port is not open by any peer or the destination peer
+ * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called
+ * for this channel.
+ *
+ * @param h cadet handle
+ * @param channel_ctx client's channel context to associate with the channel
+ * @param peer peer identity the channel should go to
+ * @param port Port number.
+ * @param options CadetOption flag field, with all desired option bits set to 
1.
+ *
+ * @return handle to the channel
+ */
+struct GNUNET_CADET_Channel *
+GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
+                            void *channel_ctx,
+                            const struct GNUNET_PeerIdentity *peer,
+                            uint32_t port,
+                            enum GNUNET_CADET_ChannelOption options)
+{
+  struct GNUNET_CADET_Channel *ch;
+  struct GNUNET_CADET_ChannelMessage msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Creating new channel to %s:%u\n",
+       GNUNET_i2s (peer), port);
+  ch = create_channel (h, 0);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", ch);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", ch->chid);
+  ch->ctx = channel_ctx;
+  ch->peer = GNUNET_PEER_intern (peer);
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
+  msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
+  msg.channel_id = htonl (ch->chid);
+  msg.port = htonl (port);
+  msg.peer = *peer;
+  msg.opt = htonl (options);
+  ch->allow_send = 0;
+  send_packet (h, &msg.header, ch);
+  return ch;
+}
+
+
+void
+GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
+{
+  struct GNUNET_CADET_Handle *h;
+  struct GNUNET_CADET_ChannelMessage msg;
+  struct GNUNET_CADET_TransmitHandle *th;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying channel\n");
+  h = channel->cadet;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
+  msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
+  msg.channel_id = htonl (channel->chid);
+  memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
+  msg.port = 0;
+  msg.opt = 0;
+  th = h->th_head;
+  while (th != NULL)
+  {
+    struct GNUNET_CADET_TransmitHandle *aux;
+    if (th->channel == channel)
+    {
+      aux = th->next;
+      /* FIXME call the handler? */
+      if (GNUNET_YES == th_is_payload (th))
+        th->notify (th->notify_cls, 0, NULL);
+      GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
+      GNUNET_free (th);
+      th = aux;
+    }
+    else
+      th = th->next;
+  }
+
+  destroy_channel (channel, GNUNET_YES);
+  send_packet (h, &msg.header, NULL);
+}
+
+
+/**
+ * Get information about a channel.
+ *
+ * @param channel Channel handle.
+ * @param option Query (GNUNET_CADET_OPTION_*).
+ * @param ... dependant on option, currently not used
+ *
+ * @return Union with an answer to the query.
+ */
+const union GNUNET_CADET_ChannelInfo *
+GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
+                              enum GNUNET_CADET_ChannelOption option, ...)
+{
+  static int bool_flag;
+  const union GNUNET_CADET_ChannelInfo *ret;
+
+  switch (option)
+  {
+    case GNUNET_CADET_OPTION_NOBUFFER:
+    case GNUNET_CADET_OPTION_RELIABLE:
+    case GNUNET_CADET_OPTION_OOORDER:
+      if (0 != (option & channel->options))
+        bool_flag = GNUNET_YES;
+      else
+        bool_flag = GNUNET_NO;
+      ret = (const union GNUNET_CADET_ChannelInfo *) &bool_flag;
+      break;
+    case GNUNET_CADET_OPTION_PEER:
+      ret = (const union GNUNET_CADET_ChannelInfo *) GNUNET_PEER_resolve2 
(channel->peer);
+      break;
+    default:
+      GNUNET_break (0);
+      return NULL;
+  }
+
+  return ret;
+}
+
+struct GNUNET_CADET_TransmitHandle *
+GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel, int 
cork,
+                                   struct GNUNET_TIME_Relative maxdelay,
+                                   size_t notify_size,
+                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
+                                   void *notify_cls)
+{
+  struct GNUNET_CADET_TransmitHandle *th;
+
+  GNUNET_assert (NULL != channel);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    on channel %X\n", channel->chid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    allow_send %d\n", channel->allow_send);
+  if (channel->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
+  GNUNET_assert (NULL != notify);
+  GNUNET_assert (0 == channel->packet_size); // Only one data packet allowed
+  th = GNUNET_new (struct GNUNET_CADET_TransmitHandle);
+  th->channel = channel;
+  th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
+  th->size = notify_size + sizeof (struct GNUNET_CADET_LocalData);
+  channel->packet_size = th->size;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
+  th->notify = notify;
+  th->notify_cls = notify_cls;
+  add_to_queue (channel->cadet, th);
+  if (NULL != channel->cadet->th)
+    return th;
+  if (GNUNET_NO == channel->allow_send)
+    return th;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    call client notify tmt rdy\n");
+  channel->cadet->th =
+      GNUNET_CLIENT_notify_transmit_ready (channel->cadet->client, th->size,
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_YES, &send_callback,
+                                           channel->cadet);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY END\n");
+  return th;
+}
+
+
+void
+GNUNET_CADET_notify_transmit_ready_cancel (struct GNUNET_CADET_TransmitHandle 
*th)
+{
+  struct GNUNET_CADET_Handle *cadet;
+
+  th->channel->packet_size = 0;
+  cadet = th->channel->cadet;
+  if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (th->timeout_task);
+  GNUNET_CONTAINER_DLL_remove (cadet->th_head, cadet->th_tail, th);
+  GNUNET_free (th);
+  if ((0 == message_ready_size (cadet)) && (NULL != cadet->th))
+  {
+    /* queue empty, no point in asking for transmission */
+    GNUNET_CLIENT_notify_transmit_ready_cancel (cadet->th);
+    cadet->th = NULL;
+  }
+}
+
+
+void
+GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
+{
+  send_ack (channel);
+}
+
+
+static void
+send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type)
+{
+  struct GNUNET_MessageHeader msg;
+
+  msg.size = htons (sizeof (msg));
+  msg.type = htons (type);
+  send_packet (h, &msg, NULL);
+}
+
+
+/**
+ * Request information about peers known to the running cadet service.
+ * The callback will be called for every peer known to the service.
+ * Only one info request (of any kind) can be active at once.
+ *
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the cadet peer.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ *
+ * @return #GNUNET_OK / #GNUNET_SYSERR
+ */
+int
+GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h,
+                       GNUNET_CADET_PeersCB callback,
+                       void *callback_cls)
+{
+  if (NULL != h->info_cb.peers_cb)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
+  h->info_cb.peers_cb = callback;
+  h->info_cls = callback_cls;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cancel a peer info request. The callback will not be called (anymore).
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Cadet handle.
+ *
+ * @return Closure given to GNUNET_CADET_get_peers.
+ */
+void *
+GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h)
+{
+  void *cls;
+
+  cls = h->info_cls;
+  h->info_cb.peers_cb = NULL;
+  h->info_cls = NULL;
+  return cls;
+}
+
+
+/**
+ * Request information about a peer known to the running cadet peer.
+ * The callback will be called for the tunnel once.
+ * Only one info request (of any kind) can be active at once.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the cadet peer.
+ * @param id Peer whose tunnel to examine.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ *
+ * @return #GNUNET_OK / #GNUNET_SYSERR
+ */
+int
+GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h,
+                      const struct GNUNET_PeerIdentity *id,
+                      GNUNET_CADET_PeerCB callback,
+                      void *callback_cls)
+{
+  struct GNUNET_CADET_LocalInfo msg;
+
+  if (NULL != h->info_cb.peer_cb)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  memset (&msg, 0, sizeof (msg));
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
+  msg.peer = *id;
+  send_packet (h, &msg.header, NULL);
+  h->info_cb.peer_cb = callback;
+  h->info_cls = callback_cls;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Request information about tunnels of the running cadet peer.
+ * The callback will be called for every tunnel of the service.
+ * Only one info request (of any kind) can be active at once.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the cadet peer.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ *
+ * @return #GNUNET_OK / #GNUNET_SYSERR
+ */
+int
+GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h,
+                         GNUNET_CADET_TunnelsCB callback,
+                         void *callback_cls)
+{
+  if (NULL != h->info_cb.tunnels_cb)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
+  h->info_cb.tunnels_cb = callback;
+  h->info_cls = callback_cls;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cancel a monitor request. The monitor callback will not be called.
+ *
+ * @param h Cadet handle.
+ *
+ * @return Closure given to GNUNET_CADET_get_tunnels.
+ */
+void *
+GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h)
+{
+  void *cls;
+
+  h->info_cb.tunnels_cb = NULL;
+  cls = h->info_cls;
+  h->info_cls = NULL;
+
+  return cls;
+}
+
+
+
+/**
+ * Request information about a tunnel of the running cadet peer.
+ * The callback will be called for the tunnel once.
+ * Only one info request (of any kind) can be active at once.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ *
+ * @param h Handle to the cadet peer.
+ * @param id Peer whose tunnel to examine.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ *
+ * @return #GNUNET_OK / #GNUNET_SYSERR
+ */
+int
+GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h,
+                        const struct GNUNET_PeerIdentity *id,
+                        GNUNET_CADET_TunnelCB callback,
+                        void *callback_cls)
+{
+  struct GNUNET_CADET_LocalInfo msg;
+
+  if (NULL != h->info_cb.tunnel_cb)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  memset (&msg, 0, sizeof (msg));
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
+  msg.peer = *id;
+  send_packet (h, &msg.header, NULL);
+  h->info_cb.tunnel_cb = callback;
+  h->info_cls = callback_cls;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Request information about a specific channel of the running cadet peer.
+ *
+ * WARNING: unstable API, likely to change in the future!
+ * FIXME Add destination option.
+ *
+ * @param h Handle to the cadet peer.
+ * @param initiator ID of the owner of the channel.
+ * @param channel_number Channel number.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ *
+ * @return #GNUNET_OK / #GNUNET_SYSERR
+ */
+int
+GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h,
+                         struct GNUNET_PeerIdentity *initiator,
+                         unsigned int channel_number,
+                         GNUNET_CADET_ChannelCB callback,
+                         void *callback_cls)
+{
+  struct GNUNET_CADET_LocalInfo msg;
+
+  if (NULL != h->info_cb.channel_cb)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL);
+  msg.peer = *initiator;
+  msg.channel_id = htonl (channel_number);
+//   msg.reserved = 0;
+  send_packet (h, &msg.header, NULL);
+  h->info_cb.channel_cb = callback;
+  h->info_cls = callback_cls;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called to notify a client about the connection
+ * begin ready to queue more data.  "buf" will be
+ * NULL and "size" zero if the connection was closed for
+ * writing in the meantime.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+cadet_mq_ntr (void *cls, size_t size,
+             void *buf)
+{
+  struct GNUNET_MQ_Handle *mq = cls;
+  struct CadetMQState *state = GNUNET_MQ_impl_state (mq);
+  const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
+  uint16_t msize;
+
+  state->th = NULL;
+  if (NULL == buf)
+  {
+    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
+    return 0;
+  }
+  msize = ntohs (msg->size);
+  GNUNET_assert (msize <= size);
+  memcpy (buf, msg, msize);
+  GNUNET_MQ_impl_send_continue (mq);
+  return msize;
+}
+
+
+/**
+ * Signature of functions implementing the
+ * sending functionality of a message queue.
+ *
+ * @param mq the message queue
+ * @param msg the message to send
+ * @param impl_state state of the implementation
+ */
+static void
+cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
+                   const struct GNUNET_MessageHeader *msg, void *impl_state)
+{
+  struct CadetMQState *state = impl_state;
+
+  GNUNET_assert (NULL == state->th);
+  state->th =
+      GNUNET_CADET_notify_transmit_ready (state->channel,
+                                         /* FIXME: add option for corking */
+                                         GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         ntohs (msg->size),
+                                         cadet_mq_ntr, mq);
+
+}
+
+
+/**
+ * Signature of functions implementing the
+ * destruction of a message queue.
+ * Implementations must not free 'mq', but should
+ * take care of 'impl_state'.
+ *
+ * @param mq the message queue to destroy
+ * @param impl_state state of the implementation
+ */
+static void
+cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
+{
+  struct CadetMQState *state = impl_state;
+
+  if (NULL != state->th)
+    GNUNET_CADET_notify_transmit_ready_cancel (state->th);
+
+  GNUNET_free (state);
+}
+
+
+/**
+ * Create a message queue for a cadet channel.
+ * The message queue can only be used to transmit messages,
+ * not to receive them.
+ *
+ * @param channel the channel to create the message qeue for
+ * @return a message queue to messages over the channel
+ */
+struct GNUNET_MQ_Handle *
+GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel)
+{
+  struct GNUNET_MQ_Handle *mq;
+  struct CadetMQState *state;
+
+  state = GNUNET_new (struct CadetMQState);
+  state->channel = channel;
+
+  mq = GNUNET_MQ_queue_for_callbacks (cadet_mq_send_impl,
+                                      cadet_mq_destroy_impl,
+                                      NULL, /* FIXME: cancel impl. */
+                                      state,
+                                      NULL, /* no msg handlers */
+                                      NULL, /* no err handlers */
+                                      NULL); /* no handler cls */
+  return mq;
+}
+

Copied: gnunet/src/cadet/cadet_common.c (from rev 33185, 
gnunet/src/mesh/cadet_common.c)
===================================================================
--- gnunet/src/cadet/cadet_common.c                             (rev 0)
+++ gnunet/src/cadet/cadet_common.c     2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,348 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/cadet_common.c
+ * @brief CADET helper functions
+ * @author Bartlomiej Polot
+ */
+
+#include "cadet.h"
+
+/**
+ * @brief Translate a fwd variable into a string representation, for logging.
+ *
+ * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO)
+ *
+ * @return String representing FWD or BCK.
+ */
+char *
+GM_f2s (int fwd)
+{
+  if (GNUNET_YES == fwd)
+  {
+    return "FWD";
+  }
+  else if (GNUNET_NO == fwd)
+  {
+    return "BCK";
+  }
+  else
+  {
+    /* Not an error, can happen with CONNECTION_BROKEN messages. */
+    return "";
+  }
+}
+
+int
+GM_is_pid_bigger (uint32_t bigger, uint32_t smaller)
+{
+    return (GNUNET_YES == PID_OVERFLOW (smaller, bigger) ||
+            (bigger > smaller && GNUNET_NO == PID_OVERFLOW (bigger, smaller)));
+}
+
+
+uint32_t
+GM_max_pid (uint32_t a, uint32_t b)
+{
+  if (GM_is_pid_bigger(a, b))
+    return a;
+  return b;
+}
+
+
+uint32_t
+GM_min_pid (uint32_t a, uint32_t b)
+{
+  if (GM_is_pid_bigger(a, b))
+    return b;
+  return a;
+}
+
+
+const struct GNUNET_HashCode *
+GM_h2hc (const struct GNUNET_CADET_Hash *id)
+{
+  static struct GNUNET_HashCode hc;
+  memcpy (&hc, id, sizeof (*id));
+
+  return &hc;
+}
+
+
+const char *
+GM_h2s (const struct GNUNET_CADET_Hash *id)
+{
+  static char s[53];
+
+  memcpy (s, GNUNET_h2s_full (GM_h2hc (id)), 52);
+  s[52] = '\0';
+
+  return s;
+}
+
+
+#if !defined(GNUNET_CULL_LOGGING)
+const char *
+GM_m2s (uint16_t m)
+{
+  static char buf[32];
+  const char *t;
+
+  switch (m)
+  {
+      /**
+       * Request the creation of a path
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+      t = "CONNECTION_CREATE";
+      break;
+
+      /**
+       * Request the modification of an existing path
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+      t = "CONNECTION_ACK";
+      break;
+
+      /**
+       * Notify that a connection of a path is no longer valid
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
+      t = "CONNECTION_BROKEN";
+      break;
+
+      /**
+       * At some point, the route will spontaneously change
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED:
+      t = "PATH_CHANGED";
+      break;
+
+      /**
+       * Transport payload data.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+      t = "DATA";
+      break;
+
+    /**
+     * Confirm receipt of payload data.
+     */
+    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+      t = "DATA_ACK";
+      break;
+
+      /**
+       * Key exchange encapsulation.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_KX:
+      t = "KX";
+      break;
+
+      /**
+       * New ephemeral key.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL:
+      t = "KX_EPHEMERAL";
+      break;
+
+      /**
+       * Challenge to test peer's session key.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_KX_PING:
+      t = "KX_PING";
+      break;
+
+      /**
+       * Answer to session key challenge.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_KX_PONG:
+      t = "KX_PONG";
+      break;
+
+      /**
+       * Request the destuction of a path
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
+      t = "CONNECTION_DESTROY";
+      break;
+
+      /**
+       * ACK for a data packet.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+      t = "ACK";
+      break;
+
+      /**
+       * POLL for ACK.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+      t = "POLL";
+      break;
+
+      /**
+       * Announce origin is still alive.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+      t = "KEEPALIVE";
+      break;
+
+    /**
+       * Connect to the cadet service, specifying subscriptions
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT:
+      t = "LOCAL_CONNECT";
+      break;
+
+      /**
+       * Ask the cadet service to create a new tunnel
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+      t = "CHANNEL_CREATE";
+      break;
+
+      /**
+       * Ask the cadet service to destroy a tunnel
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+      t = "CHANNEL_DESTROY";
+      break;
+
+      /**
+       * Confirm the creation of a channel.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+      t = "CHANNEL_ACK";
+      break;
+
+      /**
+       * Confirm the creation of a channel.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+      t = "CHANNEL_NACK";
+      break;
+
+      /**
+       * Encrypted payload.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+      t = "ENCRYPTED";
+      break;
+
+      /**
+       * Local payload traffic
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA:
+      t = "LOCAL_DATA";
+      break;
+
+      /**
+       * Local ACK for data.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK:
+      t = "LOCAL_ACK";
+      break;
+
+      /**
+       * Local monitoring of channels.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
+      t = "LOCAL_INFO_CHANNELS";
+      break;
+
+      /**
+       * Local monitoring of a channel.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
+      t = "LOCAL_INFO_CHANNEL";
+      break;
+
+      /**
+       * Local monitoring of service.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
+      t = "LOCAL_INFO_TUNNELS";
+      break;
+
+      /**
+       * Local monitoring of service.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
+      t = "LOCAL_INFO_TUNNEL";
+      break;
+
+      /**
+       * Local information about all connections of service.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTIONS:
+      t = "LOCAL_INFO_CONNECTIONS";
+      break;
+
+      /**
+       * Local information of service about a specific connection.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTION:
+      t = "LOCAL_INFO_CONNECTION";
+      break;
+
+      /**
+       * Local information about all peers known to the service.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
+      t = "LOCAL_INFO_PEERS";
+      break;
+
+      /**
+       * Local information of service about a specific peer.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
+      t = "LOCAL_INFO_PEER";
+      break;
+
+      /**
+       * Traffic (net-cat style) used by the Command Line Interface.
+       */
+    case GNUNET_MESSAGE_TYPE_CADET_CLI:
+      t = "CLI";
+      break;
+
+      /**
+       * 640kb should be enough for everybody
+       */
+    case 299:
+      t = "RESERVE_END";
+      break;
+
+    default:
+      sprintf(buf, "%u (UNKNOWN TYPE)", m);
+      return buf;
+  }
+  sprintf(buf, "{%18s}", t);
+  return buf;
+}
+#else
+const char *
+GM_m2s (uint16_t m)
+{
+  return "";
+}
+#endif

Copied: gnunet/src/cadet/cadet_path.c (from rev 33185, 
gnunet/src/mesh/cadet_path.c)
===================================================================
--- gnunet/src/cadet/cadet_path.c                               (rev 0)
+++ gnunet/src/cadet/cadet_path.c       2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,213 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/cadet_path.c
+ * @brief Path handling functions
+ * @author Bartlomiej Polot
+ */
+
+#include "cadet.h"
+#include "cadet_path.h"
+#include "gnunet-service-cadet_peer.h"
+
+/**
+ * @brief Destroy a path after some time has past.
+ *
+ * If the path is returned from DHT again after a while, try again.
+ *
+ * @param cls Closure (path to destroy).
+ * @param tc Task context.
+ */
+static void
+path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetPeerPath *path = cls;
+  struct CadetPeer *peer;
+
+  path->path_delete = GNUNET_SCHEDULER_NO_TASK;
+  peer = GMP_get_short (path->peers[path->length - 1]);
+  GMP_remove_path (peer, path);
+}
+
+
+/**
+ * Create a new path
+ *
+ * @param length How many hops will the path have.
+ *
+ * @return A newly allocated path with a peer array of the specified length.
+ */
+struct CadetPeerPath *
+path_new (unsigned int length)
+{
+  struct CadetPeerPath *p;
+
+  p = GNUNET_new (struct CadetPeerPath);
+  if (length > 0)
+  {
+    p->length = length;
+    p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id));
+  }
+  return p;
+}
+
+
+/**
+ * Invert the path
+ *
+ * @param path the path to invert
+ */
+void
+path_invert (struct CadetPeerPath *path)
+{
+  GNUNET_PEER_Id aux;
+  unsigned int i;
+
+  for (i = 0; i < path->length / 2; i++)
+  {
+    aux = path->peers[i];
+    path->peers[i] = path->peers[path->length - i - 1];
+    path->peers[path->length - i - 1] = aux;
+  }
+}
+
+
+/**
+ * Duplicate a path, incrementing short peer's rc.
+ *
+ * @param path The path to duplicate.
+ */
+struct CadetPeerPath *
+path_duplicate (const struct CadetPeerPath *path)
+{
+  struct CadetPeerPath *aux;
+  unsigned int i;
+
+  aux = path_new (path->length);
+  memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id));
+  for (i = 0; i < aux->length; i++)
+    GNUNET_PEER_change_rc (aux->peers[i], 1);
+  return aux;
+}
+
+
+/**
+ * Get the length of a path.
+ *
+ * @param path The path to measure, with the local peer at any point of it.
+ *
+ * @return Number of hops to reach destination.
+ *         UINT_MAX in case the peer is not in the path.
+ */
+unsigned int
+path_get_length (struct CadetPeerPath *path)
+{
+  if (NULL == path)
+    return UINT_MAX;
+  return path->length;
+}
+
+
+
+/**
+ * Mark path as invalid: keep it aroud for a while to avoid trying it in a 
loop.
+ *
+ * DHT_get sometimes returns bad cached results, for instance, on a locally
+ * cached result where the PUT followed a path that is no longer current.
+ *
+ * @param p Path to invalidate.
+ */
+void
+path_invalidate (struct CadetPeerPath *p)
+{
+  if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
+    return;
+
+  p->path_delete = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
+                                                 &path_destroy_delayed, p);
+}
+
+
+/**
+ * Test if a path is valid (or at least not known to be invalid).
+ *
+ * @param path Path to test.
+ *
+ * @return #GNUNET_YES If the path is valid or unknown,
+ *         #GNUNET_NO If the path is known to be invalid.
+ */
+int
+path_is_valid (const struct CadetPeerPath *path)
+{
+  return (GNUNET_SCHEDULER_NO_TASK == path->path_delete);
+}
+
+
+/**
+ * Destroy the path and free any allocated resources linked to it
+ *
+ * @param p the path to destroy
+ *
+ * @return GNUNET_OK on success
+ */
+int
+path_destroy (struct CadetPeerPath *p)
+{
+  if (NULL == p)
+    return GNUNET_OK;
+
+  GNUNET_PEER_decrement_rcs (p->peers, p->length);
+  GNUNET_free_non_null (p->peers);
+  if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
+    GNUNET_SCHEDULER_cancel (p->path_delete);
+  GNUNET_free (p);
+  return GNUNET_OK;
+}
+
+char *
+path_2s (struct CadetPeerPath *p)
+{
+  char *s;
+  char *old;
+  unsigned int i;
+
+  old = GNUNET_strdup ("");
+  for (i = 0; i < p->length; i++)
+  {
+    GNUNET_asprintf (&s, "%s %s",
+                     old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
+    GNUNET_free_non_null (old);
+    old = s;
+  }
+  return s;
+}
+
+void
+path_debug (struct CadetPeerPath *p)
+{
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n");
+  for (i = 0; i < p->length; i++)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %s\n",
+                GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n");
+}

Copied: gnunet/src/cadet/cadet_path.h (from rev 33185, 
gnunet/src/mesh/cadet_path.h)
===================================================================
--- gnunet/src/cadet/cadet_path.h                               (rev 0)
+++ gnunet/src/cadet/cadet_path.h       2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,185 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/cadet_path.h
+ * @brief Path handling functions
+ * @author Bartlomiej Polot
+ */
+
+#include "gnunet-service-cadet_connection.h"
+
+#ifndef CADET_PATH_H_
+#define CADET_PATH_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+  #if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+/******************************************************************************/
+/************************      DATA STRUCTURES     
****************************/
+/******************************************************************************/
+
+/**
+ * Information regarding a possible path to reach a single peer
+ */
+struct CadetPeerPath
+{
+
+    /**
+     * Linked list
+     */
+  struct CadetPeerPath *next;
+  struct CadetPeerPath *prev;
+
+    /**
+     * List of all the peers that form the path from origin to target.
+     */
+  GNUNET_PEER_Id *peers;
+
+    /**
+     * Number of peers (hops) in the path
+     */
+  unsigned int length;
+
+    /**
+     * User defined data store.
+     */
+  struct CadetConnection *c;
+
+    /**
+     * Path's score, how reliable is the path.
+     */
+//   int score;
+
+  /**
+   * Task to delete the path.
+   * We tried it, it didn't work, don't try again in a while.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier path_delete;
+
+};
+
+/******************************************************************************/
+/*************************        FUNCTIONS       
*****************************/
+/******************************************************************************/
+
+/**
+ * Create a new path.
+ *
+ * @param length How many hops will the path have.
+ *
+ * @return A newly allocated path with a peer array of the specified length.
+ */
+struct CadetPeerPath *
+path_new (unsigned int length);
+
+
+/**
+ * Invert the path.
+ *
+ * @param path The path to invert.
+ */
+void
+path_invert (struct CadetPeerPath *path);
+
+
+/**
+ * Duplicate a path, incrementing short peer's rc.
+ *
+ * @param path The path to duplicate.
+ */
+struct CadetPeerPath *
+path_duplicate (const struct CadetPeerPath *path);
+
+
+/**
+ * Get the length of a path.
+ *
+ * @param path The path to measure, with the local peer at any point of it.
+ *
+ * @return Number of hops to reach destination.
+ *         UINT_MAX in case the peer is not in the path.
+ */
+unsigned int
+path_get_length (struct CadetPeerPath *path);
+
+/**
+ * Mark path as invalid: keep it aroud for a while to avoid trying it in a 
loop.
+ *
+ * DHT_get sometimes returns bad cached results, for instance, on a locally
+ * cached result where the PUT followed a path that is no longer current.
+ *
+ * @param p Path to invalidate.
+ */
+void
+path_invalidate (struct CadetPeerPath *p);
+
+/**
+ * Test if a path is valid (or at least not known to be invalid).
+ *
+ * @param path Path to test.
+ *
+ * @return #GNUNET_YES If the path is valid or unknown,
+ *         #GNUNET_NO If the path is known to be invalid.
+ */
+int
+path_is_valid (const struct CadetPeerPath *path);
+
+/**
+ * Destroy the path and free any allocated resources linked to it
+ *
+ * @param p the path to destroy
+ *
+ * @return GNUNET_OK on success
+ */
+int
+path_destroy (struct CadetPeerPath *p);
+
+/**
+ * Path -> allocated one line string. Caller must free.
+ *
+ * @param p Path.
+ */
+char *
+path_2s (struct CadetPeerPath *p);
+
+/**
+ * Print info about the path for debug.
+ *
+ * @param p Path to debug.
+ */
+void
+path_debug (struct CadetPeerPath *p);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+  #endif
+  #ifdef __cplusplus
+}
+#endif
+
+
+/* ifndef CADET_PATH_H */
+#endif

Copied: gnunet/src/cadet/cadet_protocol.h (from rev 33185, 
gnunet/src/mesh/cadet_protocol.h)
===================================================================
--- gnunet/src/cadet/cadet_protocol.h                           (rev 0)
+++ gnunet/src/cadet/cadet_protocol.h   2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,459 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @author Bartlomiej Polot
+ * @file cadet/cadet_protocol.h
+ */
+
+#ifndef CADET_PROTOCOL_H_
+#define CADET_PROTOCOL_H_
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "cadet.h"
+
+#ifdef __cplusplus
+
+struct GNUNET_CADET_TunnelMessage;
+extern "C"
+{
+#if 0
+  /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+/******************************************************************************/
+/********************      CADET NETWORK MESSAGES     
**************************/
+/******************************************************************************/
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message for cadet connection creation.
+ */
+struct GNUNET_CADET_ConnectionCreate
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
+     *
+     * Size: sizeof (struct GNUNET_CADET_ConnectionCreate) +
+     *       path_length * sizeof (struct GNUNET_PeerIdentity)
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the connection
+     */
+  struct GNUNET_CADET_Hash cid;
+
+    /**
+     * path_length structs defining the *whole* path from the origin [0] to the
+     * final destination [path_length-1].
+     */
+  /* struct GNUNET_PeerIdentity peers[path_length]; */
+};
+
+/**
+ * Message for ack'ing a connection
+ */
+struct GNUNET_CADET_ConnectionACK
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the connection.
+     */
+  struct GNUNET_CADET_Hash cid;
+
+};
+
+
+/**
+ * Message for encapsulation of a Key eXchange message in a connection.
+ */
+struct GNUNET_CADET_KX
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_KX.
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the connection.
+     */
+  struct GNUNET_CADET_Hash cid;
+
+  /* Specific KX message follows. */
+};
+
+
+/**
+ * Message transmitted with the signed ephemeral key of a peer.  The
+ * session key is then derived from the two ephemeral keys (ECDHE).
+ *
+ * As far as possible, same as CORE's EphemeralKeyMessage.
+ */
+struct GNUNET_CADET_KX_Ephemeral
+{
+
+  /**
+   * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Status of the sender (should be in "enum PeerStateMachine"), nbo.
+   */
+  int32_t sender_status GNUNET_PACKED;
+
+  /**
+   * An ECC signature of the 'origin' asserting the validity of
+   * the given ephemeral key.
+   */
+  struct GNUNET_CRYPTO_EddsaSignature signature;
+
+  /**
+   * Information about what is being signed.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * At what time was this key created (beginning of validity).
+   */
+  struct GNUNET_TIME_AbsoluteNBO creation_time;
+
+  /**
+   * When does the given ephemeral key expire (end of validity).
+   */
+  struct GNUNET_TIME_AbsoluteNBO expiration_time;
+
+  /**
+   * Ephemeral public ECC key (always for NIST P-521) encoded in a format 
suitable
+   * for network transmission as created using 'gcry_sexp_sprint'.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
+
+  /**
+   * Public key of the signing peer (persistent version, not the ephemeral 
public key).
+   */
+  struct GNUNET_PeerIdentity origin_identity;
+};
+
+
+/**
+ * We're sending an (encrypted) PING to the other peer to check if he
+ * can decrypt.  The other peer should respond with a PONG with the
+ * same content, except this time encrypted with the receiver's key.
+ */
+struct GNUNET_CADET_KX_Ping
+{
+  /**
+   * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_PING.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Seed for the IV
+   */
+  uint32_t iv GNUNET_PACKED;
+
+  /**
+   * Intended target of the PING, used primarily to check
+   * that decryption actually worked.
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Random number chosen to make reply harder.
+   */
+  uint32_t nonce GNUNET_PACKED;
+};
+
+
+/**
+ * Response to a PING.  Includes data from the original PING.
+ */
+struct GNUNET_CADET_KX_Pong
+{
+  /**
+   * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_PONG.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Seed for the IV
+   */
+  uint32_t iv GNUNET_PACKED;
+
+  /**
+   * Same nonce as in the reve.
+   */
+  uint32_t nonce GNUNET_PACKED;
+};
+
+
+/**
+ * Tunnel(ed) message.
+ */
+struct GNUNET_CADET_Encrypted
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the connection.
+   */
+  struct GNUNET_CADET_Hash cid;
+
+  /**
+   * ID of the packet (hop by hop).
+   */
+  uint32_t pid GNUNET_PACKED;
+
+  /**
+   * Number of hops to live.
+   */
+  uint32_t ttl GNUNET_PACKED;
+
+  /**
+   * Initialization Vector for payload encryption.
+   */
+  uint32_t iv GNUNET_PACKED;
+
+  /**
+   * MAC of the encrypted message, used to verify message integrity.
+   * Everything after this value  will be encrypted and authenticated.
+   */
+  struct GNUNET_CADET_Hash hmac;
+
+  /**
+   * Encrypted content follows.
+   */
+};
+
+
+/**
+ * Message to create a Channel.
+ */
+struct GNUNET_CADET_ChannelCreate
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the channel
+   */
+  CADET_ChannelNumber chid GNUNET_PACKED;
+
+  /**
+   * Destination port.
+   */
+  uint32_t port GNUNET_PACKED;
+
+  /**
+   * Channel options.
+   */
+  uint32_t opt GNUNET_PACKED;
+};
+
+
+/**
+ * Message to manage a Channel (ACK, NACK, Destroy).
+ */
+struct GNUNET_CADET_ChannelManage
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_{ACK|NACK|DESTROY}
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the channel
+   */
+  CADET_ChannelNumber chid GNUNET_PACKED;
+};
+
+
+/**
+ * Message for cadet data traffic.
+ */
+struct GNUNET_CADET_Data
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_UNICAST,
+     *       GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * Unique ID of the payload message
+     */
+  uint32_t mid GNUNET_PACKED;
+
+    /**
+     * ID of the channel
+     */
+  CADET_ChannelNumber chid GNUNET_PACKED;
+
+    /**
+     * Payload follows
+     */
+};
+
+
+/**
+ * Message to acknowledge end-to-end data.
+ */
+struct GNUNET_CADET_DataACK
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_CADET_DATA_ACK
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the channel
+   */
+  CADET_ChannelNumber chid GNUNET_PACKED;
+
+  /**
+   * Bitfield of already-received newer messages
+   * pid +  1 @ LSB
+   * pid + 64 @ MSB
+   */
+  uint64_t futures GNUNET_PACKED;
+
+  /**
+   * Last message ID received.
+   */
+  uint32_t mid GNUNET_PACKED;
+};
+
+
+/**
+ * Message to acknowledge cadet encrypted traffic.
+ */
+struct GNUNET_CADET_ACK
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_ACK
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * Maximum packet ID authorized.
+     */
+  uint32_t ack GNUNET_PACKED;
+
+    /**
+     * ID of the connection.
+     */
+  struct GNUNET_CADET_Hash cid;
+};
+
+
+/**
+ * Message to query a peer about its Flow Control status regarding a tunnel.
+ */
+struct GNUNET_CADET_Poll
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_POLL
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * Last packet sent.
+     */
+  uint32_t pid GNUNET_PACKED;
+
+    /**
+     * ID of the connection.
+     */
+  struct GNUNET_CADET_Hash cid;
+
+};
+
+
+/**
+ * Message for notifying a disconnection in a path
+ */
+struct GNUNET_CADET_ConnectionBroken
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the connection.
+     */
+  struct GNUNET_CADET_Hash cid;
+
+    /**
+     * ID of the endpoint
+     */
+  struct GNUNET_PeerIdentity peer1;
+
+    /**
+     * ID of the endpoint
+     */
+  struct GNUNET_PeerIdentity peer2;
+};
+
+
+/**
+ * Message to destroy a connection.
+ */
+struct GNUNET_CADET_ConnectionDestroy
+{
+    /**
+     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
+     */
+  struct GNUNET_MessageHeader header;
+
+    /**
+     * ID of the connection.
+     */
+  struct GNUNET_CADET_Hash cid;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef CADET_PROTOCOL_H */
+#endif
+/* end of cadet_protocol.h */

Copied: gnunet/src/cadet/cadet_test_lib.c (from rev 33185, 
gnunet/src/mesh/cadet_test_lib.c)
===================================================================
--- gnunet/src/cadet/cadet_test_lib.c                           (rev 0)
+++ gnunet/src/cadet/cadet_test_lib.c   2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,295 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file cadet/cadet_test_lib.c
+ * @author Bartlomiej Polot
+ * @brief library for writing CADET tests
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "cadet_test_lib.h"
+#include "gnunet_cadet_service.h"
+
+/**
+ * Test context for a CADET Test.
+ */
+struct GNUNET_CADET_TEST_Context
+{
+  /**
+   * Array of running peers.
+   */
+  struct GNUNET_TESTBED_Peer **peers;
+
+  /**
+   * Array of handles to the CADET for each peer.
+   */
+  struct GNUNET_CADET_Handle **cadetes;
+
+  /**
+   * Operation associated with the connection to the CADET.
+   */
+  struct GNUNET_TESTBED_Operation **ops;
+
+  /**
+   * Main function of the test to run once all CADETs are available.
+   */
+  GNUNET_CADET_TEST_AppMain app_main;
+
+  /**
+   * Closure for 'app_main'.
+   */
+  void *app_main_cls;
+
+  /**
+   * Number of peers running, size of the arrays above.
+   */
+  unsigned int num_peers;
+
+  /**
+   * Handler for incoming tunnels.
+   */
+  GNUNET_CADET_InboundChannelNotificationHandler *new_channel;
+
+  /**
+   * Cleaner for destroyed incoming tunnels.
+   */
+  GNUNET_CADET_ChannelEndHandler *cleaner;
+
+  /**
+   * Message handlers.
+   */
+  struct GNUNET_CADET_MessageHandler* handlers;
+
+  /**
+   * Application ports.
+   */
+  const uint32_t *ports;
+
+};
+
+
+/**
+ * Context for a cadet adapter callback.
+ */
+struct GNUNET_CADET_TEST_AdapterContext
+{
+  /**
+   * Peer number for the particular peer.
+   */
+  unsigned int peer;
+
+  /**
+   * General context.
+   */
+  struct GNUNET_CADET_TEST_Context *ctx;
+};
+
+
+/**
+ * Adapter function called to establish a connection to
+ * the CADET service.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer to connect to; will be available until
+ *          GNUNET_TESTBED_operation_done() is called on the operation returned
+ *          from GNUNET_TESTBED_service_connect()
+ * @return service handle to return in 'op_result', NULL on error
+ */
+static void *
+cadet_connect_adapter (void *cls,
+                      const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
+  struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
+  struct GNUNET_CADET_Handle *h;
+
+  h = GNUNET_CADET_connect (cfg,
+                           (void *) (long) actx->peer,
+                           ctx->new_channel,
+                           ctx->cleaner,
+                           ctx->handlers,
+                           ctx->ports);
+  return h;
+}
+
+
+/**
+ * Adapter function called to destroy a connection to
+ * the CADET service.
+ *
+ * @param cls closure
+ * @param op_result service handle returned from the connect adapter
+ */
+static void
+cadet_disconnect_adapter (void *cls,
+                         void *op_result)
+{
+  struct GNUNET_CADET_Handle *cadet = op_result;
+  struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
+
+  GNUNET_free (actx);
+  GNUNET_CADET_disconnect (cadet);
+}
+
+
+/**
+ * Callback to be called when a service connect operation is completed.
+ *
+ * @param cls The callback closure from functions generating an operation.
+ * @param op The operation that has been finished.
+ * @param ca_result The service handle returned from
+ *                  GNUNET_TESTBED_ConnectAdapter() (cadet handle).
+ * @param emsg Error message in case the operation has failed.
+ *             NULL if operation has executed successfully.
+ */
+static void
+cadet_connect_cb (void *cls,
+                 struct GNUNET_TESTBED_Operation *op,
+                 void *ca_result,
+                 const char *emsg)
+{
+  struct GNUNET_CADET_TEST_Context *ctx = cls;
+  unsigned int i;
+
+  if (NULL != emsg)
+  {
+    fprintf (stderr, "Failed to connect to CADET service: %s\n",
+             emsg);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  for (i = 0; i < ctx->num_peers; i++)
+    if (op == ctx->ops[i])
+    {
+      ctx->cadetes[i] = ca_result;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i);
+    }
+  for (i = 0; i < ctx->num_peers; i++)
+    if (NULL == ctx->cadetes[i])
+      return; /* still some CADET connections missing */
+  /* all CADET connections ready! */
+  ctx->app_main (ctx->app_main_cls,
+                 ctx,
+                 ctx->num_peers,
+                 ctx->peers,
+                 ctx->cadetes);
+}
+
+
+void
+GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
+{
+  unsigned int i;
+
+  for (i = 0; i < ctx->num_peers; i++)
+  {
+    GNUNET_assert (NULL != ctx->ops[i]);
+    GNUNET_TESTBED_operation_done (ctx->ops[i]);
+    ctx->ops[i] = NULL;
+  }
+  GNUNET_free (ctx->ops);
+  GNUNET_free (ctx->cadetes);
+  GNUNET_free (ctx);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Callback run when the testbed is ready (peers running and connected to
+ * each other)
+ *
+ * @param cls Closure (context).
+ * @param h the run handle
+ * @param num_peers Number of peers that are running.
+ * @param peers Handles to each one of the @c num_peers peers.
+ * @param links_succeeded the number of overlay link connection attempts that
+ *          succeeded
+ * @param links_failed the number of overlay link connection attempts that
+ *          failed
+ */
+static void
+cadet_test_run (void *cls,
+               struct GNUNET_TESTBED_RunHandle *h,
+               unsigned int num_peers,
+               struct GNUNET_TESTBED_Peer **peers,
+               unsigned int links_succeeded,
+               unsigned int links_failed)
+{
+  struct GNUNET_CADET_TEST_Context *ctx = cls;
+  unsigned int i;
+
+  if  (num_peers != ctx->num_peers)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n",
+                num_peers, ctx->num_peers);
+    exit (1);
+  }
+  ctx->peers = peers;
+  for (i = 0; i < num_peers; i++)
+  {
+    struct GNUNET_CADET_TEST_AdapterContext *newctx;
+    newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
+    newctx->peer = i;
+    newctx->ctx = ctx;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i);
+    ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
+                                                  peers[i],
+                                                  "cadet",
+                                                  &cadet_connect_cb,
+                                                  ctx,
+                                                  &cadet_connect_adapter,
+                                                  &cadet_disconnect_adapter,
+                                                  newctx);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]);
+  }
+}
+
+
+void
+GNUNET_CADET_TEST_run (const char *testname,
+                      const char *cfgname,
+                      unsigned int num_peers,
+                      GNUNET_CADET_TEST_AppMain tmain,
+                      void *tmain_cls,
+                      GNUNET_CADET_InboundChannelNotificationHandler 
new_channel,
+                      GNUNET_CADET_ChannelEndHandler cleaner,
+                      struct GNUNET_CADET_MessageHandler* handlers,
+                      const uint32_t *ports)
+{
+  struct GNUNET_CADET_TEST_Context *ctx;
+
+  ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
+  ctx->num_peers = num_peers;
+  ctx->ops = GNUNET_malloc (num_peers * sizeof (struct 
GNUNET_TESTBED_Operation *));
+  ctx->cadetes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_CADET_Handle 
*));
+  ctx->app_main = tmain;
+  ctx->app_main_cls = tmain_cls;
+  ctx->new_channel = new_channel;
+  ctx->cleaner = cleaner;
+  ctx->handlers = handlers;
+  ctx->ports = ports;
+  GNUNET_TESTBED_test_run (testname,
+                           cfgname,
+                           num_peers,
+                           0LL, NULL, NULL,
+                           &cadet_test_run, ctx);
+}
+
+/* end of cadet_test_lib.c */

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

Copied: gnunet/src/cadet/cadet_tunnel_tree.c (from rev 33185, 
gnunet/src/mesh/cadet_tunnel_tree.c)
===================================================================
--- gnunet/src/cadet/cadet_tunnel_tree.c                                (rev 0)
+++ gnunet/src/cadet/cadet_tunnel_tree.c        2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,1174 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/cadet_tunnel_tree.c
+ * @brief Tunnel tree handling functions
+ * @author Bartlomiej Polot
+ */
+
+#include "cadet.h"
+#include "cadet_tunnel_tree.h"
+
+#define CADET_TREE_DEBUG GNUNET_YES
+
+
+/**
+ * Node of path tree for a tunnel
+ */
+struct CadetTunnelTreeNode
+{
+  /**
+   * Peer this node describes
+   */
+  GNUNET_PEER_Id peer;
+
+  /**
+   * Parent node in the tree
+   */
+  struct CadetTunnelTreeNode *parent;
+
+  /**
+   * DLL of siblings
+   */
+  struct CadetTunnelTreeNode *next;
+
+  /**
+   * DLL of siblings
+   */
+  struct CadetTunnelTreeNode *prev;
+
+  /**
+   * DLL of children
+   */
+  struct CadetTunnelTreeNode *children_head;
+
+  /**
+   * DLL of children
+   */
+  struct CadetTunnelTreeNode *children_tail;
+
+    /**
+     * Status of the peer in the tunnel
+     */
+  enum CadetPeerState status;
+};
+
+
+/**
+ * Tree to reach all peers in the tunnel
+ */
+struct CadetTunnelTree
+{
+  /**
+   * Root node of peer tree
+   */
+  struct CadetTunnelTreeNode *root;
+
+  /**
+   * Node that represents our position in the tree (for non local tunnels)
+   */
+  struct CadetTunnelTreeNode *me;
+
+  /**
+   * DLL of disconneted nodes
+   */
+  struct CadetTunnelTreeNode *disconnected_head;
+
+  /**
+   * DLL of disconneted nodes
+   */
+  struct CadetTunnelTreeNode *disconnected_tail;
+
+  /**
+   * Cache of all peers and the first hop to them.
+   * Indexed by PeerIdentity, contains a pointer to the PeerIdentity
+   * of 1st hop.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *first_hops;
+
+};
+
+
+/**
+ * Create a new path
+ *
+ * @param length How many hops will the path have.
+ *
+ * @return A newly allocated path with a peer array of the specified length.
+ */
+struct CadetPeerPath *
+path_new (unsigned int length)
+{
+  struct CadetPeerPath *p;
+
+  p = GNUNET_new (struct CadetPeerPath);
+  if (length > 0)
+  {
+    p->length = length;
+    p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id));
+  }
+  return p;
+}
+
+
+/**
+ * Invert the path
+ *
+ * @param path the path to invert
+ */
+void
+path_invert (struct CadetPeerPath *path)
+{
+  GNUNET_PEER_Id aux;
+  unsigned int i;
+
+  for (i = 0; i < path->length / 2; i++)
+  {
+    aux = path->peers[i];
+    path->peers[i] = path->peers[path->length - i - 1];
+    path->peers[path->length - i - 1] = aux;
+  }
+}
+
+
+/**
+ * Duplicate a path, incrementing short peer's rc.
+ *
+ * @param path The path to duplicate.
+ */
+struct CadetPeerPath *
+path_duplicate (struct CadetPeerPath *path)
+{
+  struct CadetPeerPath *aux;
+  unsigned int i;
+
+  aux = path_new (path->length);
+  memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id));
+  for (i = 0; i < path->length; i++)
+    GNUNET_PEER_change_rc (path->peers[i], 1);
+  return aux;
+}
+
+
+/**
+ * Recusively update the info about what is the first hop to reach the node
+ *
+ * @param tree Tree this nodes belongs to.
+ * @param parent The node form which to start updating.
+ * @param hop If known, ID of the first hop.
+ *            If not known, NULL to find out and pass on children.
+ */
+static void
+tree_node_update_first_hops (struct CadetTunnelTree *tree,
+                             struct CadetTunnelTreeNode *parent,
+                             struct GNUNET_PeerIdentity *hop);
+
+
+/**
+ * Get the length of a path.
+ *
+ * @param path The path to measure, with the local peer at any point of it.
+ *
+ * @return Number of hops to reach destination.
+ *         UINT_MAX in case the peer is not in the path.
+ */
+unsigned int
+path_get_length (struct CadetPeerPath *path)
+{
+  if (NULL == path)
+    return UINT_MAX;
+  return path->length;
+}
+
+
+/**
+ * Destroy the path and free any allocated resources linked to it
+ *
+ * @param p the path to destroy
+ *
+ * @return GNUNET_OK on success
+ */
+int
+path_destroy (struct CadetPeerPath *p)
+{
+  if (NULL == p)
+    return GNUNET_OK;
+  GNUNET_PEER_decrement_rcs (p->peers, p->length);
+  GNUNET_free_non_null (p->peers);
+  GNUNET_free (p);
+  return GNUNET_OK;
+}
+
+
+
+/**
+ * Allocates and initializes a new node.
+ * Sets ID and parent of the new node and inserts it in the DLL of the parent
+ *
+ * @param parent Node that will be the parent from the new node, NULL for root
+ * @param peer Short Id of the new node
+ *
+ * @return Newly allocated node
+ */
+static struct CadetTunnelTreeNode *
+tree_node_new (struct CadetTunnelTreeNode *parent, GNUNET_PEER_Id peer)
+{
+  struct CadetTunnelTreeNode *node;
+
+  node = GNUNET_new (struct CadetTunnelTreeNode);
+  node->peer = peer;
+  GNUNET_PEER_change_rc (peer, 1);
+  node->parent = parent;
+  if (NULL != parent)
+    GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail,
+                                 node);
+
+  return node;
+}
+
+
+/**
+ * Recursively find the given peer.
+ *
+ * @param parent Node where to start looking.
+ * @param peer_id Short ID of the peer to find.
+ *
+ * @return Pointer to the node of the peer. NULL if not found.
+ */
+static struct CadetTunnelTreeNode *
+tree_node_find_peer (struct CadetTunnelTreeNode *parent, GNUNET_PEER_Id 
peer_id)
+{
+  struct CadetTunnelTreeNode *n;
+  struct CadetTunnelTreeNode *r;
+
+  if (parent->peer == peer_id)
+    return parent;
+  for (n = parent->children_head; NULL != n; n = n->next)
+  {
+    r = tree_node_find_peer (n, peer_id);
+    if (NULL != r)
+      return r;
+  }
+  return NULL;
+}
+
+
+/**
+ * Recusively update the info about what is the first hop to reach the node
+ *
+ * @param tree Tree this nodes belongs to.
+ * @param parent ID from node form which to start updating.
+ * @param hop If known, ID of the first hop.
+ *            If not known, NULL to find out and pass on children.
+ */
+static void
+tree_node_update_first_hops (struct CadetTunnelTree *tree,
+                             struct CadetTunnelTreeNode *parent,
+                             struct GNUNET_PeerIdentity *hop)
+{
+  struct GNUNET_PeerIdentity pi;
+  struct GNUNET_PeerIdentity *copy;
+  struct GNUNET_PeerIdentity id;
+  struct CadetTunnelTreeNode *n;
+
+#if CADET_TREE_DEBUG
+  GNUNET_PEER_resolve (parent->peer, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Finding first hop for %s.\n",
+              GNUNET_i2s (&id));
+#endif
+  if (NULL == hop)
+  {
+    struct CadetTunnelTreeNode *aux;
+    struct CadetTunnelTreeNode *old;
+
+    aux = old = parent;
+    while (aux != tree->me)
+    {
+#if CADET_TREE_DEBUG
+      GNUNET_PEER_resolve (aux->peer, &id);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   ... checking %s.\n",
+                  GNUNET_i2s (&id));
+#endif
+      old = aux;
+      aux = aux->parent;
+      GNUNET_assert (NULL != aux);
+    }
+#if CADET_TREE_DEBUG
+    GNUNET_PEER_resolve (old->peer, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   It's %s!\n",
+                GNUNET_i2s (&id));
+#endif
+    hop = &pi;
+    GNUNET_PEER_resolve (old->peer, hop);
+  }
+  GNUNET_PEER_resolve (parent->peer, &id);
+  copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
+  if (NULL == copy)
+    copy = GNUNET_new (struct GNUNET_PeerIdentity);
+  *copy = *hop;
+
+  (void) GNUNET_CONTAINER_multihashmap_put (tree->first_hops, &id.hashPubKey,
+                                            copy,
+                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+
+  for (n = parent->children_head; NULL != n; n = n->next)
+  {
+    tree_node_update_first_hops (tree, n, hop);
+  }
+}
+
+
+static void
+tree_node_debug (struct CadetTunnelTreeNode *n, uint16_t level)
+{
+  struct CadetTunnelTreeNode *c;
+  struct GNUNET_PeerIdentity id;;
+  uint16_t i;
+
+  for (i = 0; i < level; i++)
+    FPRINTF (stderr, "%s",  "  ");
+  if (n->status == CADET_PEER_READY)
+    FPRINTF (stderr, "%s",  "#");
+  if (n->status == CADET_PEER_SEARCHING)
+    FPRINTF (stderr, "%s",  "+");
+  if (n->status == CADET_PEER_RELAY)
+    FPRINTF (stderr, "%s",  "-");
+  if (n->status == CADET_PEER_RECONNECTING)
+    FPRINTF (stderr, "%s",  "*");
+
+  GNUNET_PEER_resolve (n->peer, &id);
+  FPRINTF (stderr, "%s, [%u, %p] ", GNUNET_i2s (&id), n->peer, n);
+  if (NULL != n->parent)
+  {
+    GNUNET_PEER_resolve (n->parent->peer, &id);
+    FPRINTF (stderr, "(-> %s [%u])\n", GNUNET_i2s (&id), n->parent->peer);
+  }
+  else
+    FPRINTF (stderr, "%s",  "(root)\n");
+  for (c = n->children_head; NULL != c; c = c->next)
+    tree_node_debug (c, level + 1);
+}
+
+
+/**
+ * Destroys and frees the node and all children
+ *
+ * @param parent Parent node to be destroyed
+ */
+static void
+tree_node_destroy (struct CadetTunnelTreeNode *parent)
+{
+  struct CadetTunnelTreeNode *n;
+  struct CadetTunnelTreeNode *next;
+
+  if (NULL == parent)
+    return;
+#if CADET_TREE_DEBUG
+  struct GNUNET_PeerIdentity id;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying node %u\n",
+              parent->peer);
+  GNUNET_PEER_resolve (parent->peer, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   (%s)\n", GNUNET_i2s (&id));
+#endif
+  n = parent->children_head;
+  while (NULL != n)
+  {
+    next = n->next;
+    tree_node_destroy (n);
+    n = next;
+  }
+  GNUNET_PEER_change_rc (parent->peer, -1);
+  if (NULL != parent->parent)
+    GNUNET_CONTAINER_DLL_remove (parent->parent->children_head,
+                                 parent->parent->children_tail, parent);
+  GNUNET_free (parent);
+}
+
+
+
+/**
+ * Create a new tree.
+ *
+ * @param peer A short peer id of the root of the tree.
+ *
+ * @return A newly allocated and initialized tunnel tree.
+ */
+struct CadetTunnelTree *
+tree_new (GNUNET_PEER_Id peer)
+{
+  struct CadetTunnelTree *tree;
+
+  tree = GNUNET_new (struct CadetTunnelTree);
+  tree->first_hops = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
+  tree->root = tree_node_new (NULL, peer);
+  tree->root->status = CADET_PEER_ROOT;
+
+  if (1 == peer)
+  {
+    tree->me = tree->root;
+  }
+
+  return tree;
+}
+
+
+/**
+ * Set the status of a node.
+ *
+ * @param tree Tree.
+ * @param peer A short peer id of the node.
+ * @param status New status to set.
+ */
+void
+tree_set_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer,
+                 enum CadetPeerState status)
+{
+  struct CadetTunnelTreeNode *n;
+
+  n = tree_find_peer (tree, peer);
+  if (NULL == n)
+    return;
+  n->status = status;
+}
+
+
+/**
+ * Get the status of a node.
+ *
+ * @param tree Tree whose node's status we want to now.
+ * @param peer A short peer id of the node.
+ *
+ * @return Status of the peer.
+ */
+enum CadetPeerState
+tree_get_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer)
+{
+  struct CadetTunnelTreeNode *n;
+
+  n = tree_find_peer (tree, peer);
+  if (NULL == n)
+    return CADET_PEER_INVALID;
+  return n->status;
+}
+
+
+/**
+ * Get the id of the predecessor of the local node.
+ *
+ * @param tree Tree whose local id we want to now.
+ *
+ * @return Short peer id of local peer.
+ */
+GNUNET_PEER_Id
+tree_get_predecessor (struct CadetTunnelTree *tree)
+{
+  if (NULL != tree->me && NULL != tree->me->parent)
+    return tree->me->parent->peer;
+  else
+    return (GNUNET_PEER_Id) 0;
+}
+
+
+/**
+ * Find the first peer whom to send a packet to go down this path
+ *
+ * @param t The tunnel tree to use
+ * @param peer The peerinfo of the peer we are trying to reach
+ *
+ * @return peerinfo of the peer who is the first hop in the tunnel
+ *         NULL on error
+ *
+ * FIXME use PEER_Id
+ */
+struct GNUNET_PeerIdentity *
+tree_get_first_hop (struct CadetTunnelTree *t, GNUNET_PEER_Id peer)
+{
+  struct GNUNET_PeerIdentity id;
+  struct GNUNET_PeerIdentity *r;
+
+  GNUNET_PEER_resolve (peer, &id);
+  r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
+  if (NULL == r)
+  {
+    struct CadetTunnelTreeNode *n;
+
+    n = tree_find_peer (t, peer);
+    if (NULL != t->me && NULL != n)
+    {
+      tree_node_update_first_hops (t, n, NULL);
+      r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
+      GNUNET_assert (NULL != r);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Tree structure inconsistent! me: %p, n: %p", t->me, n);
+      GNUNET_break (0);
+    }
+  }
+
+  return r;
+}
+
+
+/**
+ * Find the given peer in the tree.
+ *
+ * @param tree Tree where to look for the peer.
+ * @param peer_id Short ID of the peer to find.
+ *
+ * @return Pointer to the node of the peer. NULL if not found.
+ */
+struct CadetTunnelTreeNode *
+tree_find_peer (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer_id)
+{
+  return tree_node_find_peer (tree->root, peer_id);
+}
+
+
+/**
+ * Recusively mark peer and children as disconnected, notify client
+ *
+ * @param tree Tree this node belongs to
+ * @param parent Node to be clean, potentially with children
+ * @param cb Callback to use to notify about disconnected peers.
+ * @param cbcls Closure for cb.
+ */
+static void
+tree_mark_peers_disconnected (struct CadetTunnelTree *tree,
+                              struct CadetTunnelTreeNode *parent,
+                              CadetTreeCallback cb, void *cbcls)
+{
+  struct GNUNET_PeerIdentity *pi;
+  struct GNUNET_PeerIdentity id;
+  struct CadetTunnelTreeNode *n;
+
+  for (n = parent->children_head; NULL != n; n = n->next)
+  {
+    tree_mark_peers_disconnected (tree, n, cb, cbcls);
+  }
+  if (CADET_PEER_READY == parent->status)
+  {
+    if (NULL != cb)
+      cb (cbcls, parent->peer);
+    parent->status = CADET_PEER_RECONNECTING;
+  }
+
+  /* Remove and free info about first hop */
+  GNUNET_PEER_resolve (parent->peer, &id);
+  pi = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
+  GNUNET_CONTAINER_multihashmap_remove_all (tree->first_hops, &id.hashPubKey);
+  if (NULL != pi)
+    GNUNET_free (pi);
+}
+
+
+/**
+ * Iterate over all children of the local node.
+ *
+ * @param tree Tree to use. Must have "me" set.
+ * @param cb Callback to call over each child.
+ * @param cb_cls Closure for @c cb.
+ */
+void
+tree_iterate_children (struct CadetTunnelTree *tree, CadetTreeCallback cb,
+                       void *cb_cls)
+{
+  struct CadetTunnelTreeNode *n;
+
+  if (NULL == tree->me)
+    return;
+  for (n = tree->me->children_head; NULL != n; n = n->next)
+  {
+    cb (cb_cls, n->peer);
+  }
+}
+
+
+/**
+ * Struct to contain a list of pending nodes when iterating a tree.
+ */
+struct CadetTreePendingNode {
+
+  /**
+   * DLL next.
+   */
+  struct CadetTreePendingNode *next;
+
+  /**
+   * DLL prev.
+   */
+  struct CadetTreePendingNode *prev;
+
+  /**
+   * Pending node.
+   */
+  struct CadetTunnelTreeNode *node;
+};
+
+
+/**
+ * Iterate over all nodes in the tree.
+ *
+ * @param tree Tree to use..
+ * @param cb Callback to call over each child.
+ * @param cb_cls Closure for @c cb.
+ *
+ * TODO: recursive implementation? (s/heap/stack/g)
+ */
+void
+tree_iterate_all (struct CadetTunnelTree *tree,
+                  CadetWholeTreeCallback cb,
+                  void *cb_cls)
+{
+  struct CadetTunnelTreeNode *parent;
+  struct CadetTunnelTreeNode *n;
+  struct CadetTreePendingNode *head;
+  struct CadetTreePendingNode *tail;
+  struct CadetTreePendingNode *pending;
+
+  cb (cb_cls, tree->root->peer, 0);
+  pending = GNUNET_new (struct CadetTreePendingNode);
+  pending->node = tree->root;
+  head = tail = NULL;
+  GNUNET_CONTAINER_DLL_insert (head, tail, pending);
+
+  while (NULL != head)
+  {
+    pending = head;
+    parent = pending->node;
+    GNUNET_CONTAINER_DLL_remove (head, tail, pending);
+    GNUNET_free (pending);
+    for (n = parent->children_head; NULL != n; n = n->next)
+    {
+      cb (cb_cls, n->peer, parent->peer);
+      pending = GNUNET_new (struct CadetTreePendingNode);
+      pending->node = n;
+      /* Insert_tail: breadth first, Insert: depth first */
+      GNUNET_CONTAINER_DLL_insert (head, tail, pending);
+    }
+  }
+}
+
+
+/**
+ * Iterator to count the children in a tree.
+ */
+static void
+count_children_cb (void *cls, GNUNET_PEER_Id peer)
+{
+  unsigned int *i = cls;
+
+  (*i)++;
+}
+
+
+/**
+ * Count how many children does the local node have in the tree.
+ *
+ * @param tree Tree to use. Must have "me" set.
+ */
+unsigned int
+tree_count_children (struct CadetTunnelTree *tree)
+{
+  unsigned int i;
+
+  i = 0;
+  tree_iterate_children(tree, &count_children_cb, &i);
+  return i;
+}
+
+
+/**
+ * Recusively update the info about what is the first hop to reach the node
+ *
+ * @param tree Tree this nodes belongs to.
+ * @param parent_id Short ID from node form which to start updating.
+ * @param hop If known, ID of the first hop.
+ *            If not known, NULL to find out and pass on children.
+ */
+void
+tree_update_first_hops (struct CadetTunnelTree *tree, GNUNET_PEER_Id parent_id,
+                        struct GNUNET_PeerIdentity *hop)
+{
+  tree_node_update_first_hops (tree, tree_find_peer (tree, parent_id), hop);
+}
+
+
+/**
+ * Delete the current path to the peer, including all now unused relays.
+ * The destination peer is NOT destroyed, it is returned in order to either set
+ * a new path to it or destroy it explicitly, taking care of it's child nodes.
+ *
+ * @param t Tunnel tree where to delete the path from.
+ * @param peer_id Short ID of the destination peer whose path we want to 
remove.
+ * @param cb Callback to use to notify about disconnected peers.
+ * @param cbcls Closure for cb.
+ *
+ * @return pointer to the pathless node.
+ *         NULL when not found
+ */
+struct CadetTunnelTreeNode *
+tree_del_path (struct CadetTunnelTree *t, GNUNET_PEER_Id peer_id,
+               CadetTreeCallback cb, void *cbcls)
+{
+  struct CadetTunnelTreeNode *parent;
+  struct CadetTunnelTreeNode *node;
+  struct CadetTunnelTreeNode *n;
+
+#if CADET_TREE_DEBUG
+  struct GNUNET_PeerIdentity id;
+
+  GNUNET_PEER_resolve (peer_id, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Deleting path to %s.\n",
+              GNUNET_i2s (&id));
+#endif
+  if (NULL == t->root || peer_id == t->root->peer)
+    return NULL;
+
+  for (n = t->disconnected_head; NULL != n; n = n->next)
+  {
+    if (n->peer == peer_id)
+    {
+      /* Was already pathless, waiting for reconnection */
+      GNUNET_CONTAINER_DLL_remove (t->disconnected_head, t->disconnected_tail,
+                                   n);
+      return n;
+    }
+  }
+  n = tree_find_peer (t, peer_id);
+  if (NULL == n)
+    return NULL;
+  node = n;
+
+  parent = n->parent;
+  GNUNET_CONTAINER_DLL_remove (parent->children_head, parent->children_tail, 
n);
+  n->parent = NULL;
+
+  while (CADET_PEER_RELAY == parent->status &&
+         NULL == parent->children_head)
+  {
+#if CADET_TREE_DEBUG
+    GNUNET_PEER_resolve (parent->peer, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Deleting node %s.\n",
+                GNUNET_i2s (&id));
+#endif
+    n = parent->parent;
+    if (parent == t->me)
+      t->me = NULL;
+    tree_node_destroy (parent);
+    parent = n;
+  }
+#if CADET_TREE_DEBUG
+  GNUNET_PEER_resolve (parent->peer, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Not deleted peer %s.\n",
+              GNUNET_i2s (&id));
+#endif
+
+  tree_mark_peers_disconnected (t, node, cb, cbcls);
+
+  return node;
+}
+
+
+/**
+ * Return a newly allocated individual path to reach a peer from the local 
peer,
+ * according to the path tree of some tunnel.
+ *
+ * @param t Tunnel from which to read the path tree.
+ * @param peer Short ID of the destination peer to whom we want a path.
+ *
+ * @return A newly allocated individual path to reach the destination peer.
+ *         Path must be destroyed afterwards.
+ */
+struct CadetPeerPath *
+tree_get_path_to_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer)
+{
+  struct CadetTunnelTreeNode *n;
+  struct CadetPeerPath *p;
+
+  n = tree_find_peer (t, peer);
+  if (NULL == n)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  p = path_new (0);
+
+  /* Building the path (inverted!) */
+  while (n->peer != 1)
+  {
+    GNUNET_array_append (p->peers, p->length, n->peer);
+    GNUNET_PEER_change_rc (n->peer, 1);
+    n = n->parent;
+    if (NULL == n)
+    {
+      GNUNET_break (0);
+      path_destroy (p);
+      return NULL;
+    }
+  }
+  GNUNET_array_append (p->peers, p->length, 1);
+  GNUNET_PEER_change_rc (1, 1);
+
+  path_invert (p);
+
+  return p;
+}
+
+
+
+/**
+ * Integrate a stand alone path into the tunnel tree.
+ * If the peer toward which the new path is already in the tree, the peer
+ * and its children will be maked as disconnected and the callback
+ * will be called on each one of them. They will be maked as online only after
+ * receiving a PATH ACK for the new path for each one of them, so the caller
+ * should take care of sending a new CREATE PATH message for each disconnected
+ * peer.
+ *
+ * @param t Tunnel where to add the new path.
+ * @param p Path to be integrated.
+ * @param cb Callback to use to notify about peers temporarily disconnecting.
+ * @param cbcls Closure for cb.
+ *
+ * @return GNUNET_OK in case of success.
+ *         GNUNET_SYSERR in case of error.
+ *
+ * TODO: optimize
+ * - go backwards on path looking for each peer in the present tree
+ * - do not disconnect peers until new path is created & connected
+ */
+int
+tree_add_path (struct CadetTunnelTree *t, const struct CadetPeerPath *p,
+               CadetTreeCallback cb, void *cbcls)
+{
+  struct CadetTunnelTreeNode *parent;
+  struct CadetTunnelTreeNode *oldnode;
+  struct CadetTunnelTreeNode *n;
+  struct CadetTunnelTreeNode *c;
+  struct GNUNET_PeerIdentity id;
+  int me;
+  unsigned int i;
+
+#if CADET_TREE_DEBUG
+  GNUNET_PEER_resolve (p->peers[p->length - 1], &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "tree:   Adding path [%u] towards peer %s.\n", p->length,
+              GNUNET_i2s (&id));
+#endif
+
+  GNUNET_assert (0 != p->length);
+  parent = n = t->root;
+  if (n->peer != p->peers[0])
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (1 == p->length)
+    return GNUNET_OK;
+  oldnode = tree_del_path (t, p->peers[p->length - 1], cb, cbcls);
+  /* Look for the first node that is not already present in the tree
+   *
+   * Assuming that the tree is somewhat balanced, O(log n * log N).
+   * - Length of the path is expected to be log N (size of whole network).
+   * - Each level of the tree is expected to have log n children (size of 
tree).
+   */
+  me = t->root->peer == 1 ? 0 : -1;
+  for (i = 1; i < p->length; i++)
+  {
+#if CADET_TREE_DEBUG
+    GNUNET_PEER_resolve (p->peers[i], &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Looking for peer %s.\n",
+                GNUNET_i2s (&id));
+#endif
+    parent = n;
+    if (p->peers[i] == 1)
+      me = i;
+    for (c = n->children_head; NULL != c; c = c->next)
+    {
+      if (c->peer == p->peers[i])
+      {
+#if CADET_TREE_DEBUG
+        GNUNET_PEER_resolve (parent->peer, &id);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "tree:   Found in children of %s.\n", GNUNET_i2s (&id));
+#endif
+        n = c;
+        break;
+      }
+    }
+    /*  If we couldn't find a child equal to path[i], we have reached the end
+     * of the common path. */
+    if (parent == n)
+      break;
+  }
+#if CADET_TREE_DEBUG
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   All childen visited.\n");
+#endif
+  /* Add the rest of the path as a branch from parent. */
+  while (i < p->length)
+  {
+#if CADET_TREE_DEBUG
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Adding peer %u to %u.\n",
+                p->peers[i], parent->peer);
+    GNUNET_PEER_resolve (p->peers[i], &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Adding peer %s.\n",
+                GNUNET_i2s (&id));
+    GNUNET_PEER_resolve (parent->peer, &id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:            to %s.\n",
+                GNUNET_i2s (&id));
+#endif
+
+    if (i == p->length - 1 && NULL != oldnode)
+    {
+#if CADET_TREE_DEBUG
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "tree:   Putting old node into place.\n");
+#endif
+      oldnode->parent = parent;
+      GNUNET_CONTAINER_DLL_insert (parent->children_head, 
parent->children_tail,
+                                   oldnode);
+      tree_node_update_first_hops (t, oldnode, NULL);
+      n = oldnode;
+    }
+    else
+    {
+#if CADET_TREE_DEBUG
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Creating new node.\n");
+#endif
+      n = tree_node_new (parent, p->peers[i]);
+      n->status = CADET_PEER_RELAY;
+    }
+    if (n->peer == 1)
+    {
+      t->me = n;
+      me = i;
+    }
+    i++;
+    parent = n;
+  }
+  n->status = CADET_PEER_SEARCHING;
+
+  GNUNET_break (-1 != me);
+
+  /* Add info about first hop into hashmap. */
+  if (-1 != me && me < p->length - 1)
+  {
+#if CADET_TREE_DEBUG
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "CADET:   finding first hop (own pos %d/%u)\n", me,
+                p->length - 1);
+#endif
+    GNUNET_PEER_resolve (p->peers[me + 1], &id);
+    tree_update_first_hops (t, p->peers[me + 1], &id);
+  }
+#if CADET_TREE_DEBUG
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "CADET:   was last in path, not updating first hops (%d/%u)\n",
+                me, p->length - 1);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   New node added.\n");
+#endif
+  if (NULL == t->me)
+    t->me = tree_find_peer (t, 1);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Notifies a tree that a connection it might be using is broken.
+ * Marks all peers down the paths as disconnected and notifies the client.
+ *
+ * @param t Tree to use.
+ * @param p1 Short id of one of the peers (order unimportant)
+ * @param p2 Short id of one of the peers (order unimportant)
+ * @param cb Function to call for every peer that is marked as disconnected.
+ * @param cbcls Closure for cb.
+ *
+ * @return Short ID of the first disconnected peer in the tree.
+ */
+GNUNET_PEER_Id
+tree_notify_connection_broken (struct CadetTunnelTree *t, GNUNET_PEER_Id p1,
+                               GNUNET_PEER_Id p2, CadetTreeCallback cb,
+                               void *cbcls)
+{
+  struct CadetTunnelTreeNode *n;
+  struct CadetTunnelTreeNode *c;
+
+  n = tree_find_peer (t, p1);
+  if (NULL == n)
+    return 0;
+  if (NULL != n->parent && n->parent->peer == p2)
+  {
+    tree_mark_peers_disconnected (t, n, cb, cbcls);
+    GNUNET_CONTAINER_DLL_remove (n->parent->children_head,
+                                 n->parent->children_tail, n);
+    GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, 
n);
+    return p1;
+  }
+  for (c = n->children_head; NULL != c; c = c->next)
+  {
+    if (c->peer == p2)
+    {
+      tree_mark_peers_disconnected (t, c, cb, cbcls);
+      GNUNET_CONTAINER_DLL_remove (n->children_head, n->children_tail, c);
+      GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail,
+                                   c);
+      return p2;
+    }
+  }
+  return 0;
+}
+
+
+/**
+ * Deletes a peer from a tunnel, liberating all unused resources on the path to
+ * it. It shouldn't have children, if it has they will be destroyed as well.
+ * If the tree is not local and no longer has any paths, the root node will be
+ * destroyed and marked as NULL.
+ *
+ * @param t Tunnel tree to use.
+ * @param peer Short ID of the peer to remove from the tunnel tree.
+ * @param cb Callback to notify client of disconnected peers.
+ * @param cbcls Closure for cb.
+ *
+ * @return GNUNET_OK or GNUNET_SYSERR
+ */
+int
+tree_del_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer,
+               CadetTreeCallback cb, void *cbcls)
+{
+  struct CadetTunnelTreeNode *n;
+
+  n = tree_del_path (t, peer, cb, cbcls);
+  if (NULL == n)
+  {
+    GNUNET_break (0);
+    return GNUNET_YES;
+  }
+  tree_node_destroy (n);
+  if (NULL == t->root->children_head && t->me != t->root)
+  {
+    tree_node_destroy (t->root);
+    t->root = NULL;
+    return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+
+
+
+/**
+ * Get the cost of the path relative to the already built tunnel tree.
+ *
+ * @param t The tunnel tree to which compare.
+ * @param path The individual path to reach a peer. It has to start at the
+ *             root of the tree to be comparable.
+ *
+ * @return Number of hops to reach destination, UINT_MAX in case the peer is 
not
+ *         in the path.
+ *
+ * TODO: adapt to allow any start / root combination
+ * TODO: take in account state of the nodes
+ */
+unsigned int
+tree_get_path_cost (struct CadetTunnelTree *t, struct CadetPeerPath *path)
+{
+  struct CadetTunnelTreeNode *n;
+  struct CadetTunnelTreeNode *p;
+  unsigned int i;
+  unsigned int l;
+
+  l = path_get_length (path);
+  p = t->root;
+  if (t->root->peer != path->peers[0])
+  {
+    GNUNET_break (0);
+    return UINT_MAX;
+  }
+  for (i = 1; i < l; i++)
+  {
+    for (n = p->children_head; NULL != n; n = n->next)
+    {
+      if (path->peers[i] == n->peer)
+      {
+        break;
+      }
+    }
+    if (NULL == n)
+      return l - i;
+    p = n;
+  }
+  return l - i;
+}
+
+
+/**
+ * Print the tree on stderr
+ *
+ * @param t The tree
+ */
+void
+tree_debug (struct CadetTunnelTree *t)
+{
+  tree_node_debug (t->root, 0);
+  FPRINTF (stderr, "root: %p\n", t->root);
+  FPRINTF (stderr, "me:   %p\n", t->me);
+}
+
+
+/**
+ * Iterator over hash map peer entries and frees all data in it.
+ * Used prior to destroying a hashmap. Makes you miss anonymous functions in C.
+ *
+ * @param cls closure
+ * @param key current key code (will no longer contain valid data!!)
+ * @param value value in the hash map (treated as void *)
+ * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
+ */
+static int
+iterate_free (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+  GNUNET_free (value);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Destroy the whole tree and free all used memory and Peer_Ids
+ *
+ * @param t Tree to be destroyed
+ */
+void
+tree_destroy (struct CadetTunnelTree *t)
+{
+#if CADET_TREE_DEBUG
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying tree\n");
+#endif
+  tree_node_destroy (t->root);
+  GNUNET_CONTAINER_multihashmap_iterate (t->first_hops, &iterate_free, NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (t->first_hops);
+  GNUNET_free (t);
+}

Copied: gnunet/src/cadet/cadet_tunnel_tree.h (from rev 33185, 
gnunet/src/mesh/cadet_tunnel_tree.h)
===================================================================
--- gnunet/src/cadet/cadet_tunnel_tree.h                                (rev 0)
+++ gnunet/src/cadet/cadet_tunnel_tree.h        2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,382 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/cadet_tunnel_tree.h
+ * @brief Tunnel tree handling functions
+ * @author Bartlomiej Polot
+ */
+
+#include "cadet.h"
+
+/******************************************************************************/
+/************************      DATA STRUCTURES     
****************************/
+/******************************************************************************/
+
+/**
+ * Information regarding a possible path to reach a single peer
+ */
+struct CadetPeerPath
+{
+
+    /**
+     * Linked list
+     */
+  struct CadetPeerPath *next;
+  struct CadetPeerPath *prev;
+
+    /**
+     * List of all the peers that form the path from origin to target.
+     */
+  GNUNET_PEER_Id *peers;
+
+    /**
+     * Number of peers (hops) in the path
+     */
+  unsigned int length;
+
+};
+
+
+/**
+ * Node of path tree for a tunnel
+ */
+struct CadetTunnelTreeNode;
+
+
+/**
+ * Tree to reach all peers in the tunnel
+ */
+struct CadetTunnelTree;
+
+
+/******************************************************************************/
+/*************************        FUNCTIONS       
*****************************/
+/******************************************************************************/
+
+/**
+ * Create a new path.
+ *
+ * @param length How many hops will the path have.
+ *
+ * @return A newly allocated path with a peer array of the specified length.
+ */
+struct CadetPeerPath *
+path_new (unsigned int length);
+
+
+/**
+ * Invert the path.
+ *
+ * @param path The path to invert.
+ */
+void
+path_invert (struct CadetPeerPath *path);
+
+
+/**
+ * Duplicate a path, incrementing short peer's rc.
+ *
+ * @param path The path to duplicate.
+ */
+struct CadetPeerPath *
+path_duplicate (struct CadetPeerPath *path);
+
+
+/**
+ * Get the length of a path.
+ *
+ * @param path The path to measure, with the local peer at any point of it.
+ *
+ * @return Number of hops to reach destination.
+ *         UINT_MAX in case the peer is not in the path.
+ */
+unsigned int
+path_get_length (struct CadetPeerPath *path);
+
+
+/**
+ * Destroy the path and free any allocated resources linked to it
+ *
+ * @param p the path to destroy
+ *
+ * @return GNUNET_OK on success
+ */
+int
+path_destroy (struct CadetPeerPath *p);
+
+
+/******************************************************************************/
+
+/**
+ * Iterator over all children of a node.
+ *
+ * @param cls Closure.
+ * @param peer_id Short ID of the peer.
+ */
+typedef void (*CadetTreeCallback) (void *cls, GNUNET_PEER_Id peer_id);
+
+
+/**
+ * Iterator over all nodes in a tree.
+ *
+ * @param cls Closure.
+ * @param peer_id Short ID of the peer.
+ * @param peer_id Short ID of the parent of the peer.
+ */
+typedef void (*CadetWholeTreeCallback) (void *cls,
+                                       GNUNET_PEER_Id peer_id,
+                                       GNUNET_PEER_Id parent_id);
+
+/**
+ * Create a new tunnel tree associated to a tunnel
+ *
+ * @param peer A short peer id of the root of the tree
+ *
+ * @return A newly allocated and initialized tunnel tree
+ */
+struct CadetTunnelTree *
+tree_new (GNUNET_PEER_Id peer);
+
+
+/**
+ * Set the status of a node.
+ *
+ * @param tree Tree.
+ * @param peer A short peer id of the node.
+ * @param status New status to set.
+ */
+void
+tree_set_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer,
+                 enum CadetPeerState status);
+
+
+/**
+ * Get the status of a node.
+ *
+ * @param tree Tree whose local id we want to now.
+ * @param peer A short peer id of the node.
+ *
+ * @return Short peer id of local peer.
+ */
+enum CadetPeerState
+tree_get_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer);
+
+
+/**
+ * Get the id of the predecessor of the local node.
+ *
+ * @param tree Tree whose local id we want to now.
+ *
+ * @return Short peer id of local peer.
+ */
+GNUNET_PEER_Id
+tree_get_predecessor (struct CadetTunnelTree *tree);
+
+
+/**
+ * Find the first peer whom to send a packet to go down this path
+ *
+ * @param t The tunnel tree to use
+ * @param peer The peerinfo of the peer we are trying to reach
+ *
+ * @return peerinfo of the peer who is the first hop in the tunnel
+ *         NULL on error
+ */
+struct GNUNET_PeerIdentity *
+tree_get_first_hop (struct CadetTunnelTree *t, GNUNET_PEER_Id peer);
+
+
+/**
+ * Find the given peer in the tree.
+ *
+ * @param tree Tree where to look for the peer.
+ * @param peer_id Peer to find.
+ *
+ * @return Pointer to the node of the peer. NULL if not found.
+ */
+struct CadetTunnelTreeNode *
+tree_find_peer (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer_id);
+
+
+/**
+ * Iterate over all children of the local node.
+ *
+ * @param tree Tree to use. Must have "me" set.
+ * @param cb Callback to call over each child.
+ * @param cb_cls Closure for @c cb.
+ */
+void
+tree_iterate_children (struct CadetTunnelTree *tree,
+                       CadetTreeCallback cb,
+                       void *cb_cls);
+
+
+/**
+ * Iterate over all nodes in the tree.
+ *
+ * @param tree Tree to use..
+ * @param cb Callback to call over each child.
+ * @param cb_cls Closure for @c cb.
+ *
+ * TODO: recursive implementation? (s/heap/stack/g)
+ */
+void
+tree_iterate_all (struct CadetTunnelTree *tree,
+                  CadetWholeTreeCallback cb,
+                  void *cb_cls);
+
+/**
+ * Count how many children does the local node have in the tree.
+ *
+ * @param tree Tree to use. Must have "me" set.
+ */
+unsigned int
+tree_count_children (struct CadetTunnelTree *tree);
+
+
+/**
+ * Recusively update the info about what is the first hop to reach the node
+ *
+ * @param tree Tree this nodes belongs to.
+ * @param parent_id Short ID from node form which to start updating.
+ * @param hop If known, ID of the first hop.
+ *            If not known, NULL to find out and pass on children.
+ */
+void
+tree_update_first_hops (struct CadetTunnelTree *tree, GNUNET_PEER_Id parent_id,
+                        struct GNUNET_PeerIdentity *hop);
+
+/**
+ * Delete the current path to the peer, including all now unused relays.
+ * The destination peer is NOT destroyed, it is returned in order to either set
+ * a new path to it or destroy it explicitly, taking care of it's child nodes.
+ *
+ * @param t Tunnel tree where to delete the path from.
+ * @param peer_id Short ID of the destination peer whose path we want to 
remove.
+ * @param cb Callback to use to notify about which peers are going to be
+ *           disconnected.
+ * @param cbcls Closure for cb.
+ *
+ * @return pointer to the pathless node.
+ *         NULL when not found
+ */
+struct CadetTunnelTreeNode *
+tree_del_path (struct CadetTunnelTree *t, GNUNET_PEER_Id peer_id,
+               CadetTreeCallback cb, void *cbcls);
+
+
+/**
+ * Return a newly allocated individual path to reach a peer from the local 
peer,
+ * according to the path tree of some tunnel.
+ *
+ * @param t Tunnel from which to read the path tree
+ * @param peer Destination peer to whom we want a path
+ *
+ * @return A newly allocated individual path to reach the destination peer.
+ *         Path must be destroyed afterwards.
+ */
+struct CadetPeerPath *
+tree_get_path_to_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer);
+
+
+/**
+ * Integrate a stand alone path into the tunnel tree.
+ *
+ * @param t Tunnel where to add the new path.
+ * @param p Path to be integrated.
+ * @param cb Callback to use to notify about peers temporarily disconnecting.
+ * @param cbcls Closure for cb.
+ *
+ * @return GNUNET_OK in case of success.
+ *         GNUNET_SYSERR in case of error.
+ */
+int
+tree_add_path (struct CadetTunnelTree *t, const struct CadetPeerPath *p,
+               CadetTreeCallback cb, void *cbcls);
+
+
+/**
+ * Notifies a tree that a connection it might be using is broken.
+ * Marks all peers down the paths as disconnected and notifies the client.
+ *
+ * @param t Tree to use.
+ * @param p1 Short id of one of the peers (order unimportant)
+ * @param p2 Short id of one of the peers (order unimportant)
+ * @param cb Function to call for every peer that is marked as disconnected.
+ * @param cbcls Closure for cb.
+ *
+ * @return Short ID of the first disconnected peer in the tree.
+ */
+GNUNET_PEER_Id
+tree_notify_connection_broken (struct CadetTunnelTree *t, GNUNET_PEER_Id p1,
+                               GNUNET_PEER_Id p2, CadetTreeCallback cb,
+                               void *cbcls);
+
+
+/**
+ * Deletes a peer from a tunnel, liberating all unused resources on the path to
+ * it. It shouldn't have children, if it has they will be destroyed as well.
+ * If the tree is not local and no longer has any paths, the root node will be
+ * destroyed and marked as NULL.
+ *
+ * FIXME: dont destroy the root
+ *
+ * @param t Tunnel tree to use.
+ * @param peer Short ID of the peer to remove from the tunnel tree.
+ * @param cb Callback to notify client of disconnected peers.
+ * @param cbcls Closure for cb.
+ *
+ * @return GNUNET_YES if the tunnel still has nodes
+ */
+int
+tree_del_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer,
+               CadetTreeCallback cb, void *cbcls);
+
+
+/**
+ * Get the cost of the path relative to the already built tunnel tree
+ *
+ * @param t The tunnel tree to which compare
+ * @param path The individual path to reach a peer
+ *
+ * @return Number of hops to reach destination, UINT_MAX in case the peer is 
not
+ * in the path
+ */
+unsigned int
+tree_get_path_cost (struct CadetTunnelTree *t, struct CadetPeerPath *path);
+
+
+/**
+ * Print the tree on stderr
+ *
+ * @param t The tree
+ */
+void
+tree_debug (struct CadetTunnelTree *t);
+
+
+/**
+ * Destroy the whole tree and free all used memory and Peer_Ids
+ *
+ * @param t Tree to be destroyed
+ */
+void
+tree_destroy (struct CadetTunnelTree *t);

Copied: gnunet/src/cadet/gnunet-cadet-profiler.c (from rev 33185, 
gnunet/src/mesh/gnunet-cadet-profiler.c)
===================================================================
--- gnunet/src/cadet/gnunet-cadet-profiler.c                            (rev 0)
+++ gnunet/src/cadet/gnunet-cadet-profiler.c    2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,1092 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file cadet/gnunet-cadet-profiler.c
+ *
+ * @brief Profiler for cadet experiments.
+ */
+#include <stdio.h>
+#include "platform.h"
+#include "cadet_test_lib.h"
+#include "gnunet_cadet_service.h"
+#include "gnunet_statistics_service.h"
+
+
+#define PING 1
+#define PONG 2
+
+
+/**
+ * Paximum ping period in milliseconds. Real period = rand (0, PING_PERIOD)
+ */
+#define PING_PERIOD 1000
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * Time to wait for stuff that should be rather fast
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
300)
+
+/**
+ * Total number of rounds.
+ */
+#define number_rounds sizeof(rounds)/sizeof(rounds[0])
+
+/**
+ * Ratio of peers active. First round always is 1.0.
+ */
+static float rounds[] = {0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.0};
+
+/**
+ * Message type for pings.
+ */
+struct CadetPingMessage
+{
+  /**
+   * Header. Type PING/PONG.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Message number.
+   */
+  uint32_t counter;
+
+  /**
+   * Time the message was sent.
+   */
+  struct GNUNET_TIME_AbsoluteNBO timestamp;
+
+  /**
+   * Round number.
+   */
+  uint32_t round_number;
+};
+
+/**
+ * Peer description.
+ */
+struct CadetPeer
+{
+  /**
+   * Testbed Operation (to get peer id, etc).
+   */
+  struct GNUNET_TESTBED_Operation *op;
+
+  /**
+   * Peer ID.
+   */
+  struct GNUNET_PeerIdentity id;
+
+  /**
+   * Cadet handle for the root peer
+   */
+  struct GNUNET_CADET_Handle *cadet;
+
+  /**
+   * Channel handle for the root peer
+   */
+  struct GNUNET_CADET_Channel *ch;
+
+  /**
+   * Channel handle for the dest peer
+   */
+  struct GNUNET_CADET_Channel *incoming_ch;
+
+  /**
+   * Channel handle for a warmup channel.
+   */
+  struct GNUNET_CADET_Channel *warmup_ch;
+
+  /**
+   * Number of payload packes sent
+   */
+  int data_sent;
+
+  /**
+   * Number of payload packets received
+   */
+  int data_received;
+
+  /**
+   * Is peer up?
+   */
+  int up;
+
+  /**
+   * Destinaton to ping.
+   */
+  struct CadetPeer *dest;
+
+  /**
+   * Incoming channel for pings.
+   */
+  struct CadetPeer *incoming;
+
+  /**
+   * Task to do the next ping.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier ping_task;
+
+  float mean[number_rounds];
+  float var[number_rounds];
+  unsigned int pongs[number_rounds];
+  unsigned int pings[number_rounds];
+
+};
+
+/**
+ * Duration of each round.
+ */
+static struct GNUNET_TIME_Relative round_time;
+
+/**
+ * GNUNET_PeerIdentity -> CadetPeer
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *ids;
+
+/**
+ * Testbed peer handles.
+ */
+static struct GNUNET_TESTBED_Peer **testbed_handles;
+
+/**
+ * Testbed Operation (to get stats).
+ */
+static struct GNUNET_TESTBED_Operation *stats_op;
+
+/**
+ * Operation to get peer ids.
+ */
+struct CadetPeer *peers;
+
+/**
+ * Peer ids counter.
+ */
+static unsigned int p_ids;
+
+/**
+ * Total number of peers.
+ */
+static unsigned long long peers_total;
+
+/**
+ * Number of currently running peers.
+ */
+static unsigned long long peers_running;
+
+/**
+ * Number of peers doing pings.
+ */
+static unsigned long long peers_pinging;
+
+/**
+ * Test context (to shut down).
+ */
+static struct GNUNET_CADET_TEST_Context *test_ctx;
+
+/**
+ * Task called to shutdown test.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
+
+/**
+ * Task called to disconnect peers, before shutdown.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+/**
+ * Task to perform tests
+ */
+static GNUNET_SCHEDULER_TaskIdentifier test_task;
+
+/**
+ * Round number.
+ */
+static unsigned int current_round;
+
+/**
+ * Do preconnect? (Each peer creates a tunnel to one other peer).
+ */
+static int do_warmup;
+
+/**
+ * Warmup progress.
+ */
+static unsigned int peers_warmup;
+
+/**
+ * Flag to notify callbacks not to generate any new traffic anymore.
+ */
+static int test_finished;
+
+
+/**
+ * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
+ *
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ *
+ * @param cls Closure (unsued).
+ * @param tc Task Context.
+ */
+static void
+start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Calculate a random delay.
+ *
+ * @param max Exclusive maximum, in ms.
+ *
+ * @return A time between 0 a max-1 ms.
+ */
+static struct GNUNET_TIME_Relative
+delay_ms_rnd (unsigned int max)
+{
+  unsigned int rnd;
+
+  rnd = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max);
+  return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rnd);
+}
+
+
+/**
+ * Get the index of a peer in the peers array.
+ *
+ * @param peer Peer whose index to get.
+ *
+ * @return Index of peer in peers.
+ */
+static unsigned int
+get_index (struct CadetPeer *peer)
+{
+  return peer - peers;
+}
+
+
+/**
+ * Show the results of the test (banwidth acheived) and log them to GAUGER
+ */
+static void
+show_end_data (void)
+{
+  struct CadetPeer *peer;
+  unsigned int i;
+  unsigned int j;
+
+  for (i = 0; i < number_rounds; i++)
+  {
+    for (j = 0; j < peers_pinging; j++)
+    {
+      peer = &peers[j];
+      FPRINTF (stdout,
+               "ROUND %3u PEER %3u: %10.2f / %10.2f, PINGS: %3u, PONGS: %3u\n",
+               i, j, peer->mean[i], sqrt (peer->var[i] / (peer->pongs[i] - 1)),
+               peer->pings[i], peer->pongs[i]);
+    }
+  }
+}
+
+
+/**
+ * Shut down peergroup, clean up.
+ *
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ending test.\n");
+  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
+}
+
+
+/**
+ * Disconnect from cadet services af all peers, call shutdown.
+ *
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+disconnect_cadet_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
+{
+  long line = (long) cls;
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "disconnecting cadet service, called from line %ld\n", line);
+  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  for (i = 0; i < peers_total; i++)
+  {
+    if (NULL != peers[i].op)
+      GNUNET_TESTBED_operation_done (peers[i].op);
+
+    if (peers[i].up != GNUNET_YES)
+      continue;
+
+    if (NULL != peers[i].ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: channel %p\n", i, peers[i].ch);
+      GNUNET_CADET_channel_destroy (peers[i].ch);
+    }
+    if (NULL != peers[i].warmup_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: warmup channel %p\n",
+                  i, peers[i].warmup_ch);
+      GNUNET_CADET_channel_destroy (peers[i].warmup_ch);
+    }
+    if (NULL != peers[i].incoming_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: incoming channel %p\n",
+                  i, peers[i].incoming_ch);
+      GNUNET_CADET_channel_destroy (peers[i].incoming_ch);
+    }
+  }
+  GNUNET_CADET_TEST_cleanup (test_ctx);
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_handle);
+  }
+  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+
+/**
+ * Finish test normally: schedule disconnect and shutdown
+ *
+ * @param line Line in the code the abort is requested from (__LINE__).
+ */
+static void
+abort_test (long line)
+{
+  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                                (void *) line);
+  }
+}
+
+/**
+ * Stats callback. Finish the stats testbed operation and when all stats have
+ * been iterated, shutdown the test.
+ *
+ * @param cls closure
+ * @param op the operation that has been finished
+ * @param emsg error message in case the operation has failed; will be NULL if
+ *          operation has executed successfully.
+ */
+static void
+stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "... collecting statistics done.\n");
+  GNUNET_TESTBED_operation_done (stats_op);
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                              (void *) __LINE__);
+
+}
+
+
+/**
+ * Process statistic values.
+ *
+ * @param cls closure
+ * @param peer the peer the statistic belong to
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
+ * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
+ */
+static int
+stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
+                const char *subsystem, const char *name,
+                uint64_t value, int is_persistent)
+{
+  uint32_t i;
+
+  i = GNUNET_TESTBED_get_index (peer);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " STATS %u - %s [%s]: %llu\n",
+              i, subsystem, name, value);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Task check that keepalives were sent and received.
+ *
+ * @param cls Closure (NULL).
+ * @param tc Task Context.
+ */
+static void
+collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start collecting statistics...\n");
+  stats_op = GNUNET_TESTBED_get_statistics (peers_total, testbed_handles,
+                                            NULL, NULL,
+                                            stats_iterator, stats_cont, NULL);
+}
+
+
+/**
+ * @brief Finish profiler normally. Signal finish and start collecting stats.
+ *
+ * @param cls Closure (unused).
+ * @param tc Task context.
+ */
+static void
+finish_profiler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  test_finished = GNUNET_YES;
+  show_end_data();
+  GNUNET_SCHEDULER_add_now (&collect_stats, NULL);
+}
+
+/**
+ * Set the total number of running peers.
+ *
+ * @param target Desired number of running peers.
+ */
+static void
+adjust_running_peers (unsigned int target)
+{
+  struct GNUNET_TESTBED_Operation *op;
+  unsigned int delta;
+  unsigned int run;
+  unsigned int i;
+  unsigned int r;
+
+  GNUNET_assert (target <= peers_total);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "adjust peers to %u\n", target);
+  if (target > peers_running)
+  {
+    delta = target - peers_running;
+    run = GNUNET_YES;
+  }
+  else
+  {
+    delta = peers_running - target;
+    run = GNUNET_NO;
+  }
+
+  for (i = 0; i < delta; i++)
+  {
+    do {
+      r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                    peers_total - peers_pinging);
+      r += peers_pinging;
+    } while (peers[r].up == run || NULL != peers[r].incoming);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "St%s peer %u: %s\n",
+                run ? "arting" : "opping", r, GNUNET_i2s (&peers[r].id));
+
+    if (GNUNET_SCHEDULER_NO_TASK != peers[r].ping_task)
+      GNUNET_SCHEDULER_cancel (peers[r].ping_task);
+    peers[r].ping_task = GNUNET_SCHEDULER_NO_TASK;
+
+    peers[r].up = run;
+
+    if (NULL != peers[r].ch)
+      GNUNET_CADET_channel_destroy (peers[r].ch);
+    peers[r].ch = NULL;
+    if (NULL != peers[r].dest)
+    {
+      if (NULL != peers[r].dest->incoming_ch)
+        GNUNET_CADET_channel_destroy (peers[r].dest->incoming_ch);
+      peers[r].dest->incoming_ch = NULL;
+    }
+
+    op = GNUNET_TESTBED_peer_manage_service (&peers[r], testbed_handles[r],
+                                             "cadet", NULL, NULL, run);
+    GNUNET_break (NULL != op);
+    peers_running += run ? 1 : -1;
+    GNUNET_assert (peers_running > 0);
+  }
+}
+
+
+/**
+ * @brief Move to next round.
+ *
+ * @param cls Closure (round #).
+ * @param tc Task context.
+ */
+static void
+next_rnd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ROUND %ld\n", current_round);
+  if (0.0 == rounds[current_round])
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finishing\n");
+    GNUNET_SCHEDULER_add_now (&finish_profiler, NULL);
+    return;
+  }
+  adjust_running_peers (rounds[current_round] * peers_total);
+  current_round++;
+
+  GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL);
+}
+
+
+/**
+ * Transmit ping callback.
+ *
+ * @param cls Closure (peer for PING, NULL for PONG).
+ * @param size Size of the tranmist buffer.
+ * @param buf Pointer to the beginning of the buffer.
+ *
+ * @return Number of bytes written to buf.
+ */
+static size_t
+tmt_rdy_ping (void *cls, size_t size, void *buf);
+
+
+/**
+ * Transmit pong callback.
+ *
+ * @param cls Closure (copy of PING message, to be freed).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+static size_t
+tmt_rdy_pong (void *cls, size_t size, void *buf)
+{
+  struct CadetPingMessage *ping = cls;
+  struct CadetPingMessage *pong;
+
+  if (0 == size || NULL == buf)
+  {
+    GNUNET_free (ping);
+    return 0;
+  }
+  pong = (struct CadetPingMessage *) buf;
+  memcpy (pong, ping, sizeof (*ping));
+  pong->header.type = htons (PONG);
+
+  GNUNET_free (ping);
+  return sizeof (*ping);
+}
+
+
+/**
+ * @brief Send a ping to destination
+ *
+ * @param cls Closure (peer).
+ * @param tc Task context.
+ */
+static void
+ping (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetPeer *peer = (struct CadetPeer *) cls;
+
+  peer->ping_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0
+      || GNUNET_YES == test_finished)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u -> %u (%u)\n",
+              get_index (peer), get_index (peer->dest), peer->data_sent);
+
+  GNUNET_CADET_notify_transmit_ready (peer->ch, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     sizeof (struct CadetPingMessage),
+                                     &tmt_rdy_ping, peer);
+}
+
+/**
+ * @brief Reply with a pong to origin.
+ *
+ * @param cls Closure (peer).
+ * @param tc Task context.
+ */
+static void
+pong (struct GNUNET_CADET_Channel *channel, const struct CadetPingMessage 
*ping)
+{
+  struct CadetPingMessage *copy;
+
+  copy = GNUNET_new (struct CadetPingMessage);
+  memcpy (copy, ping, sizeof (*ping));
+  GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     sizeof (struct CadetPingMessage),
+                                     &tmt_rdy_pong, copy);
+}
+
+
+/**
+ * Transmit ping callback
+ *
+ * @param cls Closure (peer).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+static size_t
+tmt_rdy_ping (void *cls, size_t size, void *buf)
+{
+  struct CadetPeer *peer = (struct CadetPeer *) cls;
+  struct CadetPingMessage *msg = buf;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tmt_rdy called, filling buffer\n");
+  if (size < sizeof (struct CadetPingMessage) || NULL == buf)
+  {
+    GNUNET_break (GNUNET_YES == test_finished);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "size %u, buf %p, data_sent %u, data_received %u\n",
+                size, buf, peer->data_sent, peer->data_received);
+
+    return 0;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending: msg %d\n", peer->data_sent);
+  msg->header.size = htons (size);
+  msg->header.type = htons (PING);
+  msg->counter = htonl (peer->data_sent++);
+  msg->round_number = htonl (current_round);
+  msg->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
+  peer->pings[current_round]++;
+  peer->ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (PING_PERIOD),
+                                                  &ping, peer);
+
+  return sizeof (struct CadetPingMessage);
+}
+
+
+/**
+ * Function is called whenever a PING message is received.
+ *
+ * @param cls closure (peer #, set from GNUNET_CADET_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+ping_handler (void *cls, struct GNUNET_CADET_Channel *channel,
+              void **channel_ctx,
+              const struct GNUNET_MessageHeader *message)
+{
+  long n = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u got PING\n", n);
+  GNUNET_CADET_receive_done (channel);
+  if (GNUNET_NO == test_finished)
+    pong (channel, (struct CadetPingMessage *) message);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function is called whenever a PONG message is received.
+ *
+ * @param cls closure (peer #, set from GNUNET_CADET_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+pong_handler (void *cls, struct GNUNET_CADET_Channel *channel,
+              void **channel_ctx,
+              const struct GNUNET_MessageHeader *message)
+{
+  long n = (long) cls;
+  struct CadetPeer *peer;
+  struct CadetPingMessage *msg;
+  struct GNUNET_TIME_Absolute send_time;
+  struct GNUNET_TIME_Relative latency;
+  unsigned int r /* Ping round */;
+  float delta;
+
+  GNUNET_CADET_receive_done (channel);
+  peer = &peers[n];
+
+  msg = (struct CadetPingMessage *) message;
+
+  send_time = GNUNET_TIME_absolute_ntoh (msg->timestamp);
+  latency = GNUNET_TIME_absolute_get_duration (send_time);
+  r = ntohl (msg->round_number);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n",
+              get_index (peer), get_index (peer->dest), ntohl (msg->counter),
+              GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
+
+  /* Online variance calculation */
+  peer->pongs[r]++;
+  delta = latency.rel_value_us - peer->mean[r];
+  peer->mean[r] = peer->mean[r] + delta/peer->pongs[r];
+  peer->var[r] += delta * (latency.rel_value_us - peer->mean[r]);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handlers, for diverse services
+ */
+static struct GNUNET_CADET_MessageHandler handlers[] = {
+  {&ping_handler, PING, sizeof (struct CadetPingMessage)},
+  {&pong_handler, PONG, sizeof (struct CadetPingMessage)},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * Method called whenever another peer has added us to a channel
+ * the other peer initiated.
+ *
+ * @param cls Closure.
+ * @param channel New handle to the channel.
+ * @param initiator Peer that started the channel.
+ * @param port Port this channel is connected to.
+ * @param options channel option flags
+ * @return Initial channel context for the channel
+ *         (can be NULL -- that's not an error).
+ */
+static void *
+incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel,
+                 const struct GNUNET_PeerIdentity *initiator,
+                 uint32_t port, enum GNUNET_CADET_ChannelOption options)
+{
+  long n = (long) cls;
+  struct CadetPeer *peer;
+
+  peer = GNUNET_CONTAINER_multipeermap_get (ids, initiator);
+  GNUNET_assert (NULL != peer);
+  if (NULL == peers[n].incoming)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %3u: %u <= %u\n",
+                peers_warmup, n, get_index (peer));
+    peers_warmup++;
+    if (peers_warmup < peers_total)
+      return NULL;
+    if (GNUNET_SCHEDULER_NO_TASK != test_task)
+    {
+      GNUNET_SCHEDULER_cancel (test_task);
+      test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                                &start_test, NULL);
+    }
+    return NULL;
+  }
+  GNUNET_assert (peer == peers[n].incoming);
+  GNUNET_assert (peer->dest == &peers[n]);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <= %u %p\n",
+              n, get_index (peer), channel);
+  peers[n].incoming_ch = channel;
+
+  return NULL;
+}
+
+/**
+ * Function called whenever an inbound channel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect)
+ * @param channel connection to the other end (henceforth invalid)
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ */
+static void
+channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel,
+                 void *channel_ctx)
+{
+  long n = (long) cls;
+  struct CadetPeer *peer = &peers[n];
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Channel %p disconnected at peer %ld\n", channel, n);
+  if (peer->ch == channel)
+    peer->ch = NULL;
+}
+
+
+/**
+ * Select a random peer that has no incoming channel
+ *
+ * @param peer ID of the peer connecting. NULL if irrelevant (warmup).
+ *
+ * @return Random peer not yet connected to.
+ */
+static struct CadetPeer *
+select_random_peer (struct CadetPeer *peer)
+{
+  unsigned int r;
+
+  do
+  {
+    r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total);
+  } while (NULL != peers[r].incoming);
+  peers[r].incoming = peer;
+
+  return &peers[r];
+}
+
+/**
+ * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
+ *
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ *
+ * @param cls Closure (unsued).
+ * @param tc Task Context.
+ */
+static void
+start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  enum GNUNET_CADET_ChannelOption flags;
+  unsigned long i;
+
+  test_task = GNUNET_SCHEDULER_NO_TASK;
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start profiler\n");
+
+  flags = GNUNET_CADET_OPTION_DEFAULT;
+  for (i = 0; i < peers_pinging; i++)
+  {
+    peers[i].dest = select_random_peer (&peers[i]);
+    peers[i].ch = GNUNET_CADET_channel_create (peers[i].cadet, NULL,
+                                              &peers[i].dest->id,
+                                              1, flags);
+    if (NULL == peers[i].ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Channel %lu failed\n", i);
+      GNUNET_CADET_TEST_cleanup (test_ctx);
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u => %u %p\n",
+                i, get_index (peers[i].dest), peers[i].ch);
+    peers[i].ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (2000),
+                                                       &ping, &peers[i]);
+  }
+  peers_running = peers_total;
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task =
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(round_time,
+                                                                number_rounds 
+ 1),
+                                  &disconnect_cadet_peers,
+                                  (void *) __LINE__);
+  GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL);
+}
+
+
+/**
+ * Do warmup: create some channels to spread information about the topology.
+ */
+static void
+warmup (void)
+{
+  struct CadetPeer *peer;
+  unsigned int i;
+
+  for (i = 0; i < peers_total; i++)
+  {
+    peer = select_random_peer (NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %u => %u\n",
+                i, get_index (peer));
+    peers[i].warmup_ch =
+      GNUNET_CADET_channel_create (peers[i].cadet, NULL, &peer->id,
+                                  1, GNUNET_CADET_OPTION_DEFAULT);
+    if (NULL == peers[i].warmup_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Warmup %u failed\n", i);
+      GNUNET_CADET_TEST_cleanup (test_ctx);
+      return;
+    }
+  }
+}
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed;
+ *             NULL if the operation is successfull
+ */
+static void
+peer_id_cb (void *cls,
+       struct GNUNET_TESTBED_Operation *op,
+       const struct GNUNET_TESTBED_PeerInformation *pinfo,
+       const char *emsg)
+{
+  long n = (long) cls;
+
+  if (NULL == pinfo || NULL != emsg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
+    abort_test (__LINE__);
+    return;
+  }
+  peers[n].id = *(pinfo->result.id);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u  id: %s\n",
+              n, GNUNET_i2s (&peers[n].id));
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_CONTAINER_multipeermap_put (ids, &peers[n].id, 
&peers[n],
+                                                   
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+
+  GNUNET_TESTBED_operation_done (peers[n].op);
+  peers[n].op = NULL;
+
+  p_ids++;
+  if (p_ids < peers_total)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting profiler\n");
+  if (do_warmup)
+  {
+    struct GNUNET_TIME_Relative delay;
+
+    warmup();
+    delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                           100 * peers_total);
+    test_task = GNUNET_SCHEDULER_add_delayed (delay, &start_test, NULL);
+    return; /* start_test from incoming_channel */
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting in a second...\n");
+  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                            &start_test, NULL);
+}
+
+/**
+ * test main: start test when all peers are connected
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param testbed_peers Array of peers.
+ * @param cadetes Handle to each of the CADETs of the peers.
+ */
+static void
+tmain (void *cls,
+       struct GNUNET_CADET_TEST_Context *ctx,
+       unsigned int num_peers,
+       struct GNUNET_TESTBED_Peer **testbed_peers,
+       struct GNUNET_CADET_Handle **cadetes)
+{
+  unsigned long i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
+  test_ctx = ctx;
+  GNUNET_assert (peers_total == num_peers);
+  peers_running = num_peers;
+  testbed_handles = testbed_peers;
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_cadet_peers,
+                                                  (void *) __LINE__);
+  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                  &shutdown_task, NULL);
+  for (i = 0; i < peers_total; i++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requesting id %ld\n", i);
+    peers[i].up = GNUNET_YES;
+    peers[i].cadet = cadetes[i];
+    peers[i].op =
+      GNUNET_TESTBED_peer_get_information (testbed_handles[i],
+                                           GNUNET_TESTBED_PIT_IDENTITY,
+                                           &peer_id_cb, (void *) i);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "requested peer ids\n");
+  /* Continues from pi_cb -> do_test */
+}
+
+
+/**
+ * Main: start profiler.
+ */
+int
+main (int argc, char *argv[])
+{
+  static uint32_t ports[2];
+  const char *config_file;
+
+  config_file = ".profiler.conf";
+
+  if (4 > argc)
+  {
+    fprintf (stderr, "usage: %s ROUND_TIME PEERS PINGS [DO_WARMUP]\n", 
argv[0]);
+    fprintf (stderr, "example: %s 30s 16 1 Y\n", argv[0]);
+    return 1;
+  }
+
+  if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[1], 
&round_time))
+  {
+    fprintf (stderr, "%s is not a valid time\n", argv[1]);
+    return 1;
+  }
+
+  peers_total = atoll (argv[2]);
+  if (2 > peers_total)
+  {
+    fprintf (stderr, "%s peers is not valid (> 2)\n", argv[1]);
+    return 1;
+  }
+  peers = GNUNET_malloc (sizeof (struct CadetPeer) * peers_total);
+
+  peers_pinging = atoll (argv[3]);
+
+  if (peers_total < 2 * peers_pinging)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "not enough peers, total should be > 2 * peers_pinging\n");
+    return 1;
+  }
+
+  do_warmup = (5 > argc || argv[4][0] != 'N');
+
+  ids = GNUNET_CONTAINER_multipeermap_create (2 * peers_total, GNUNET_YES);
+  GNUNET_assert (NULL != ids);
+  p_ids = 0;
+  test_finished = GNUNET_NO;
+  ports[0] = 1;
+  ports[1] = 0;
+  GNUNET_CADET_TEST_run ("cadet-profiler", config_file, peers_total,
+                        &tmain, NULL, /* tmain cls */
+                        &incoming_channel, &channel_cleaner,
+                        handlers, ports);
+  GNUNET_free (peers);
+
+  return 0;
+}
+
+/* end of gnunet-cadet-profiler.c */
+

Copied: gnunet/src/cadet/gnunet-cadet.c (from rev 33185, 
gnunet/src/mesh/gnunet-cadet.c)
===================================================================
--- gnunet/src/cadet/gnunet-cadet.c                             (rev 0)
+++ gnunet/src/cadet/gnunet-cadet.c     2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,851 @@
+/*
+     This file is part of GNUnet.
+     (C) 2012 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-cadet.c
+ * @brief Print information about cadet tunnels and peers.
+ * @author Bartlomiej Polot
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_cadet_service.h"
+#include "cadet.h"
+
+
+/**
+ * Option -m.
+ */
+static int monitor_connections;
+
+/**
+ * Option -P.
+ */
+static int request_peers;
+
+/**
+ * Option --peer
+ */
+static char *peer_id;
+
+/**
+ * Option -T.
+ */
+static int request_tunnels;
+
+/**
+ * Option --tunnel
+ */
+static char *tunnel_id;
+
+/**
+ * Option --connection
+ */
+static char *conn_id;
+
+/**
+ * Option --channel
+ */
+static char *channel_id;
+
+/**
+ * Port to listen on (-p).
+ */
+static uint32_t listen_port;
+
+/**
+ * Request echo service
+ */
+int echo;
+
+/**
+ * Time of last echo request.
+ */
+struct GNUNET_TIME_Absolute echo_time;
+
+/**
+ * Task for next echo request.
+ */
+GNUNET_SCHEDULER_TaskIdentifier echo_task;
+
+/**
+ * Peer to connect to.
+ */
+static char *target_id;
+
+/**
+ * Port to connect to
+ */
+static uint32_t target_port;
+
+/**
+ * Data pending in netcat mode.
+ */
+size_t data_size;
+
+
+/**
+ * Cadet handle.
+ */
+static struct GNUNET_CADET_Handle *mh;
+
+/**
+ * Channel handle.
+ */
+static struct GNUNET_CADET_Channel *ch;
+
+/**
+ * Shutdown task handle.
+ */
+GNUNET_SCHEDULER_TaskIdentifier sd;
+
+
+
+static void
+listen_stdio (void);
+
+
+
+/**
+ * Task run in monitor mode when the user presses CTRL-C to abort.
+ * Stops monitoring activity.
+ *
+ * @param cls Closure (unused).
+ * @param tc scheduler context
+ */
+static void
+shutdown_task (void *cls,
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
+  if (NULL != ch)
+  {
+    GNUNET_CADET_channel_destroy (ch);
+    ch = NULL;
+  }
+  if (NULL != mh)
+  {
+    GNUNET_CADET_disconnect (mh);
+        mh = NULL;
+  }
+}
+
+
+/**
+ * Function called to notify a client about the connection
+ * begin ready to queue more data.  "buf" will be
+ * NULL and "size" zero if the connection was closed for
+ * writing in the meantime.
+ *
+ * FIXME
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+size_t
+data_ready (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *msg;
+  size_t total_size;
+
+  if (NULL == buf || 0 == size)
+  {
+    GNUNET_SCHEDULER_shutdown();
+    return 0;
+  }
+
+  total_size = data_size + sizeof (struct GNUNET_MessageHeader);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending %u bytes\n", data_size);
+  GNUNET_assert (size >= total_size);
+
+  msg = buf;
+  msg->size = htons (total_size);
+  msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_CLI);
+  memcpy (&msg[1], cls, data_size);
+  if (GNUNET_NO == echo)
+  {
+    listen_stdio ();
+  }
+  else
+  {
+    echo_time = GNUNET_TIME_absolute_get ();
+  }
+
+  return total_size;
+}
+
+
+/**
+ * Task run in monitor mode when the user presses CTRL-C to abort.
+ * Stops monitoring activity.
+ *
+ * @param cls Closure (unused).
+ * @param tc scheduler context
+ */
+static void
+read_stdio (void *cls,
+            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  static char buf[60000];
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    return;
+  }
+
+  data_size = read (0, buf, 60000);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stdio read %u bytes\n", data_size);
+  if (data_size < 1)
+  {
+    GNUNET_SCHEDULER_shutdown();
+    return;
+  }
+  GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     data_size
+                                     + sizeof (struct GNUNET_MessageHeader),
+                                     &data_ready, buf);
+}
+
+
+/**
+ * Start listening to stdin
+ */
+static void
+listen_stdio (void)
+{
+  struct GNUNET_NETWORK_FDSet *rs;
+
+  rs = GNUNET_NETWORK_fdset_create ();
+  GNUNET_NETWORK_fdset_set_native (rs, 0);
+  GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                               GNUNET_TIME_UNIT_FOREVER_REL,
+                               rs, NULL,
+                               &read_stdio, NULL);
+  GNUNET_NETWORK_fdset_destroy (rs);
+}
+
+
+/**
+ * Function called whenever a channel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
+ *
+ * @param cls closure (set from #GNUNET_CADET_connect)
+ * @param channel connection to the other end (henceforth invalid)
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ */
+static void
+channel_ended (void *cls,
+               const struct GNUNET_CADET_Channel *channel,
+               void *channel_ctx)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n");
+  GNUNET_break (channel == ch);
+  ch = NULL;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Method called whenever another peer has added us to a channel
+ * the other peer initiated.
+ * Only called (once) upon reception of data with a message type which was
+ * subscribed to in #GNUNET_CADET_connect.
+ *
+ * A call to #GNUNET_CADET_channel_destroy causes te channel to be ignored. In
+ * this case the handler MUST return NULL.
+ *
+ * @param cls closure
+ * @param channel new handle to the channel
+ * @param initiator peer that started the channel
+ * @param port Port this channel is for.
+ * @param options CadetOption flag field, with all active option bits set to 1.
+ *
+ * @return initial channel context for the channel
+ *         (can be NULL -- that's not an error)
+ */
+static void *
+channel_incoming (void *cls,
+                  struct GNUNET_CADET_Channel * channel,
+                  const struct GNUNET_PeerIdentity * initiator,
+                  uint32_t port, enum GNUNET_CADET_ChannelOption options)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Incoming channel %p on port %u\n",
+              channel, port);
+  if (NULL != ch)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A channel already exists\n");
+    return NULL;
+  }
+  if (0 == listen_port)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not listening to channels\n");
+    return NULL;
+  }
+  ch = channel;
+  if (GNUNET_NO == echo)
+  {
+    listen_stdio ();
+    return NULL;
+  }
+  data_size = 0;
+  return NULL;
+}
+
+/**
+ * @brief Send an echo request to the remote peer.
+ *
+ * @param cls Closure (NULL).
+ * @param tc Task context.
+ */
+static void
+send_echo (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || NULL == ch)
+    return;
+
+  GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     sizeof (struct GNUNET_MessageHeader),
+                                     &data_ready, NULL);
+}
+
+
+
+/**
+ * Call CADET's monitor API, get info of one connection.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_PeerIdentity pid;
+  enum GNUNET_CADET_ChannelOption opt;
+
+  GNUNET_assert (NULL == ch);
+
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
+                                                  strlen (target_id),
+                                                  &pid.public_key))
+  {
+    FPRINTF (stderr,
+             _("Invalid target `%s'\n"),
+             target_id);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id);
+  opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
+  ch = GNUNET_CADET_channel_create (mh, NULL, &pid, target_port, opt);
+  if (GNUNET_NO == echo)
+    listen_stdio ();
+  else
+    GNUNET_SCHEDULER_add_now (send_echo, NULL);
+}
+
+
+/**
+ * Function called whenever a message is received.
+ *
+ * Each time the function must call #GNUNET_CADET_receive_done on the channel
+ * in order to receive the next message. This doesn't need to be immediate:
+ * can be delayed if some processing is done on the message.
+ *
+ * @param cls Closure (set from #GNUNET_CADET_connect).
+ * @param channel Connection to the other end.
+ * @param channel_ctx Place to store local state associated with the channel.
+ * @param message The actual message.
+ * @return #GNUNET_OK to keep the channel open,
+ *         #GNUNET_SYSERR to close it (signal serious error).
+ */
+static int
+data_callback (void *cls,
+               struct GNUNET_CADET_Channel *channel,
+               void **channel_ctx,
+               const struct GNUNET_MessageHeader *message)
+{
+  uint16_t len;
+  ssize_t done;
+  uint16_t off;
+  const char *buf;
+  GNUNET_break (ch == channel);
+
+  if (GNUNET_YES == echo)
+  {
+    if (0 != listen_port)
+    {
+      /* Just listening to echo incoming messages*/
+      GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
+                                        GNUNET_TIME_UNIT_FOREVER_REL,
+                                        sizeof (struct GNUNET_MessageHeader),
+                                        &data_ready, NULL);
+      return GNUNET_OK;
+    }
+    else
+    {
+      struct GNUNET_TIME_Relative latency;
+
+      latency = GNUNET_TIME_absolute_get_duration (echo_time);
+      echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
+      FPRINTF (stdout, "time: %s\n",
+               GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
+      echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                                &send_echo, NULL);
+    }
+  }
+
+  len = ntohs (message->size) - sizeof (*message);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len);
+  buf = (const char *) &message[1];
+  off = 0;
+  while (off < len)
+  {
+    done = write (1, &buf[off], len - off);
+    if (done <= 0)
+    {
+      if (-1 == done)
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                             "write");
+      return GNUNET_SYSERR;
+    }
+    off += done;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Method called to retrieve information about all peers in CADET, called
+ * once per peer.
+ *
+ * After last peer has been reported, an additional call with NULL is done.
+ *
+ * @param cls Closure.
+ * @param peer Peer, or NULL on "EOF".
+ * @param tunnel Do we have a tunnel towards this peer?
+ * @param n_paths Number of known paths towards this peer.
+ * @param best_path How long is the best path?
+ *                  (0 = unknown, 1 = ourselves, 2 = neighbor)
+ */
+static void
+peers_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
+                int tunnel, unsigned int n_paths, unsigned int best_path)
+{
+  if (NULL == peer)
+  {
+    if (GNUNET_YES != monitor_connections)
+    {
+      GNUNET_SCHEDULER_shutdown();
+    }
+    return;
+  }
+  FPRINTF (stdout, "%s tunnel: %c, paths: %u\n",
+           GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths);
+}
+
+/**
+ * Method called to retrieve information about a specific peer
+ * known to the service.
+ *
+ * @param cls Closure.
+ * @param peer Peer ID.
+ * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO
+ * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO
+ * @param n_paths Number of paths known towards peer.
+ * @param paths Array of PEER_IDs representing all paths to reach the peer.
+ *              Each path starts with the local peer.
+ *              Each path ends with the destination peer (given in @c peer).
+ */
+void
+peer_callback (void *cls,
+               const struct GNUNET_PeerIdentity *peer,
+               int tunnel,
+               int neighbor,
+               unsigned int n_paths,
+               struct GNUNET_PeerIdentity *paths)
+{
+}
+
+
+/**
+ * Method called to retrieve information about all tunnels in CADET.
+ *
+ * @param cls Closure.
+ * @param peer Destination peer.
+ * @param channels Number of channels.
+ * @param connections Number of connections.
+ * @param estate Encryption state.
+ * @param cstate Connectivity state.
+ */
+void
+tunnels_callback (void *cls,
+                  const struct GNUNET_PeerIdentity *peer,
+                  unsigned int channels,
+                  unsigned int connections,
+                  uint16_t estate,
+                  uint16_t cstate)
+{
+  if (NULL == peer)
+  {
+    if (GNUNET_YES != monitor_connections)
+    {
+      GNUNET_SCHEDULER_shutdown();
+    }
+    return;
+  }
+  FPRINTF (stdout, "%s [ENC: %u, CON: %u] CHs: %u, CONNs: %u\n",
+           GNUNET_i2s_full (peer), estate, cstate, channels, connections);
+}
+
+
+/**
+ * Method called to retrieve information about a specific tunnel the cadet peer
+ * has established, o`r is trying to establish.
+ *
+ * @param cls Closure.
+ * @param peer Peer towards whom the tunnel is directed.
+ * @param n_channels Number of channels.
+ * @param n_connections Number of connections.
+ * @param channels Channels.
+ * @param connections Connections.
+ * @param estate Encryption status.
+ * @param cstate Connectivity status.
+ */
+void
+tunnel_callback (void *cls,
+                 const struct GNUNET_PeerIdentity *peer,
+                 unsigned int n_channels,
+                 unsigned int n_connections,
+                 uint32_t *channels,
+                 struct GNUNET_CADET_Hash *connections,
+                 unsigned int estate,
+                 unsigned int cstate)
+{
+  unsigned int i;
+
+  if (NULL != peer)
+  {
+    FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
+    FPRINTF (stdout, "- %u channels\n", n_channels);
+    for (i = 0; i < n_channels; i++)
+      FPRINTF (stdout, "   %u\n", channels[i]);
+    FPRINTF (stdout, "- %u connections\n", n_connections);
+    for (i = 0; i < n_connections; i++)
+      FPRINTF (stdout, "   %s\n", GM_h2s (&connections[i]));
+    FPRINTF (stdout, "- enc state: %u\n", estate);
+    FPRINTF (stdout, "- con state: %u\n", cstate);
+  }
+  if (GNUNET_YES != monitor_connections)
+  {
+    GNUNET_SCHEDULER_shutdown();
+  }
+  return;
+
+}
+
+
+/**
+ * Call CADET's meta API, get all peers known to a peer.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+get_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
+    return;
+  }
+  GNUNET_CADET_get_peers (mh, &peers_callback, NULL);
+}
+
+
+/**
+ * Call CADET's monitor API, get info of one peer.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+show_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_PeerIdentity pid;
+
+  if (GNUNET_OK !=
+    GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
+                                                strlen (peer_id),
+                                                &pid.public_key))
+  {
+    fprintf (stderr,
+             _("Invalid peer ID `%s'\n"),
+             peer_id);
+    GNUNET_SCHEDULER_shutdown();
+    return;
+  }
+  GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL);
+}
+
+/**
+ * Call CADET's meta API, get all tunnels known to a peer.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+get_tunnels (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
+    return;
+  }
+  GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL);
+}
+
+
+/**
+ * Call CADET's monitor API, get info of one tunnel.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_PeerIdentity pid;
+
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id,
+                                                  strlen (tunnel_id),
+                                                  &pid.public_key))
+  {
+    fprintf (stderr,
+             _("Invalid tunnel owner `%s'\n"),
+             tunnel_id);
+    GNUNET_SCHEDULER_shutdown();
+    return;
+  }
+  GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL);
+}
+
+
+/**
+ * Call CADET's monitor API, get info of one channel.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+show_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+}
+
+
+/**
+ * Call CADET's monitor API, get info of one connection.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext
+ */
+static void
+show_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GNUNET_CADET_InboundChannelNotificationHandler *newch = NULL;
+  GNUNET_CADET_ChannelEndHandler *endch = NULL;
+  static const struct GNUNET_CADET_MessageHandler handlers[] = {
+    {&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0},
+    {NULL, 0, 0} /* FIXME add option to monitor msg types */
+  };
+  static uint32_t *ports = NULL;
+  /* FIXME add option to monitor apps */
+
+  target_id = args[0];
+  target_port = args[0] && args[1] ? atoi(args[1]) : 0;
+  if ( (0 != (request_peers | request_tunnels)
+        || 0 != monitor_connections
+        || NULL != tunnel_id
+        || NULL != conn_id
+        || NULL != channel_id)
+       && target_id != NULL)
+  {
+    FPRINTF (stderr,
+             _("You must NOT give a TARGET"
+               "when using 'request all' options\n"));
+    return;
+  }
+
+  if (NULL != target_id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating channel to %s\n",
+                target_id);
+    GNUNET_SCHEDULER_add_now (&create_channel, NULL);
+    endch = &channel_ended;
+  }
+  else if (0 != listen_port)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Listen\n");
+    newch = &channel_incoming;
+    endch = &channel_ended;
+    ports = GNUNET_malloc (sizeof (uint32_t) * 2);
+    ports[0] = listen_port;
+  }
+  else if (NULL != peer_id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n");
+    GNUNET_SCHEDULER_add_now (&show_peer, NULL);
+  }
+  else if (NULL != tunnel_id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n");
+    GNUNET_SCHEDULER_add_now (&show_tunnel, NULL);
+  }
+  else if (NULL != channel_id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n");
+    GNUNET_SCHEDULER_add_now (&show_channel, NULL);
+  }
+  else if (NULL != conn_id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n");
+    GNUNET_SCHEDULER_add_now (&show_connection, NULL);
+  }
+  else if (GNUNET_YES == request_peers)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n");
+    GNUNET_SCHEDULER_add_now (&get_peers, NULL);
+  }
+  else if (GNUNET_YES == request_tunnels)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n");
+    GNUNET_SCHEDULER_add_now (&get_tunnels, NULL);
+  }
+  else
+  {
+    FPRINTF (stderr, "No action requested\n");
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to cadet\n");
+  mh = GNUNET_CADET_connect (cfg,
+                            NULL, /* cls */
+                            newch, /* new channel */
+                            endch, /* cleaner */
+                            handlers,
+                            ports);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done\n");
+  if (NULL == mh)
+    GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
+  else
+    sd = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       shutdown_task, NULL);
+
+}
+
+
+/**
+ * The main function to obtain peer information.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  int res;
+  const char helpstr[] = "Create channels and retreive info about cadets 
status.";
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+//     {'a', "channel", "TUNNEL_ID:CHANNEL_ID",
+//      gettext_noop ("provide information about a particular channel"),
+//      GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id},
+    {'C', "connection", "CONNECTION_ID",
+     gettext_noop ("provide information about a particular connection"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id},
+    {'e', "echo", NULL,
+     gettext_noop ("activate echo mode"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &echo},
+//     {'m', "monitor", NULL,
+//      gettext_noop ("provide information about all events (continuously)"),
+//      GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_mode},
+    {'o', "open-port", NULL,
+     gettext_noop ("port to listen to (default; 0)"),
+     GNUNET_YES, &GNUNET_GETOPT_set_uint, &listen_port},
+    {'p', "peer", "PEER_ID",
+     gettext_noop ("provide information about a patricular peer"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id},
+    {'P', "peers", NULL,
+      gettext_noop ("provide information about all peers"),
+      GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers},
+    {'t', "tunnel", "TUNNEL_ID",
+     gettext_noop ("provide information about a particular tunnel"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id},
+    {'T', "tunnels", NULL,
+     gettext_noop ("provide information about all tunnels"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels},
+
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  monitor_connections = GNUNET_NO;
+
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+
+  res = GNUNET_PROGRAM_run (argc, argv, "gnunet-cadet (OPTIONS | TARGET PORT)",
+                            gettext_noop (helpstr),
+                            options, &run, NULL);
+
+  GNUNET_free ((void *) argv);
+
+  if (GNUNET_OK == res)
+    return 0;
+  else
+    return 1;
+}
+
+/* end of gnunet-cadet.c */

Copied: gnunet/src/cadet/gnunet-service-cadet.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet.c                             (rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet.c     2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,181 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001-2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet.c
+ * @brief GNUnet CADET service with encryption
+ * @author Bartlomiej Polot
+ *
+ *  FIXME in progress:
+ * - rekey - reliability interaction
+ * - channel retransmit timing
+ *
+ * TODO:
+ * - relay corking down to core
+ * - set ttl relative to path length
+ * TODO END
+ *
+ * Dictionary:
+ * - peer: other cadet 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 "cadet.h"
+#include "gnunet_statistics_service.h"
+
+#include "gnunet-service-cadet_local.h"
+#include "gnunet-service-cadet_channel.h"
+#include "gnunet-service-cadet_connection.h"
+#include "gnunet-service-cadet_tunnel.h"
+#include "gnunet-service-cadet_dht.h"
+#include "gnunet-service-cadet_peer.h"
+#include "gnunet-service-cadet_hello.h"
+
+
+/******************************************************************************/
+/***********************      GLOBAL VARIABLES     
****************************/
+/******************************************************************************/
+
+/****************************** Global variables 
******************************/
+
+/**
+ * Handle to the statistics service.
+ */
+struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Local peer own ID (memory efficient handle).
+ */
+GNUNET_PEER_Id myid;
+
+/**
+ * Local peer own ID (full value).
+ */
+struct GNUNET_PeerIdentity my_full_id;
+
+
+/**
+ * Signal that shutdown is happening: prevent recover measures.
+ */
+int shutting_down;
+
+/*************************** Static global variables 
**************************/
+
+/**
+ * Own private key.
+ */
+static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
+
+
+/******************************************************************************/
+/************************      MAIN FUNCTIONS      
****************************/
+/******************************************************************************/
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
+
+  shutting_down = GNUNET_YES;
+
+  GML_shutdown ();
+  GMH_shutdown ();
+  GMC_shutdown ();
+  GMT_shutdown ();
+  GMD_shutdown ();
+  GMP_shutdown ();
+
+  GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+  stats = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
+}
+
+
+/**
+ * Process cadet requests.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls, struct GNUNET_SERVER_Handle *server,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
+
+  stats = GNUNET_STATISTICS_create ("cadet", 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");
+  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,
+              "STARTING SERVICE (CADET) for peer [%s]\n",
+              GNUNET_i2s (&my_full_id));
+
+  GML_init (server);    /* Local clients */
+  GMH_init (c);         /* Hellos */
+  GMC_init (c);         /* Connections */
+  GMP_init (c);         /* Peers */
+  GMD_init (c);         /* DHT */
+  GMT_init (c, my_private_key); /* Tunnels */
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cadet service running\n");
+}
+
+
+/**
+ * The main function for the cadet service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  int ret;
+  int r;
+
+  shutting_down = GNUNET_NO;
+  r = GNUNET_SERVICE_run (argc, argv, "cadet", GNUNET_SERVICE_OPTION_NONE, 
&run,
+                          NULL);
+  GNUNET_free (my_private_key);
+  ret = (GNUNET_OK == r) ? 0 : 1;
+
+  return ret;
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_channel.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_channel.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_channel.c                             
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_channel.c     2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,2432 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_statistics_service.h"
+
+#include "cadet.h"
+#include "cadet_protocol.h"
+
+#include "gnunet-service-cadet_channel.h"
+#include "gnunet-service-cadet_local.h"
+#include "gnunet-service-cadet_tunnel.h"
+#include "gnunet-service-cadet_peer.h"
+
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__)
+
+#define CADET_RETRANSMIT_TIME    GNUNET_TIME_relative_multiply(\
+                                    GNUNET_TIME_UNIT_MILLISECONDS, 250)
+#define CADET_RETRANSMIT_MARGIN  4
+
+
+/**
+ * All the states a connection can be in.
+ */
+enum CadetChannelState
+{
+  /**
+   * Uninitialized status, should never appear in operation.
+   */
+  CADET_CHANNEL_NEW,
+
+  /**
+   * Connection create message sent, waiting for ACK.
+   */
+  CADET_CHANNEL_SENT,
+
+  /**
+   * Connection confirmed, ready to carry traffic.
+   */
+  CADET_CHANNEL_READY,
+};
+
+
+/**
+ * Info holder for channel messages in queues.
+ */
+struct CadetChannelQueue
+{
+  /**
+   * Tunnel Queue.
+   */
+  struct CadetTunnel3Queue *tq;
+
+  /**
+   * Message type (DATA/DATA_ACK)
+   */
+  uint16_t type;
+
+  /**
+   * Message copy (for DATAs, to start retransmission timer)
+   */
+  struct CadetReliableMessage *copy;
+
+  /**
+   * Reliability (for DATA_ACKs, to access rel->ack_q)
+   */
+  struct CadetChannelReliability *rel;
+};
+
+
+/**
+ * Info needed to retry a message in case it gets lost.
+ */
+struct CadetReliableMessage
+{
+    /**
+     * Double linked list, FIFO style
+     */
+  struct CadetReliableMessage    *next;
+  struct CadetReliableMessage    *prev;
+
+    /**
+     * Type of message (payload, channel management).
+     */
+  int16_t type;
+
+    /**
+     * Tunnel Reliability queue this message is in.
+     */
+  struct CadetChannelReliability  *rel;
+
+    /**
+     * ID of the message (ACK needed to free)
+     */
+  uint32_t                      mid;
+
+  /**
+   * Tunnel Queue.
+   */
+  struct CadetChannelQueue       *chq;
+
+    /**
+     * When was this message issued (to calculate ACK delay)
+     */
+  struct GNUNET_TIME_Absolute   timestamp;
+
+  /* struct GNUNET_CADET_Data with payload */
+};
+
+
+/**
+ * Info about the traffic state for a client in a channel.
+ */
+struct CadetChannelReliability
+{
+    /**
+     * Channel this is about.
+     */
+  struct CadetChannel *ch;
+
+    /**
+     * DLL of messages sent and not yet ACK'd.
+     */
+  struct CadetReliableMessage        *head_sent;
+  struct CadetReliableMessage        *tail_sent;
+
+    /**
+     * DLL of messages received out of order.
+     */
+  struct CadetReliableMessage        *head_recv;
+  struct CadetReliableMessage        *tail_recv;
+
+    /**
+     * Messages received.
+     */
+  unsigned int                      n_recv;
+
+    /**
+     * Next MID to use for outgoing traffic.
+     */
+  uint32_t                          mid_send;
+
+    /**
+     * Next MID expected for incoming traffic.
+     */
+  uint32_t                          mid_recv;
+
+    /**
+     * Handle for queued unique data CREATE, DATA_ACK.
+     */
+  struct CadetChannelQueue           *uniq;
+
+    /**
+     * Can we send data to the client?
+     */
+  int                               client_ready;
+
+  /**
+   * Can the client send data to us?
+   */
+  int                               client_allowed;
+
+    /**
+     * Task to resend/poll in case no ACK is received.
+     */
+  GNUNET_SCHEDULER_TaskIdentifier   retry_task;
+
+    /**
+     * Counter for exponential backoff.
+     */
+  struct GNUNET_TIME_Relative       retry_timer;
+
+    /**
+     * How long does it usually take to get an ACK.
+     */
+  struct GNUNET_TIME_Relative       expected_delay;
+};
+
+
+/**
+ * Struct containing all information regarding a channel to a remote client.
+ */
+struct CadetChannel
+{
+    /**
+     * Tunnel this channel is in.
+     */
+  struct CadetTunnel3 *t;
+
+    /**
+     * Destination port of the channel.
+     */
+  uint32_t port;
+
+    /**
+     * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+     */
+  CADET_ChannelNumber gid;
+
+    /**
+     * Local tunnel number for root (owner) client.
+     * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
+     */
+  CADET_ChannelNumber lid_root;
+
+    /**
+     * Local tunnel number for local destination clients (incoming number)
+     * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0).
+     */
+  CADET_ChannelNumber lid_dest;
+
+    /**
+     * Channel state.
+     */
+  enum CadetChannelState state;
+
+    /**
+     * Is the tunnel bufferless (minimum latency)?
+     */
+  int nobuffer;
+
+    /**
+     * Is the tunnel reliable?
+     */
+  int reliable;
+
+    /**
+     * Last time the channel was used
+     */
+  struct GNUNET_TIME_Absolute timestamp;
+
+    /**
+     * Client owner of the tunnel, if any
+     */
+  struct CadetClient *root;
+
+    /**
+     * Client destination of the tunnel, if any.
+     */
+  struct CadetClient *dest;
+
+    /**
+     * Flag to signal the destruction of the channel.
+     * If this is set GNUNET_YES the channel will be destroyed
+     * when the queue is empty.
+     */
+  int destroy;
+
+    /**
+     * Total (reliable) messages pending ACK for this channel.
+     */
+  unsigned int pending_messages;
+
+    /**
+     * Reliability data.
+     * Only present (non-NULL) at the owner of a tunnel.
+     */
+  struct CadetChannelReliability *root_rel;
+
+    /**
+     * Reliability data.
+     * Only present (non-NULL) at the destination of a tunnel.
+     */
+  struct CadetChannelReliability *dest_rel;
+
+};
+
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Local peer own ID (memory efficient handle).
+ */
+extern GNUNET_PEER_Id myid;
+
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+/**
+ * Destroy a reliable message after it has been acknowledged, either by
+ * direct mid ACK or bitfield. Updates the appropriate data structures and
+ * timers and frees all memory.
+ *
+ * @param copy Message that is no longer needed: remote peer got it.
+ * @param update_time Is the timing information relevant?
+ *                    If this message is ACK in a batch the timing information
+ *                    is skewed by the retransmission, count only for the
+ *                    retransmitted message.
+ */
+static int
+rel_message_free (struct CadetReliableMessage *copy, int update_time);
+
+/**
+ * send a channel create message.
+ *
+ * @param ch Channel for which to send.
+ */
+static void
+send_create (struct CadetChannel *ch);
+
+/**
+ * Confirm we got a channel create, FWD ack.
+ *
+ * @param ch The channel to confirm.
+ * @param fwd Should we send a FWD ACK? (going dest->root)
+ * @param reaction This ACK is a reaction to a duplicate CREATE, don't save.
+ */
+static void
+send_ack (struct CadetChannel *ch, int fwd, int reaction);
+
+
+
+/**
+ * Test if the channel is loopback: both root and dest are on the local peer.
+ *
+ * @param ch Channel to test.
+ *
+ * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise.
+ */
+static int
+is_loopback (const struct CadetChannel *ch)
+{
+  if (NULL != ch->t)
+    return GMT_is_loopback (ch->t);
+
+  return (NULL != ch->root && NULL != ch->dest);
+}
+
+
+/**
+ * Save a copy of the data message for later retransmission.
+ *
+ * @param msg Message to copy.
+ * @param mid Message ID.
+ * @param rel Reliability data for retransmission.
+ */
+static struct CadetReliableMessage *
+copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
+              struct CadetChannelReliability *rel)
+{
+  struct CadetReliableMessage *copy;
+  uint16_t size;
+
+  size = ntohs (msg->header.size);
+  copy = GNUNET_malloc (sizeof (*copy) + size);
+  copy->mid = mid;
+  copy->rel = rel;
+  copy->type = GNUNET_MESSAGE_TYPE_CADET_DATA;
+  memcpy (&copy[1], msg, size);
+
+  return copy;
+}
+
+/**
+ * We have received a message out of order, or the client is not ready.
+ * Buffer it until we receive an ACK from the client or the missing
+ * message from the channel.
+ *
+ * @param msg Message to buffer (MUST be of type CADET_DATA).
+ * @param rel Reliability data to the corresponding direction.
+ */
+static void
+add_buffered_data (const struct GNUNET_CADET_Data *msg,
+                   struct CadetChannelReliability *rel)
+{
+  struct CadetReliableMessage *copy;
+  struct CadetReliableMessage *prev;
+  uint32_t mid;
+
+  mid = ntohl (msg->mid);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data %u\n", mid);
+
+  rel->n_recv++;
+
+  // FIXME do something better than O(n), although n < 64...
+  // FIXME start from the end (most messages are the latest ones)
+  for (prev = rel->head_recv; NULL != prev; prev = prev->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid);
+    if (prev->mid == mid)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n");
+      return;
+    }
+    else if (GM_is_pid_bigger (prev->mid, mid))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n");
+      copy = copy_message (msg, mid, rel);
+      GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv,
+                                          prev, copy);
+      return;
+    }
+  }
+  copy = copy_message (msg, mid, rel);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail!\n");
+  GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n");
+}
+
+
+/**
+ * Add a destination client to a channel, initializing all data structures
+ * in the channel and the client.
+ *
+ * @param ch Channel to which add the destination.
+ * @param c Client which to add to the channel.
+ */
+static void
+add_destination (struct CadetChannel *ch, struct CadetClient *c)
+{
+  if (NULL != ch->dest)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Assign local id as destination */
+  ch->lid_dest = GML_get_next_chid (c);
+
+  /* Store in client's hashmap */
+  GML_channel_add (c, ch->lid_dest, ch);
+
+  GNUNET_break (NULL == ch->dest_rel);
+  ch->dest_rel = GNUNET_new (struct CadetChannelReliability);
+  ch->dest_rel->ch = ch;
+  ch->dest_rel->expected_delay.rel_value_us = 0;
+  ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME;
+
+  ch->dest = c;
+}
+
+
+/**
+ * Set options in a channel, extracted from a bit flag field.
+ *
+ * @param ch Channel to set options to.
+ * @param options Bit array in host byte order.
+ */
+static void
+channel_set_options (struct CadetChannel *ch, uint32_t options)
+{
+  ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ?
+  GNUNET_YES : GNUNET_NO;
+  ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ?
+  GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
+ * Get a bit flag field with the options of a channel.
+ *
+ * @param ch Channel to get options from.
+ *
+ * @return Bit array in host byte order.
+ */
+static uint32_t
+channel_get_options (struct CadetChannel *ch)
+{
+  uint32_t options;
+
+  options = 0;
+  if (ch->nobuffer)
+    options |= GNUNET_CADET_OPTION_NOBUFFER;
+  if (ch->reliable)
+    options |= GNUNET_CADET_OPTION_RELIABLE;
+
+  return options;
+}
+
+
+/**
+ * Notify a client that the channel is no longer valid.
+ *
+ * @param ch Channel that is destroyed.
+ * @param local_only Should we avoid sending it to other peers?
+ */
+static void
+send_destroy (struct CadetChannel *ch, int local_only)
+{
+  struct GNUNET_CADET_ChannelManage msg;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
+  msg.header.size = htons (sizeof (msg));
+  msg.chid = htonl (ch->gid);
+
+  /* If root is not NULL, notify.
+   * If it's NULL, check lid_root. When a local destroy comes in, root
+   * is set to NULL but lid_root is left untouched. In this case, do nothing,
+   * the client is the one who requested the channel to be destroyed.
+   */
+  if (NULL != ch->root)
+    GML_send_channel_destroy (ch->root, ch->lid_root);
+  else if (0 == ch->lid_root && GNUNET_NO == local_only)
+    GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
+
+  if (NULL != ch->dest)
+    GML_send_channel_destroy (ch->dest, ch->lid_dest);
+  else if (0 == ch->lid_dest && GNUNET_NO == local_only)
+    GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL);
+}
+
+
+/**
+ * Notify the destination client that a new incoming channel was created.
+ *
+ * @param ch Channel that was created.
+ */
+static void
+send_client_create (struct CadetChannel *ch)
+{
+  uint32_t opt;
+
+  if (NULL == ch->dest)
+    return;
+
+  opt = 0;
+  opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
+  opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
+  GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt,
+                           GMT_get_destination (ch->t));
+
+}
+
+
+/**
+ * Send data to a client.
+ *
+ * If the client is ready, send directly, otherwise buffer while listening
+ * for a local ACK.
+ *
+ * @param ch Channel
+ * @param msg Message.
+ * @param fwd Is this a fwd (root->dest) message?
+ */
+static void
+send_client_data (struct CadetChannel *ch,
+                  const struct GNUNET_CADET_Data *msg,
+                  int fwd)
+{
+  if (fwd)
+  {
+    if (ch->dest_rel->client_ready)
+      GML_send_data (ch->dest, msg, ch->lid_dest);
+    else
+      add_buffered_data (msg, ch->dest_rel);
+  }
+  else
+  {
+    if (ch->root_rel->client_ready)
+      GML_send_data (ch->root, msg, ch->lid_root);
+    else
+      add_buffered_data (msg, ch->root_rel);
+  }
+}
+
+
+/**
+ * Send a buffered message to the client, for in order delivery or
+ * as result of client ACK.
+ *
+ * @param ch Channel on which to empty the message buffer.
+ * @param c Client to send to.
+ * @param fwd Is this to send FWD data?.
+ */
+static void
+send_client_buffered_data (struct CadetChannel *ch,
+                           struct CadetClient *c,
+                           int fwd)
+{
+  struct CadetReliableMessage *copy;
+  struct CadetChannelReliability *rel;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n");
+  rel = fwd ? ch->dest_rel : ch->root_rel;
+  if (GNUNET_NO == rel->client_ready)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n");
+    return;
+  }
+
+  copy = rel->head_recv;
+  /* We never buffer channel management messages */
+  if (NULL != copy)
+  {
+    if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
+    {
+      struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) &copy[1];
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           " have %u! now expecting %u\n",
+           copy->mid, rel->mid_recv + 1);
+      send_client_data (ch, msg, fwd);
+      rel->n_recv--;
+      rel->mid_recv++;
+      GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE RECV %p\n", copy);
+      GNUNET_free (copy);
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           " reliable && don't have %u, next is %u\n",
+           rel->mid_recv,
+           copy->mid);
+      if (GNUNET_YES == ch->destroy)
+      {
+        /* We don't have the next data piece and the remote peer has closed the
+         * channel. We won't receive it anymore, so just destroy the channel.
+         * FIXME: wait some time to allow other connections to
+         *        deliver missing messages
+         */
+        send_destroy (ch, GNUNET_YES);
+        GMCH_destroy (ch);
+      }
+    }
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n");
+}
+
+
+/**
+ * Allow a client to send more data.
+ *
+ * In case the client was already allowed to send data, do nothing.
+ *
+ * @param ch Channel.
+ * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root)
+ */
+static void
+send_client_ack (struct CadetChannel *ch, int fwd)
+{
+  struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel;
+  struct CadetClient *c = fwd ? ch->root : ch->dest;
+
+  if (NULL == c)
+  {
+    GNUNET_break (GNUNET_NO != ch->destroy);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  sending %s ack to client on channel %s\n",
+       GM_f2s (fwd), GMCH_2s (ch));
+
+  if (NULL == rel)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  if (GNUNET_YES == rel->client_allowed)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  already allowed\n");
+    return;
+  }
+  rel->client_allowed = GNUNET_YES;
+
+  GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest);
+}
+
+
+/**
+ * Notify the root that the destination rejected the channel.
+ *
+ * @param ch Rejected channel.
+ */
+static void
+send_client_nack (struct CadetChannel *ch)
+{
+  if (NULL == ch->root)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  GML_send_channel_nack (ch->root, ch->lid_root);
+}
+
+
+/**
+ * We haven't received an ACK after a certain time: restransmit the message.
+ *
+ * @param cls Closure (CadetChannelReliability with the message to restransmit)
+ * @param tc TaskContext.
+ */
+static void
+channel_retransmit_message (void *cls,
+                            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetChannelReliability *rel = cls;
+  struct CadetReliableMessage *copy;
+  struct CadetChannel *ch;
+  struct GNUNET_CADET_Data *payload;
+  int fwd;
+
+  rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  ch = rel->ch;
+  copy = rel->head_sent;
+  if (NULL == copy)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  payload = (struct GNUNET_CADET_Data *) &copy[1];
+  fwd = (rel == ch->root_rel);
+
+  /* Message not found in the queue that we are going to use. */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid);
+
+  GMCH_send_prebuilt_message (&payload->header, ch, fwd, copy);
+  GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
+}
+
+
+/**
+ * We haven't received an Channel ACK after a certain time: resend the CREATE.
+ *
+ * @param cls Closure (CadetChannelReliability of the channel to recreate)
+ * @param tc TaskContext.
+ */
+static void
+channel_recreate (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetChannelReliability *rel = cls;
+
+  rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RE-CREATE\n");
+  GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
+
+  if (rel == rel->ch->root_rel)
+  {
+    send_create (rel->ch);
+  }
+  else if (rel == rel->ch->dest_rel)
+  {
+    send_ack (rel->ch, GNUNET_YES, GNUNET_NO);
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+
+}
+
+
+/**
+ * Message has been sent: start retransmission timer.
+ *
+ * @param cls Closure (queue structure).
+ * @param t Tunnel.
+ * @param q Queue handler (no longer valid).
+ * @param type Type of message.
+ * @param size Size of the message.
+ */
+static void
+ch_message_sent (void *cls,
+                 struct CadetTunnel3 *t,
+                 struct CadetTunnel3Queue *q,
+                 uint16_t type, size_t size)
+{
+  struct CadetChannelQueue *chq = cls;
+  struct CadetReliableMessage *copy = chq->copy;
+  struct CadetChannelReliability *rel;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "channel message sent callback %s\n",
+       GM_m2s (chq->type));
+
+  switch (chq->type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT DATA MID %u\n", copy->mid);
+      GNUNET_assert (chq == copy->chq);
+      copy->timestamp = GNUNET_TIME_absolute_get ();
+      rel = copy->rel;
+      if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task)
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "!! scheduling retry in 4 * %s\n",
+             GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
+                                                     GNUNET_YES));
+        if (0 != rel->expected_delay.rel_value_us)
+        {
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay != 0\n");
+          rel->retry_timer =
+          GNUNET_TIME_relative_multiply (rel->expected_delay,
+                                         CADET_RETRANSMIT_MARGIN);
+        }
+        else
+        {
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay reset\n");
+          rel->retry_timer = CADET_RETRANSMIT_TIME;
+        }
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "!! using delay %s\n",
+             GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
+                                                     GNUNET_NO));
+        rel->retry_task =
+            GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
+                                          &channel_retransmit_message, rel);
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "!! retry task %u\n", rel->retry_task);
+      }
+      copy->chq = NULL;
+      break;
+
+
+    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT %s\n", GM_m2s (chq->type));
+      rel = chq->rel;
+      GNUNET_assert (rel->uniq == chq);
+      rel->uniq = NULL;
+
+      if (CADET_CHANNEL_READY != rel->ch->state
+          && GNUNET_MESSAGE_TYPE_CADET_DATA_ACK != type
+          && GNUNET_NO == rel->ch->destroy)
+      {
+        GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rel->retry_task);
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! STD BACKOFF %s\n",
+             GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
+                                                     GNUNET_NO));
+        rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
+        rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
+                                                        &channel_recreate, 
rel);
+      }
+      break;
+
+    default:
+      GNUNET_break (0);
+  }
+
+  GNUNET_free (chq);
+}
+
+
+/**
+ * send a channel create message.
+ *
+ * @param ch Channel for which to send.
+ */
+static void
+send_create (struct CadetChannel *ch)
+{
+  struct GNUNET_CADET_ChannelCreate msgcc;
+
+  msgcc.header.size = htons (sizeof (msgcc));
+  msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
+  msgcc.chid = htonl (ch->gid);
+  msgcc.port = htonl (ch->port);
+  msgcc.opt = htonl (channel_get_options (ch));
+
+  GMCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL);
+}
+
+
+/**
+ * Confirm we got a channel create or FWD ack.
+ *
+ * @param ch The channel to confirm.
+ * @param fwd Should we send a FWD ACK? (going dest->root)
+ * @param reaction This ACK is a reaction to a duplicate CREATE, don't save.
+ */
+static void
+send_ack (struct CadetChannel *ch, int fwd, int reaction)
+{
+  struct GNUNET_CADET_ChannelManage msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending channel %s ack for channel %s\n",
+       GM_f2s (fwd), GMCH_2s (ch));
+
+  msg.chid = htonl (ch->gid);
+  GMCH_send_prebuilt_message (&msg.header, ch, !fwd, reaction ? &msg : NULL);
+}
+
+
+/**
+ * Send a message and don't keep any info about it: we won't need to cancel it
+ * or resend it.
+ *
+ * @param msg Header of the message to fire away.
+ * @param ch Channel on which the message should go.
+ * @param force Is this a forced (undroppable) message?
+ */
+static void
+fire_and_forget (const struct GNUNET_MessageHeader *msg,
+                 struct CadetChannel *ch,
+                 int force)
+{
+  GNUNET_break (NULL == GMT_send_prebuilt_message (msg, ch->t, NULL,
+                                                   force, NULL, NULL));
+}
+
+
+/**
+ * Notify that a channel create didn't succeed.
+ *
+ * @param ch The channel to reject.
+ */
+static void
+send_nack (struct CadetChannel *ch)
+{
+  struct GNUNET_CADET_ChannelManage msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  sending channel NACK for channel %s\n",
+       GMCH_2s (ch));
+
+  msg.chid = htonl (ch->gid);
+  GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
+}
+
+
+/**
+ * Destroy all reliable messages queued for a channel,
+ * during a channel destruction.
+ * Frees the reliability structure itself.
+ *
+ * @param rel Reliability data for a channel.
+ */
+static void
+channel_rel_free_all (struct CadetChannelReliability *rel)
+{
+  struct CadetReliableMessage *copy;
+  struct CadetReliableMessage *next;
+
+  if (NULL == rel)
+    return;
+
+  for (copy = rel->head_recv; NULL != copy; copy = next)
+  {
+    next = copy->next;
+    GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH RECV %p\n", copy);
+    GNUNET_break (NULL == copy->chq);
+    GNUNET_free (copy);
+  }
+  for (copy = rel->head_sent; NULL != copy; copy = next)
+  {
+    next = copy->next;
+    GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH %p\n", copy);
+    if (NULL != copy->chq)
+    {
+      if (NULL != copy->chq->tq)
+      {
+        GMT_cancel (copy->chq->tq);
+        /* ch_message_sent will free copy->q */
+      }
+      else
+      {
+        GNUNET_free (copy->chq);
+        GNUNET_break (0);
+      }
+    }
+    GNUNET_free (copy);
+  }
+  if (NULL != rel->uniq && NULL != rel->uniq->tq)
+  {
+    GMT_cancel (rel->uniq->tq);
+    /* ch_message_sent is called freeing uniq */
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (rel->retry_task);
+    rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_free (rel);
+}
+
+
+/**
+ * Mark future messages as ACK'd.
+ *
+ * @param rel Reliability data.
+ * @param msg DataACK message with a bitfield of future ACK'd messages.
+ */
+static void
+channel_rel_free_sent (struct CadetChannelReliability *rel,
+                       const struct GNUNET_CADET_DataACK *msg)
+{
+  struct CadetReliableMessage *copy;
+  struct CadetReliableMessage *next;
+  uint64_t bitfield;
+  uint64_t mask;
+  uint32_t mid;
+  uint32_t target;
+  unsigned int i;
+
+  bitfield = msg->futures;
+  mid = ntohl (msg->mid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+              "!!! free_sent_reliable %u %llX\n",
+              mid, bitfield);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+              " rel %p, head %p\n",
+              rel, rel->head_sent);
+  for (i = 0, copy = rel->head_sent;
+       i < 64 && NULL != copy && 0 != bitfield;
+       i++)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+                " trying bit %u (mid %u)\n",
+                i, mid + i + 1);
+    mask = 0x1LL << i;
+    if (0 == (bitfield & mask))
+     continue;
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n");
+    /* Bit was set, clear the bit from the bitfield */
+    bitfield &= ~mask;
+
+    /* The i-th bit was set. Do we have that copy? */
+    /* Skip copies with mid < target */
+    target = mid + i + 1;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target);
+    while (NULL != copy && GM_is_pid_bigger (target, copy->mid))
+      copy = copy->next;
+
+    /* Did we run out of copies? (previously freed, it's ok) */
+    if (NULL == copy)
+    {
+     LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n");
+     return;
+    }
+
+    /* Did we overshoot the target? (previously freed, it's ok) */
+    if (GM_is_pid_bigger (copy->mid, target))
+    {
+     LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid);
+     continue;
+    }
+
+    /* Now copy->mid == target, free it */
+    next = copy->next;
+    GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES));
+    copy = next;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n");
+}
+
+
+/**
+ * Destroy a reliable message after it has been acknowledged, either by
+ * direct mid ACK or bitfield. Updates the appropriate data structures and
+ * timers and frees all memory.
+ *
+ * @param copy Message that is no longer needed: remote peer got it.
+ * @param update_time Is the timing information relevant?
+ *                    If this message is ACK in a batch the timing information
+ *                    is skewed by the retransmission, count only for the
+ *                    retransmitted message.
+ *
+ * @return #GNUNET_YES if channel was destroyed as a result of the call,
+ *         #GNUNET_NO otherwise.
+ */
+static int
+rel_message_free (struct CadetReliableMessage *copy, int update_time)
+{
+  struct CadetChannelReliability *rel;
+  struct GNUNET_TIME_Relative time;
+
+  rel = copy->rel;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid);
+  if (update_time)
+  {
+    time = GNUNET_TIME_absolute_get_duration (copy->timestamp);
+    if (0 == rel->expected_delay.rel_value_us)
+      rel->expected_delay = time;
+    else
+    {
+      rel->expected_delay.rel_value_us *= 7;
+      rel->expected_delay.rel_value_us += time.rel_value_us;
+      rel->expected_delay.rel_value_us /= 8;
+    }
+    LOG (GNUNET_ERROR_TYPE_INFO, "!!!  took %s, new delay %s\n",
+         GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO),
+         GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
+                                                 GNUNET_NO));
+    rel->retry_timer = rel->expected_delay;
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO, "!!! batch free, ignoring timing\n");
+  }
+  rel->ch->pending_messages--;
+  if (NULL != copy->chq)
+  {
+    GMT_cancel (copy->chq->tq);
+    /* copy->q is set to NULL by ch_message_sent */
+  }
+  GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE %p\n", copy);
+  GNUNET_free (copy);
+
+  if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages)
+  {
+    GMCH_destroy (rel->ch);
+    return GNUNET_YES;
+  }
+  return GNUNET_NO;
+}
+
+
+/**
+ * Channel was ACK'd by remote peer, mark as ready and cancel retransmission.
+ *
+ * @param ch Channel to mark as ready.
+ * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK)
+ */
+static void
+channel_confirm (struct CadetChannel *ch, int fwd)
+{
+  struct CadetChannelReliability *rel;
+  enum CadetChannelState oldstate;
+
+  rel = fwd ? ch->root_rel : ch->dest_rel;
+  if (NULL == rel)
+  {
+    GNUNET_break (GNUNET_NO != ch->destroy);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  channel confirm %s %s\n",
+       GM_f2s (fwd), GMCH_2s (ch));
+  oldstate = ch->state;
+  ch->state = CADET_CHANNEL_READY;
+
+  if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch))
+  {
+    rel->client_ready = GNUNET_YES;
+    rel->expected_delay = rel->retry_timer;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  !! retry timer confirm %s\n",
+         GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO));
+    if (GMT_get_connections_buffer (ch->t) > 0 || GMT_is_loopback (ch->t))
+      send_client_ack (ch, fwd);
+
+    if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
+    {
+      GNUNET_SCHEDULER_cancel (rel->retry_task);
+      rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+    else if (NULL != rel->uniq)
+    {
+      GMT_cancel (rel->uniq->tq);
+      /* ch_message_sent will free and NULL uniq */
+    }
+    else
+    {
+      if (GNUNET_NO == is_loopback (ch))
+      {
+        /* We SHOULD have been trying to retransmit this! */
+        GNUNET_break (0);
+      }
+    }
+  }
+
+  /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */
+  if (GNUNET_YES == fwd)
+    send_ack (ch, GNUNET_NO, GNUNET_NO);
+}
+
+
+/**
+ * Save a copy to retransmit in case it gets lost.
+ *
+ * Initializes all needed callbacks and timers.
+ *
+ * @param ch Channel this message goes on.
+ * @param msg Message to copy.
+ * @param fwd Is this fwd traffic?
+ */
+static struct CadetReliableMessage *
+channel_save_copy (struct CadetChannel *ch,
+                   const struct GNUNET_MessageHeader *msg,
+                   int fwd)
+{
+  struct CadetChannelReliability *rel;
+  struct CadetReliableMessage *copy;
+  uint32_t mid;
+  uint16_t type;
+  uint16_t size;
+
+  rel = fwd ? ch->root_rel : ch->dest_rel;
+  mid = rel->mid_send - 1;
+  type = ntohs (msg->type);
+  size = ntohs (msg->size);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u %s\n", mid, GM_m2s (type));
+  copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", copy);
+  copy->mid = mid;
+  copy->rel = rel;
+  copy->type = type;
+  memcpy (&copy[1], msg, size);
+  GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
+  ch->pending_messages++;
+
+  return copy;
+}
+
+
+/**
+ * Create a new channel.
+ *
+ * @param t Tunnel this channel is in.
+ * @param owner Client that owns the channel, NULL for foreign channels.
+ * @param lid_root Local ID for root client.
+ *
+ * @return A new initialized channel. NULL on error.
+ */
+static struct CadetChannel *
+channel_new (struct CadetTunnel3 *t,
+             struct CadetClient *owner,
+             CADET_ChannelNumber lid_root)
+{
+  struct CadetChannel *ch;
+
+  ch = GNUNET_new (struct CadetChannel);
+  ch->root = owner;
+  ch->lid_root = lid_root;
+  ch->t = t;
+
+  GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
+
+  if (NULL != owner)
+  {
+    ch->gid = GMT_get_next_chid (t);
+    GML_channel_add (owner, lid_root, ch);
+  }
+  GMT_add_channel (t, ch);
+
+  return ch;
+}
+
+
+/**
+ * Handle a loopback message: call the appropriate handler for the message 
type.
+ *
+ * @param ch Channel this message is on.
+ * @param msgh Message header.
+ * @param fwd Is this FWD traffic?
+ */
+void
+handle_loopback (struct CadetChannel *ch,
+                 const struct GNUNET_MessageHeader *msgh,
+                 int fwd)
+{
+  uint16_t type;
+
+  type = ntohs (msgh->type);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Loopback %s %s message!\n",
+       GM_f2s (fwd), GM_m2s (type));
+
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+      /* Don't send hop ACK, wait for client to ACK */
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SEND loopback %u (%u)\n",
+           ntohl (((struct GNUNET_CADET_Data *) msgh)->mid), ntohs 
(msgh->size));
+      GMCH_handle_data (ch, (struct GNUNET_CADET_Data *) msgh, fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+      GMCH_handle_data_ack (ch, (struct GNUNET_CADET_DataACK *) msgh, fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+      GMCH_handle_create (ch->t,
+                          (struct GNUNET_CADET_ChannelCreate *) msgh);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+      GMCH_handle_ack (ch,
+                       (struct GNUNET_CADET_ChannelManage *) msgh,
+                       fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+      GMCH_handle_nack (ch);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+      GMCH_handle_destroy (ch,
+                           (struct GNUNET_CADET_ChannelManage *) msgh,
+                           fwd);
+      break;
+
+    default:
+      GNUNET_break_op (0);
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "end-to-end message not known (%u)\n",
+           ntohs (msgh->type));
+  }
+}
+
+
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Destroy a channel and free all resources.
+ *
+ * @param ch Channel to destroy.
+ */
+void
+GMCH_destroy (struct CadetChannel *ch)
+{
+  struct CadetClient *c;
+  struct CadetTunnel3 *t;
+
+  if (NULL == ch)
+    return;
+  if (2 == ch->destroy)
+    return; /* recursive call */
+  ch->destroy = 2;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n",
+              GMT_2s (ch->t), ch->gid);
+  GMCH_debug (ch);
+
+  c = ch->root;
+  if (NULL != c)
+  {
+    GML_channel_remove (c, ch->lid_root, ch);
+  }
+
+  c = ch->dest;
+  if (NULL != c)
+  {
+    GML_channel_remove (c, ch->lid_dest, ch);
+  }
+
+  channel_rel_free_all (ch->root_rel);
+  channel_rel_free_all (ch->dest_rel);
+
+  t = ch->t;
+  GMT_remove_channel (t, ch);
+  GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO);
+
+  GNUNET_free (ch);
+  GMT_destroy_if_empty (t);
+}
+
+
+/**
+ * Get the channel's public ID.
+ *
+ * @param ch Channel.
+ *
+ * @return ID used to identify the channel with the remote peer.
+ */
+CADET_ChannelNumber
+GMCH_get_id (const struct CadetChannel *ch)
+{
+  return ch->gid;
+}
+
+
+/**
+ * Get the channel tunnel.
+ *
+ * @param ch Channel to get the tunnel from.
+ *
+ * @return tunnel of the channel.
+ */
+struct CadetTunnel3 *
+GMCH_get_tunnel (const struct CadetChannel *ch)
+{
+  return ch->t;
+}
+
+
+/**
+ * Get free buffer space towards the client on a specific channel.
+ *
+ * @param ch Channel.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Free buffer space [0 - 64]
+ */
+unsigned int
+GMCH_get_buffer (struct CadetChannel *ch, int fwd)
+{
+  struct CadetChannelReliability *rel;
+
+  rel = fwd ? ch->dest_rel : ch->root_rel;
+
+  /* If rel is NULL it means that the end is not yet created,
+   * most probably is a loopback channel at the point of sending
+   * the ChannelCreate to itself.
+   */
+  if (NULL == rel)
+    return 64;
+
+  return (64 - rel->n_recv);
+}
+
+
+/**
+ * Get flow control status of end point: is client allow to send?
+ *
+ * @param ch Channel.
+ * @param fwd Is query about FWD traffic? (Request root status).
+ *
+ * @return #GNUNET_YES if client is allowed to send us data.
+ */
+int
+GMCH_get_allowed (struct CadetChannel *ch, int fwd)
+{
+  struct CadetChannelReliability *rel;
+
+  rel = fwd ? ch->root_rel : ch->dest_rel;
+
+  if (NULL == rel)
+  {
+    /* Probably shutting down: root/dest NULL'ed to mark disconnection */
+    GNUNET_break (GNUNET_NO != ch->destroy);
+    return 0;
+  }
+
+  return rel->client_allowed;
+}
+
+
+/**
+ * Is the root client for this channel on this peer?
+ *
+ * @param ch Channel.
+ * @param fwd Is this for fwd traffic?
+ *
+ * @return #GNUNET_YES in case it is.
+ */
+int
+GMCH_is_origin (struct CadetChannel *ch, int fwd)
+{
+  struct CadetClient *c;
+
+  c = fwd ? ch->root : ch->dest;
+  return NULL != c;
+}
+
+
+/**
+ * Is the destination client for this channel on this peer?
+ *
+ * @param ch Channel.
+ * @param fwd Is this for fwd traffic?
+ *
+ * @return #GNUNET_YES in case it is.
+ */
+int
+GMCH_is_terminal (struct CadetChannel *ch, int fwd)
+{
+  struct CadetClient *c;
+
+  c = fwd ? ch->dest : ch->root;
+  return NULL != c;
+}
+
+
+/**
+ * Send an end-to-end ACK message for the most recent in-sequence payload.
+ *
+ * If channel is not reliable, do nothing.
+ *
+ * @param ch Channel this is about.
+ * @param fwd Is for FWD traffic? (ACK dest->owner)
+ */
+void
+GMCH_send_data_ack (struct CadetChannel *ch, int fwd)
+{
+  struct GNUNET_CADET_DataACK msg;
+  struct CadetChannelReliability *rel;
+  struct CadetReliableMessage *copy;
+  unsigned int delta;
+  uint64_t mask;
+  uint32_t ack;
+
+  if (GNUNET_NO == ch->reliable)
+  {
+    return;
+  }
+  rel = fwd ? ch->dest_rel : ch->root_rel;
+  ack = rel->mid_recv - 1;
+  LOG (GNUNET_ERROR_TYPE_INFO, "===> DATA_ACK for %u\n", ack);
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK);
+  msg.header.size = htons (sizeof (msg));
+  msg.chid = htonl (ch->gid);
+  msg.futures = 0;
+  for (copy = rel->head_recv; NULL != copy; copy = copy->next)
+  {
+    if (copy->type != GNUNET_MESSAGE_TYPE_CADET_DATA)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "!!  Type %s, expected DATA\n",
+           GM_m2s (copy->type));
+      continue;
+    }
+    if (copy->mid == ack + 1)
+    {
+      ack++;
+      continue;
+    }
+    delta = copy->mid - (ack + 1);
+    if (63 < delta)
+      break;
+    mask = 0x1LL << delta;
+    msg.futures |= mask;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         " !! setting bit for %u (delta %u) (%llX) -> %llX\n",
+         copy->mid, delta, mask, msg.futures);
+  }
+  msg.mid = htonl (ack);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "!!! ACK for %u, futures %llX\n",
+       ack, msg.futures);
+
+  GMCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n");
+}
+
+
+/**
+ * Allow a client to send us more data, in case it was choked.
+ *
+ * @param ch Channel.
+ * @param fwd Is this about FWD traffic? (Root client).
+ */
+void
+GMCH_allow_client (struct CadetChannel *ch, int fwd)
+{
+  struct CadetChannelReliability *rel;
+  unsigned int buffer;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n");
+
+  if (CADET_CHANNEL_READY != ch->state)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n");
+    return;
+  }
+
+  if (GNUNET_YES == ch->reliable)
+  {
+    rel = fwd ? ch->root_rel : ch->dest_rel;
+    if (NULL == rel)
+    {
+      GNUNET_break (GNUNET_NO != ch->destroy);
+      return;
+    }
+    if (NULL != rel->head_sent)
+    {
+      if (64 <= rel->mid_send - rel->head_sent->mid)
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n");
+        return;
+      }
+      else
+        LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n",
+             rel->head_sent->mid, rel->mid_send);
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n");
+    }
+  }
+
+  if (is_loopback (ch))
+    buffer = GMCH_get_buffer (ch, fwd);
+  else
+    buffer = GMT_get_connections_buffer (ch->t);
+
+  if (0 == buffer)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n");
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer);
+  send_client_ack (ch, fwd);
+}
+
+
+/**
+ * Log channel info.
+ *
+ * @param ch Channel.
+ */
+void
+GMCH_debug (struct CadetChannel *ch)
+{
+  if (NULL == ch)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n");
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n",
+              GMT_2s (ch->t), ch->gid, ch);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  root %p/%p\n",
+              ch->root, ch->root_rel);
+  if (NULL != ch->root)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->root));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
+                ch->root_rel->client_ready ? "YES" : "NO");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_root);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  dest %p/%p\n",
+              ch->dest, ch->dest_rel);
+  if (NULL != ch->dest)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->dest));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
+                ch->dest_rel->client_ready ? "YES" : "NO");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_dest);
+  }
+}
+
+
+/**
+ * Handle an ACK given by a client.
+ *
+ * Mark client as ready and send him any buffered data we could have for him.
+ *
+ * @param ch Channel.
+ * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK)
+ */
+void
+GMCH_handle_local_ack (struct CadetChannel *ch, int fwd)
+{
+  struct CadetChannelReliability *rel;
+  struct CadetClient *c;
+
+  rel = fwd ? ch->dest_rel : ch->root_rel;
+  c   = fwd ? ch->dest     : ch->root;
+
+  rel->client_ready = GNUNET_YES;
+  send_client_buffered_data (ch, c, fwd);
+
+  if (GNUNET_YES == ch->destroy && 0 == rel->n_recv)
+  {
+    send_destroy (ch, GNUNET_YES);
+    GMCH_destroy (ch);
+  }
+  /* if loopback is marked for destruction, no need to ACK to the other peer,
+   * it requested the destruction and is already gone, therefore, else if.
+   */
+  else if (is_loopback (ch))
+  {
+    unsigned int buffer;
+
+    buffer = GMCH_get_buffer (ch, fwd);
+    if (0 < buffer)
+      GMCH_allow_client (ch, fwd);
+
+    return;
+  }
+  GMT_send_connection_acks (ch->t);
+}
+
+
+/**
+ * Handle data given by a client.
+ *
+ * Check whether the client is allowed to send in this tunnel, save if channel
+ * is reliable and send an ACK to the client if there is still buffer space
+ * in the tunnel.
+ *
+ * @param ch Channel.
+ * @param c Client which sent the data.
+ * @param message Message.
+ * @param fwd Is this a FWD data?
+ *
+ * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en 
error.
+ */
+int
+GMCH_handle_local_data (struct CadetChannel *ch,
+                        struct CadetClient *c,
+                        struct GNUNET_MessageHeader *message,
+                        int fwd)
+{
+  struct CadetChannelReliability *rel;
+  struct GNUNET_CADET_Data *payload;
+  size_t size = ntohs (message->size);
+  uint16_t p2p_size = sizeof(struct GNUNET_CADET_Data) + size;
+  unsigned char cbuf[p2p_size];
+
+  /* Is the client in the channel? */
+  if ( !( (fwd &&
+           ch->root == c)
+         ||
+          (!fwd &&
+           ch->dest == c) ) )
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+
+  rel = fwd ? ch->root_rel : ch->dest_rel;
+
+  if (GNUNET_NO == rel->client_allowed)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+
+  rel->client_allowed = GNUNET_NO;
+
+  /* Ok, everything is correct, send the message. */
+  payload = (struct GNUNET_CADET_Data *) cbuf;
+  payload->mid = htonl (rel->mid_send);
+  rel->mid_send++;
+  memcpy (&payload[1], message, size);
+  payload->header.size = htons (p2p_size);
+  payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA);
+  payload->chid = htonl (ch->gid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
+  GMCH_send_prebuilt_message (&payload->header, ch, fwd, NULL);
+
+  if (is_loopback (ch))
+  {
+    if (GMCH_get_buffer (ch, fwd) > 0)
+      GMCH_allow_client (ch, fwd);
+
+    return GNUNET_OK;
+  }
+
+  if (GMT_get_connections_buffer (ch->t) > 0)
+  {
+    GMCH_allow_client (ch, fwd);
+  }
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle a channel destroy requested by a client.
+ *
+ * Destroy the channel and the tunnel in case this was the last channel.
+ *
+ * @param ch Channel.
+ * @param c Client that requested the destruction (to avoid notifying him).
+ * @param is_root Is the request coming from root?
+ */
+void
+GMCH_handle_local_destroy (struct CadetChannel *ch,
+                           struct CadetClient *c,
+                           int is_root)
+{
+  ch->destroy = GNUNET_YES;
+  /* Cleanup after the tunnel */
+  if (GNUNET_NO == is_root && c == ch->dest)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c));
+    GML_client_delete_channel (c, ch, ch->lid_dest);
+    ch->dest = NULL;
+  }
+  if (GNUNET_YES == is_root && c == ch->root)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c));
+    GML_client_delete_channel (c, ch, ch->lid_root);
+    ch->root = NULL;
+  }
+
+  send_destroy (ch, GNUNET_NO);
+  if (0 == ch->pending_messages)
+    GMCH_destroy (ch);
+}
+
+
+/**
+ * Handle a channel create requested by a client.
+ *
+ * Create the channel and the tunnel in case this was the first0 channel.
+ *
+ * @param c Client that requested the creation (will be the root).
+ * @param msg Create Channel message.
+ *
+ * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise.
+ */
+int
+GMCH_handle_local_create (struct CadetClient *c,
+                          struct GNUNET_CADET_ChannelMessage *msg)
+{
+  struct CadetChannel *ch;
+  struct CadetTunnel3 *t;
+  struct CadetPeer *peer;
+  CADET_ChannelNumber chid;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s:%u\n",
+              GNUNET_i2s (&msg->peer), ntohl (msg->port));
+  chid = ntohl (msg->channel_id);
+
+  /* Sanity check for duplicate channel IDs */
+  if (NULL != GML_channel_get (c, chid))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  peer = GMP_get (&msg->peer);
+  GMP_add_tunnel (peer);
+  t = GMP_get_tunnel (peer);
+
+  if (GMP_get_short_id (peer) == myid)
+  {
+    GMT_change_cstate (t, CADET_TUNNEL3_READY);
+  }
+  else
+  {
+    /* FIXME change to a tunnel API, eliminate ch <-> peer connection */
+    GMP_connect (peer);
+  }
+
+  /* Create channel */
+  ch = channel_new (t, c, chid);
+  if (NULL == ch)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  ch->port = ntohl (msg->port);
+  channel_set_options (ch, ntohl (msg->opt));
+
+  /* In unreliable channels, we'll use the DLL to buffer BCK data */
+  ch->root_rel = GNUNET_new (struct CadetChannelReliability);
+  ch->root_rel->ch = ch;
+  ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME;
+  ch->root_rel->expected_delay.rel_value_us = 0;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GMCH_2s (ch));
+
+  send_create (ch);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handler for cadet network payload traffic.
+ *
+ * @param ch Channel for the message.
+ * @param msg Unencryted data message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_data (struct CadetChannel *ch,
+                  const struct GNUNET_CADET_Data *msg,
+                  int fwd)
+{
+  struct CadetChannelReliability *rel;
+  struct CadetClient *c;
+  uint32_t mid;
+
+  /* If this is a remote (non-loopback) channel, find 'fwd'. */
+  if (GNUNET_SYSERR == fwd)
+  {
+    if (is_loopback (ch))
+    {
+      /* It is a loopback channel after all... */
+      GNUNET_break (0);
+      return;
+    }
+    fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+  }
+
+  /*  Initialize FWD/BCK data */
+  c   = fwd ? ch->dest     : ch->root;
+  rel = fwd ? ch->dest_rel : ch->root_rel;
+
+  if (NULL == c)
+  {
+    GNUNET_break (GNUNET_NO != ch->destroy);
+    return;
+  }
+
+  if (CADET_CHANNEL_READY != ch->state)
+  {
+    if (GNUNET_NO == fwd)
+    {
+      /* If we are the root, this means the other peer has sent traffic before
+       * receiving our ACK. Even if the SYNACK goes missing, no traffic should
+       * be sent before the ACK.
+       */
+      GNUNET_break_op (0);
+      return;
+    }
+    /* If we are the dest, this means that the SYNACK got to the root but
+     * the ACK went missing. Treat this as an ACK.
+     */
+    channel_confirm (ch, GNUNET_NO);
+  }
+
+  GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO);
+
+  mid = ntohl (msg->mid);
+  LOG (GNUNET_ERROR_TYPE_INFO, "<=== DATA %u %s on channel %s\n",
+       mid, GM_f2s (fwd), GMCH_2s (ch));
+
+  if (GNUNET_NO == ch->reliable ||
+      ( !GM_is_pid_bigger (rel->mid_recv, mid) &&
+        GM_is_pid_bigger (rel->mid_recv + 64, mid) ) )
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "RECV %u (%u)\n",
+         mid, ntohs (msg->header.size));
+    if (GNUNET_YES == ch->reliable)
+    {
+      /* Is this the exact next expected messasge? */
+      if (mid == rel->mid_recv)
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n");
+        rel->mid_recv++;
+        send_client_data (ch, msg, fwd);
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
+        add_buffered_data (msg, rel);
+      }
+    }
+    else
+    {
+      /* Tunnel is unreliable: send to clients directly */
+      /* FIXME: accept Out Of Order traffic */
+      rel->mid_recv = mid + 1;
+      send_client_data (ch, msg, fwd);
+    }
+  }
+  else
+  {
+    GNUNET_break_op (GM_is_pid_bigger (rel->mid_recv, mid));
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "MID %u not expected (%u - %u), dropping!\n",
+         mid, rel->mid_recv, rel->mid_recv + 63);
+  }
+
+  GMCH_send_data_ack (ch, fwd);
+}
+
+
+/**
+ * Handler for cadet network traffic end-to-end ACKs.
+ *
+ * @param ch Channel on which we got this message.
+ * @param msg Data message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_data_ack (struct CadetChannel *ch,
+                      const struct GNUNET_CADET_DataACK *msg,
+                      int fwd)
+{
+  struct CadetChannelReliability *rel;
+  struct CadetReliableMessage *copy;
+  struct CadetReliableMessage *next;
+  uint32_t ack;
+  int work;
+
+  /* If this is a remote (non-loopback) channel, find 'fwd'. */
+  if (GNUNET_SYSERR == fwd)
+  {
+    if (is_loopback (ch))
+    {
+      /* It is a loopback channel after all... */
+      GNUNET_break (0);
+      return;
+    }
+    /* Inverted: if message came 'FWD' is a 'BCK ACK'. */
+    fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES;
+  }
+
+  ack = ntohl (msg->mid);
+  LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s ACK %u\n", GM_f2s (fwd), ack);
+
+  if (GNUNET_YES == fwd)
+  {
+    rel = ch->root_rel;
+  }
+  else
+  {
+    rel = ch->dest_rel;
+  }
+  if (NULL == rel)
+  {
+    GNUNET_break_op (GNUNET_NO != ch->destroy);
+    return;
+  }
+
+  /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */
+  for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
+  {
+    if (GM_is_pid_bigger (copy->mid, ack))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  head %u, out!\n", copy->mid);
+      channel_rel_free_sent (rel, msg);
+      break;
+    }
+    work = GNUNET_YES;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %u\n", copy->mid);
+    next = copy->next;
+    if (GNUNET_YES == rel_message_free (copy, GNUNET_YES))
+      return;
+  }
+
+  /* ACK client if needed and possible */
+  GMCH_allow_client (ch, fwd);
+
+  /* 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);
+      rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
+      if (NULL != rel->head_sent && NULL == rel->head_sent->chq)
+      {
+        struct GNUNET_TIME_Absolute new_target;
+        struct GNUNET_TIME_Relative delay;
+
+        delay = GNUNET_TIME_relative_multiply (rel->retry_timer,
+                                               CADET_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
+    {
+      /* Work was done but no task was pending? Shouldn't happen! */
+      GNUNET_break (0);
+    }
+  }
+}
+
+
+/**
+ * Handler for channel create messages.
+ *
+ * Does not have fwd parameter because it's always 'FWD': channel is incoming.
+ *
+ * @param t Tunnel this channel will be in.
+ * @param msg Channel crate message.
+ */
+struct CadetChannel *
+GMCH_handle_create (struct CadetTunnel3 *t,
+                    const struct GNUNET_CADET_ChannelCreate *msg)
+{
+  CADET_ChannelNumber chid;
+  struct CadetChannel *ch;
+  struct CadetClient *c;
+  int new_channel;
+  int reaction;
+
+  reaction = GNUNET_NO;
+  chid = ntohl (msg->chid);
+  ch = GMT_get_channel (t, chid);
+  if (NULL == ch)
+  {
+    /* Create channel */
+    ch = channel_new (t, NULL, 0);
+    ch->gid = chid;
+    channel_set_options (ch, ntohl (msg->opt));
+    new_channel = GNUNET_YES;
+  }
+  else
+  {
+    new_channel = GNUNET_NO;
+  }
+
+  if (GNUNET_YES == new_channel || GMT_is_loopback (t))
+  {
+    /* Find a destination client */
+    ch->port = ntohl (msg->port);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "   port %u\n", ch->port);
+    c = GML_client_get_by_port (ch->port);
+    if (NULL == c)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  no client has port registered\n");
+      if (is_loopback (ch))
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "  loopback: destroy on handler\n");
+        send_nack (ch);
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "  not loopback: destroy now\n");
+        send_nack (ch);
+        GMCH_destroy (ch);
+      }
+      return NULL;
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  client %p has port registered\n", c);
+    }
+
+    add_destination (ch, c);
+    if (GNUNET_YES == ch->reliable)
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n");
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Not Reliable\n");
+
+    send_client_create (ch);
+    ch->state =  CADET_CHANNEL_SENT;
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  duplicate create channel\n");
+    reaction = GNUNET_YES;
+    if (GNUNET_SCHEDULER_NO_TASK != ch->dest_rel->retry_task)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  clearing retry task\n");
+      /* we were waiting to re-send our 'SYNACK', wait no more! */
+      GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task);
+      ch->dest_rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  }
+  send_ack (ch, GNUNET_YES, reaction);
+
+  return ch;
+}
+
+
+/**
+ * Handler for channel NACK messages.
+ *
+ * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
+ *
+ * @param ch Channel.
+ */
+void
+GMCH_handle_nack (struct CadetChannel *ch)
+{
+  send_client_nack (ch);
+  GMCH_destroy (ch);
+}
+
+
+/**
+ * Handler for channel ack messages.
+ *
+ * @param ch Channel.
+ * @param msg Message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_ack (struct CadetChannel *ch,
+                 const struct GNUNET_CADET_ChannelManage *msg,
+                 int fwd)
+{
+  /* If this is a remote (non-loopback) channel, find 'fwd'. */
+  if (GNUNET_SYSERR == fwd)
+  {
+    if (is_loopback (ch))
+    {
+      /* It is a loopback channel after all... */
+      GNUNET_break (0);
+      return;
+    }
+    fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+  }
+
+  channel_confirm (ch, !fwd);
+}
+
+
+/**
+ * Handler for channel destroy messages.
+ *
+ * @param ch Channel to be destroyed of.
+ * @param msg Message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_destroy (struct CadetChannel *ch,
+                     const struct GNUNET_CADET_ChannelManage *msg,
+                     int fwd)
+{
+  struct CadetChannelReliability *rel;
+
+  /* If this is a remote (non-loopback) channel, find 'fwd'. */
+  if (GNUNET_SYSERR == fwd)
+  {
+    if (is_loopback (ch))
+    {
+      /* It is a loopback channel after all... */
+      GNUNET_break (0);
+      return;
+    }
+    fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
+  }
+
+  GMCH_debug (ch);
+  if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
+  {
+    /* Not for us (don't destroy twice a half-open loopback channel) */
+    return;
+  }
+
+  rel = fwd ? ch->dest_rel : ch->root_rel;
+  if (0 == rel->n_recv)
+  {
+    send_destroy (ch, GNUNET_YES);
+    GMCH_destroy (ch);
+  }
+  else
+  {
+    ch->destroy = GNUNET_YES;
+  }
+}
+
+
+/**
+ * Sends an already built message on a channel.
+ *
+ * If the channel is on a loopback tunnel, notifies the appropriate destination
+ * client locally.
+ *
+ * On a normal channel passes the message to the tunnel for encryption and
+ * sending on a connection.
+ *
+ * This function DOES NOT save the message for retransmission.
+ *
+ * @param message Message to send. Function makes a copy of it.
+ * @param ch Channel on which this message is transmitted.
+ * @param fwd Is this a fwd message?
+ * @param existing_copy This is a retransmission, don't save a copy.
+ */
+void
+GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                            struct CadetChannel *ch, int fwd,
+                            void *existing_copy)
+{
+  struct CadetChannelQueue *chq;
+  uint16_t type;
+
+  type = ntohs (message->type);
+  LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %s on channel %s\n",
+       GM_m2s (type), GM_f2s (fwd), GMCH_2s (ch));
+
+  if (GMT_is_loopback (ch->t))
+  {
+    handle_loopback (ch, message, fwd);
+    return;
+  }
+
+  switch (type)
+  {
+    struct GNUNET_CADET_Data *payload;
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+
+      payload = (struct GNUNET_CADET_Data *) message;
+      LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %u\n",
+           GM_m2s (type), ntohl (payload->mid));
+      if (GNUNET_YES == ch->reliable)
+      {
+        chq = GNUNET_new (struct CadetChannelQueue);
+        chq->type = type;
+        if (NULL == existing_copy)
+          chq->copy = channel_save_copy (ch, message, fwd);
+        else
+        {
+          chq->copy = (struct CadetReliableMessage *) existing_copy;
+          if (NULL != chq->copy->chq)
+          {
+            /* Last retransmission was queued but not yet sent!
+             * This retransmission was scheduled by a ch_message_sent which
+             * followed a very fast RTT, so the tiny delay made the
+             * retransmission function to execute before the previous
+             * retransmitted message even had a chance to leave the peer.
+             * Cancel this message and wait until the pending
+             * retransmission leaves the peer and ch_message_sent starts
+             * the timer for the next one.
+             */
+            GNUNET_free (chq);
+            LOG (GNUNET_ERROR_TYPE_DEBUG,
+                 "  exisitng copy not yet transmitted!\n");
+            return;
+          }
+          LOG (GNUNET_ERROR_TYPE_DEBUG,
+               "  using existing copy: %p {r:%p q:%p t:%u}\n",
+               existing_copy,
+               chq->copy->rel, chq->copy->chq, chq->copy->type);
+        }
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "  new chq: %p\n", chq);
+            chq->copy->chq = chq;
+            chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL,
+                                                 NULL != existing_copy,
+                                                 &ch_message_sent, chq);
+        /* q itself is stored in copy */
+        GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy);
+      }
+      else
+      {
+        fire_and_forget (message, ch, GNUNET_NO);
+      }
+      break;
+
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+      if (GNUNET_YES == fwd || NULL != existing_copy)
+      {
+        /* BCK ACK (going FWD) is just a response for a SYNACK, don't keep*/
+        fire_and_forget (message, ch, GNUNET_YES);
+        return;
+      }
+      /* fall-trough */
+    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+      chq = GNUNET_new (struct CadetChannelQueue);
+      chq->type = type;
+      chq->rel = fwd ? ch->root_rel : ch->dest_rel;
+      if (NULL != chq->rel->uniq)
+      {
+        if (NULL != chq->rel->uniq->tq)
+        {
+          GMT_cancel (chq->rel->uniq->tq);
+          /* ch_message_sent is called, freeing and NULLing uniq */
+        }
+        else
+        {
+          GNUNET_break (0);
+          GNUNET_free (chq->rel->uniq);
+        }
+      }
+      chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES,
+                                           &ch_message_sent, chq);
+      if (NULL == chq->tq)
+      {
+        GNUNET_break (0);
+        GNUNET_free (chq);
+        chq = NULL;
+        return;
+      }
+      chq->rel->uniq = chq;
+      break;
+
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+      fire_and_forget (message, ch, GNUNET_YES);
+      break;
+
+
+    default:
+      GNUNET_break (0);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s unknown!\n", GM_m2s (type));
+      fire_and_forget (message, ch, GNUNET_YES);
+  }
+}
+
+
+/**
+ * Get the static string for identification of the channel.
+ *
+ * @param ch Channel.
+ *
+ * @return Static string with the channel IDs.
+ */
+const char *
+GMCH_2s (const struct CadetChannel *ch)
+{
+  static char buf[64];
+
+  if (NULL == ch)
+    return "(NULL Channel)";
+
+  sprintf (buf, "%s:%u gid:%X (%X / %X)",
+           GMT_2s (ch->t), ch->port, ch->gid, ch->lid_root, ch->lid_dest);
+
+  return buf;
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_channel.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_channel.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_channel.h                             
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_channel.h     2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,349 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_channel.h
+ * @brief cadet service; dealing with end-to-end channels
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GMCH (Gnunet Cadet CHannel)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
+#define GNUNET_SERVICE_CADET_CHANNEL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "cadet_protocol.h"
+#include "cadet.h"
+
+/**
+ * Struct containing all information regarding a channel to a remote client.
+ */
+struct CadetChannel;
+
+
+#include "gnunet-service-cadet_tunnel.h"
+#include "gnunet-service-cadet_local.h"
+
+
+/**
+ * Destroy a channel and free all resources.
+ *
+ * @param ch Channel to destroy.
+ */
+void
+GMCH_destroy (struct CadetChannel *ch);
+
+
+/**
+ * Get the channel's public ID.
+ *
+ * @param ch Channel.
+ *
+ * @return ID used to identify the channel with the remote peer.
+ */
+CADET_ChannelNumber
+GMCH_get_id (const struct CadetChannel *ch);
+
+/**
+ * Get the channel tunnel.
+ *
+ * @param ch Channel to get the tunnel from.
+ *
+ * @return tunnel of the channel.
+ */
+struct CadetTunnel3 *
+GMCH_get_tunnel (const struct CadetChannel *ch);
+
+/**
+ * Get free buffer space towards the client on a specific channel.
+ *
+ * @param ch Channel.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Free buffer space [0 - 64]
+ */
+unsigned int
+GMCH_get_buffer (struct CadetChannel *ch, int fwd);
+
+
+/**
+ * Get flow control status of end point: is client allow to send?
+ *
+ * @param ch Channel.
+ * @param fwd Is query about FWD traffic? (Request root status).
+ *
+ * @return #GNUNET_YES if client is allowed to send us data.
+ */
+int
+GMCH_get_allowed (struct CadetChannel *ch, int fwd);
+
+
+/**
+ * Is the root client for this channel on this peer?
+ *
+ * @param ch Channel.
+ * @param fwd Is this for fwd traffic?
+ *
+ * @return #GNUNET_YES in case it is.
+ */
+int
+GMCH_is_origin (struct CadetChannel *ch, int fwd);
+
+/**
+ * Is the destination client for this channel on this peer?
+ *
+ * @param ch Channel.
+ * @param fwd Is this for fwd traffic?
+ *
+ * @return #GNUNET_YES in case it is.
+ */
+int
+GMCH_is_terminal (struct CadetChannel *ch, int fwd);
+
+/**
+ * Send an end-to-end ACK message for the most recent in-sequence payload.
+ *
+ * If channel is not reliable, do nothing.
+ *
+ * @param ch Channel this is about.
+ * @param fwd Is for FWD traffic? (ACK dest->owner)
+ */
+void
+GMCH_send_data_ack (struct CadetChannel *ch, int fwd);
+
+/**
+ * Notify the destination client that a new incoming channel was created.
+ *
+ * @param ch Channel that was created.
+ */
+void
+GMCH_send_create (struct CadetChannel *ch);
+
+/**
+ * Allow a client to send us more data, in case it was choked.
+ *
+ * @param ch Channel.
+ * @param fwd Is this about FWD traffic? (Root client).
+ */
+void
+GMCH_allow_client (struct CadetChannel *ch, int fwd);
+
+/**
+ * Log channel info.
+ *
+ * @param ch Channel.
+ */
+void
+GMCH_debug (struct CadetChannel *ch);
+
+/**
+ * Handle an ACK given by a client.
+ *
+ * Mark client as ready and send him any buffered data we could have for him.
+ *
+ * @param ch Channel.
+ * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK)
+ */
+void
+GMCH_handle_local_ack (struct CadetChannel *ch, int fwd);
+
+/**
+ * Handle data given by a client.
+ *
+ * Check whether the client is allowed to send in this tunnel, save if channel
+ * is reliable and send an ACK to the client if there is still buffer space
+ * in the tunnel.
+ *
+ * @param ch Channel.
+ * @param c Client which sent the data.
+ * @param message Message.
+ * @param fwd Is this a FWD data?
+ *
+ * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en 
error.
+ */
+int
+GMCH_handle_local_data (struct CadetChannel *ch,
+                        struct CadetClient *c,
+                        struct GNUNET_MessageHeader *message,
+                        int fwd);
+
+/**
+ * Handle a channel destroy requested by a client.
+ *
+ * Destroy the channel and the tunnel in case this was the last channel.
+ *
+ * @param ch Channel.
+ * @param c Client that requested the destruction (to avoid notifying him).
+ * @param is_root Is the request coming from root?
+ */
+void
+GMCH_handle_local_destroy (struct CadetChannel *ch,
+                           struct CadetClient *c,
+                           int is_root);
+
+/**
+ * Handle a channel create requested by a client.
+ *
+ * Create the channel and the tunnel in case this was the first0 channel.
+ *
+ * @param c Client that requested the creation (will be the root).
+ * @param msg Create Channel message.
+ *
+ * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise.
+ */
+int
+GMCH_handle_local_create (struct CadetClient *c,
+                          struct GNUNET_CADET_ChannelMessage *msg);
+
+/**
+ * Handler for cadet network payload traffic.
+ *
+ * @param ch Channel for the message.
+ * @param msg Unencryted data message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_data (struct CadetChannel *ch,
+                  const struct GNUNET_CADET_Data *msg,
+                  int fwd);
+
+/**
+ * Handler for cadet network traffic end-to-end ACKs.
+ *
+ * @param ch Channel on which we got this message.
+ * @param msg Data message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_data_ack (struct CadetChannel *ch,
+                      const struct GNUNET_CADET_DataACK *msg,
+                      int fwd);
+
+/**
+ * Handler for channel create messages.
+ *
+ * Does not have fwd parameter because it's always 'FWD': channel is incoming.
+ *
+ * @param t Tunnel this channel will be in.
+ * @param msg Channel crate message.
+ */
+struct CadetChannel *
+GMCH_handle_create (struct CadetTunnel3 *t,
+                    const struct GNUNET_CADET_ChannelCreate *msg);
+
+/**
+ * Handler for channel NACK messages.
+ *
+ * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
+ *
+ * @param ch Channel.
+ */
+void
+GMCH_handle_nack (struct CadetChannel *ch);
+
+/**
+ * Handler for channel ack messages.
+ *
+ * @param ch Channel this channel is to be created in.
+ * @param msg Message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_ack (struct CadetChannel *ch,
+                 const struct GNUNET_CADET_ChannelManage *msg,
+                 int fwd);
+
+/**
+ * Handler for channel destroy messages.
+ *
+ * @param ch Channel this channel is to be destroyed of.
+ * @param msg Message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+void
+GMCH_handle_destroy (struct CadetChannel *ch,
+                     const struct GNUNET_CADET_ChannelManage *msg,
+                     int fwd);
+
+/**
+ * Sends an already built message on a channel.
+ *
+ * If the channel is on a loopback tunnel, notifies the appropriate destination
+ * client locally.
+ *
+ * On a normal channel passes the message to the tunnel for encryption and
+ * sending on a connection.
+ *
+ * This function DOES NOT save the message for retransmission.
+ *
+ * @param message Message to send. Function makes a copy of it.
+ * @param ch Channel on which this message is transmitted.
+ * @param fwd Is this a fwd message?
+ * @param existing_copy This is a retransmission, don't save a copy.
+ */
+void
+GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                            struct CadetChannel *ch, int fwd,
+                            void *existing_copy);
+
+/**
+ * Get the static string for identification of the channel.
+ *
+ * @param ch Channel.i
+ *
+ * @return Static string with the channel IDs.
+ */
+const char *
+GMCH_2s (const struct CadetChannel *ch);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_SERVICE_CADET_CHANNEL_H */
+#endif
+/* end of gnunet-service-cadet_channel.h */

Copied: gnunet/src/cadet/gnunet-service-cadet_connection.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_connection.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_connection.c                          
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_connection.c  2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,3176 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001-2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_connection.c
+ * @brief GNUnet CADET service connection handling
+ * @author Bartlomiej Polot
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_statistics_service.h"
+
+#include "cadet_path.h"
+#include "cadet_protocol.h"
+#include "cadet.h"
+#include "gnunet-service-cadet_connection.h"
+#include "gnunet-service-cadet_peer.h"
+#include "gnunet-service-cadet_tunnel.h"
+
+
+#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__)
+
+#define CADET_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
+                                  GNUNET_TIME_UNIT_MINUTES,\
+                                  10)
+#define AVG_MSGS                32
+
+
+/******************************************************************************/
+/********************************   STRUCTS  
**********************************/
+/******************************************************************************/
+
+/**
+ * Struct to encapsulate all the Flow Control information to a peer to which
+ * we are directly connected (on a core level).
+ */
+struct CadetFlowControl
+{
+  /**
+   * Connection this controls.
+   */
+  struct CadetConnection *c;
+
+  /**
+   * How many messages are in the queue on this connection.
+   */
+  unsigned int queue_n;
+
+  /**
+   * How many messages do we accept in the queue.
+   */
+  unsigned int queue_max;
+
+  /**
+   * ID of the last packet sent towards the peer.
+   */
+  uint32_t last_pid_sent;
+
+  /**
+   * ID of the last packet received from the peer.
+   */
+  uint32_t last_pid_recv;
+
+  /**
+   * Last ACK sent to the peer (peer can't send more than this PID).
+   */
+  uint32_t last_ack_sent;
+
+  /**
+   * Last ACK sent towards the origin (for traffic towards leaf node).
+   */
+  uint32_t last_ack_recv;
+
+  /**
+   * Task to poll the peer in case of a lost ACK causes stall.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier poll_task;
+
+  /**
+   * How frequently to poll for ACKs.
+   */
+  struct GNUNET_TIME_Relative poll_time;
+
+  /**
+   * Queued poll message, to cancel if not necessary anymore (got ACK).
+   */
+  struct CadetConnectionQueue *poll_msg;
+
+  /**
+   * Queued poll message, to cancel if not necessary anymore (got ACK).
+   */
+  struct CadetConnectionQueue *ack_msg;
+};
+
+/**
+ * Keep a record of the last messages sent on this connection.
+ */
+struct CadetConnectionPerformance
+{
+  /**
+   * Circular buffer for storing measurements.
+   */
+  double usecsperbyte[AVG_MSGS];
+
+  /**
+   * Running average of @c usecsperbyte.
+   */
+  double avg;
+
+  /**
+   * How many values of @c usecsperbyte are valid.
+   */
+  uint16_t size;
+
+  /**
+   * Index of the next "free" position in @c usecsperbyte.
+   */
+  uint16_t idx;
+};
+
+
+/**
+ * Struct containing all information regarding a connection to a peer.
+ */
+struct CadetConnection
+{
+  /**
+   * Tunnel this connection is part of.
+   */
+  struct CadetTunnel3 *t;
+
+  /**
+   * Flow control information for traffic fwd.
+   */
+  struct CadetFlowControl fwd_fc;
+
+  /**
+   * Flow control information for traffic bck.
+   */
+  struct CadetFlowControl bck_fc;
+
+  /**
+   * Measure connection performance on the endpoint.
+   */
+  struct CadetConnectionPerformance *perf;
+
+  /**
+   * ID of the connection.
+   */
+  struct GNUNET_CADET_Hash id;
+
+  /**
+   * State of the connection.
+   */
+  enum CadetConnectionState state;
+
+  /**
+   * Path being used for the tunnel. At the origin of the connection
+   * it's a pointer to the destination's path pool, otherwise just a copy.
+   */
+  struct CadetPeerPath *path;
+
+  /**
+   * Position of the local peer in the path.
+   */
+  unsigned int own_pos;
+
+  /**
+   * Task to keep the used paths alive at the owner,
+   * time tunnel out on all the other peers.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
+
+  /**
+   * Task to keep the used paths alive at the destination,
+   * time tunnel out on all the other peers.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
+
+  /**
+   * Queue handle for maintainance traffic. One handle for FWD and BCK since
+   * one peer never needs to maintain both directions (no loopback 
connections).
+   */
+  struct CadetPeerQueue *maintenance_q;
+
+  /**
+   * Counter to do exponential backoff when creating a connection (max 64).
+   */
+  unsigned short create_retry;
+
+  /**
+   * Pending message count.
+   */
+  int pending_messages;
+
+  /**
+   * Destroy flag: if true, destroy on last message.
+   */
+  int destroy;
+};
+
+/**
+ * Handle for messages queued but not yet sent.
+ */
+struct CadetConnectionQueue
+{
+  /**
+   * Peer queue handle, to cancel if necessary.
+   */
+  struct CadetPeerQueue *q;
+
+  /**
+   * Was this a forced message? (Do not account for it)
+   */
+  int forced;
+
+  /**
+   * Continuation to call once sent.
+   */
+  GMC_sent cont;
+
+  /**
+   * Closure for @c cont.
+   */
+  void *cont_cls;
+};
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Local peer own ID (memory efficient handle).
+ */
+extern GNUNET_PEER_Id myid;
+
+/**
+ * Local peer own ID (full value).
+ */
+extern struct GNUNET_PeerIdentity my_full_id;
+
+/**
+ * Connections known, indexed by cid (CadetConnection).
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *connections;
+
+/**
+ * How many connections are we willing to maintain.
+ * Local connections are always allowed, even if there are more connections 
than max.
+ */
+static unsigned long long max_connections;
+
+/**
+ * How many messages *in total* are we willing to queue, divide by number of
+ * connections to get connection queue size.
+ */
+static unsigned long long max_msgs_queue;
+
+/**
+ * How often to send path keepalives. Paths timeout after 4 missed.
+ */
+static struct GNUNET_TIME_Relative refresh_connection_time;
+
+/**
+ * How often to send path create / ACKs.
+ */
+static struct GNUNET_TIME_Relative create_connection_time;
+
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+#if 0 // avoid compiler warning for unused static function
+static void
+fc_debug (struct CadetFlowControl *fc)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
+              fc->last_pid_recv, fc->last_ack_sent);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
+              fc->last_pid_sent, fc->last_ack_recv);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
+              fc->queue_n, fc->queue_max);
+}
+
+static void
+connection_debug (struct CadetConnection *c)
+{
+  if (NULL == c)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
+              peer2s (c->t->peer), GMC_2s (c));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n",
+              c->state, c->pending_messages);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
+  fc_debug (&c->fwd_fc);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
+  fc_debug (&c->bck_fc);
+}
+#endif
+
+
+/**
+ * Schedule next keepalive task, taking in consideration
+ * the connection state and number of retries.
+ *
+ * @param c Connection for which to schedule the next keepalive.
+ * @param fwd Direction for the next keepalive.
+ */
+static void
+schedule_next_keepalive (struct CadetConnection *c, int fwd);
+
+
+/**
+ * Resets the connection timeout task, some other message has done the
+ * task's job.
+ * - For the first peer on the direction this means to send
+ *   a keepalive or a path confirmation message (either create or ACK).
+ * - For all other peers, this means to destroy the connection,
+ *   due to lack of activity.
+ * Starts the timeout if no timeout was running (connection just created).
+ *
+ * @param c Connection whose timeout to reset.
+ * @param fwd Is this forward?
+ */
+static void
+connection_reset_timeout (struct CadetConnection *c, int fwd);
+
+
+/**
+ * Get string description for tunnel state. Reentrant.
+ *
+ * @param s Tunnel state.
+ *
+ * @return String representation.
+ */
+static const char *
+GMC_state2s (enum CadetConnectionState s)
+{
+  switch (s)
+  {
+    case CADET_CONNECTION_NEW:
+      return "CADET_CONNECTION_NEW";
+    case CADET_CONNECTION_SENT:
+      return "CADET_CONNECTION_SENT";
+    case CADET_CONNECTION_ACK:
+      return "CADET_CONNECTION_ACK";
+    case CADET_CONNECTION_READY:
+      return "CADET_CONNECTION_READY";
+    case CADET_CONNECTION_DESTROYED:
+      return "CADET_CONNECTION_DESTROYED";
+    default:
+      return "CADET_CONNECTION_STATE_ERROR";
+  }
+}
+
+
+/**
+ * Initialize a Flow Control structure to the initial state.
+ *
+ * @param fc Flow Control structure to initialize.
+ */
+static void
+fc_init (struct CadetFlowControl *fc)
+{
+  fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
+  fc->last_pid_recv = (uint32_t) -1;
+  fc->last_ack_sent = (uint32_t) 0;
+  fc->last_ack_recv = (uint32_t) 0;
+  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
+  fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
+  fc->queue_n = 0;
+  fc->queue_max = (max_msgs_queue / max_connections) + 1;
+}
+
+
+/**
+ * Find a connection.
+ *
+ * @param cid Connection ID.
+ */
+static struct CadetConnection *
+connection_get (const struct GNUNET_CADET_Hash *cid)
+{
+  return GNUNET_CONTAINER_multihashmap_get (connections, GM_h2hc (cid));
+}
+
+
+static void
+connection_change_state (struct CadetConnection* c,
+                         enum CadetConnectionState state)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Connection %s state %s -> %s\n",
+       GMC_2s (c), GMC_state2s (c->state), GMC_state2s (state));
+  if (CADET_CONNECTION_DESTROYED == c->state)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n");
+    return;
+  }
+  c->state = state;
+  if (CADET_CONNECTION_READY == state)
+    c->create_retry = 1;
+}
+
+
+/**
+ * Callback called when a queued ACK message is sent.
+ *
+ * @param cls Closure (FC).
+ * @param c Connection this message was on.
+ * @param q Queue handler this call invalidates.
+ * @param type Type of message sent.
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ */
+static void
+ack_sent (void *cls,
+          struct CadetConnection *c,
+          struct CadetConnectionQueue *q,
+          uint16_t type, int fwd, size_t size)
+{
+  struct CadetFlowControl *fc = cls;
+
+  fc->ack_msg = NULL;
+}
+
+
+/**
+ * Send an ACK on the connection, informing the predecessor about
+ * the available buffer space. Should not be called in case the peer
+ * is origin (no predecessor) in the @c fwd direction.
+ *
+ * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
+ * the ACK itself goes "back" (dest->root).
+ *
+ * @param c Connection on which to send the ACK.
+ * @param buffer How much space free to advertise?
+ * @param fwd Is this FWD ACK? (Going dest -> root)
+ * @param force Don't optimize out.
+ */
+static void
+send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
+{
+  struct CadetFlowControl *next_fc;
+  struct CadetFlowControl *prev_fc;
+  struct GNUNET_CADET_ACK msg;
+  uint32_t ack;
+  int delta;
+
+  /* If origin, there is no connection to send ACKs. Wrong function! */
+  if (GMC_is_origin (c, fwd))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "connection %s is origin in %s\n",
+         GMC_2s (c), GM_f2s (fwd));
+    GNUNET_break (0);
+    return;
+  }
+
+  next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "connection send %s ack on %s\n",
+       GM_f2s (fwd), GMC_2s (c));
+
+  /* Check if we need to transmit the ACK. */
+  delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
+  if (3 < delta && buffer < delta && GNUNET_NO == force)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "  last pid recv: %u, last ack sent: %u\n",
+         prev_fc->last_pid_recv, prev_fc->last_ack_sent);
+    return;
+  }
+
+  /* Ok, ACK might be necessary, what PID to ACK? */
+  ack = prev_fc->last_pid_recv + buffer;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       " last pid %u, last ack %u, qmax %u, q %u\n",
+       prev_fc->last_pid_recv, prev_fc->last_ack_sent,
+       next_fc->queue_max, next_fc->queue_n);
+  if (ack == prev_fc->last_ack_sent && GNUNET_NO == force)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
+    return;
+  }
+
+  /* Check if message is already in queue */
+  if (NULL != prev_fc->ack_msg)
+  {
+    if (GM_is_pid_bigger (ack, prev_fc->last_ack_sent))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
+      GMC_cancel (prev_fc->ack_msg);
+      /* GMC_cancel triggers ack_sent(), which clears fc->ack_msg */
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n");
+      return;
+    }
+  }
+
+  prev_fc->last_ack_sent = ack;
+
+  /* Build ACK message and send on connection */
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ACK);
+  msg.ack = htonl (ack);
+  msg.cid = c->id;
+
+  prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header,
+                                                GNUNET_MESSAGE_TYPE_CADET_ACK,
+                                                ack, c, !fwd, GNUNET_YES,
+                                                &ack_sent, prev_fc);
+}
+
+
+/**
+ * Callback called when a connection queued message is sent.
+ *
+ * Calculates the average time and connection packet tracking.
+ *
+ * @param cls Closure (ConnectionQueue Handle).
+ * @param c Connection this message was on.
+ * @param sent Was it really sent? (Could have been canceled)
+ * @param type Type of message sent.
+ * @param pid Packet ID, or 0 if not applicable (create, destroy, etc).
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ * @param wait Time spent waiting for core (only the time for THIS message)
+ */
+static void
+conn_message_sent (void *cls,
+                   struct CadetConnection *c, int sent,
+                   uint16_t type, uint32_t pid, int fwd, size_t size,
+                   struct GNUNET_TIME_Relative wait)
+{
+  struct CadetConnectionPerformance *p;
+  struct CadetFlowControl *fc;
+  struct CadetConnectionQueue *q = cls;
+  double usecsperbyte;
+  int forced;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "connection message_sent\n");
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s\n",
+       sent ? "" : "not ", GM_f2s (fwd), GM_m2s (type));
+  if (NULL != q)
+  {
+    forced = q->forced;
+    if (NULL != q->cont)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n");
+      q->cont (q->cont_cls, c, q, type, fwd, size);
+    }
+    GNUNET_free (q);
+  }
+  else if (type == GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED)
+  {
+    /* If NULL == q and ENCRYPTED == type, message must have been ch_mngmnt */
+    forced = GNUNET_YES;
+  }
+  else
+  {
+    forced = GNUNET_NO;
+  }
+  if (NULL == c)
+  {
+    GNUNET_break (type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN ||
+                  type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
+    LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n",
+         GM_m2s (type));
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages);
+  c->pending_messages--;
+  if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "!  destroying connection!\n");
+    GMC_destroy (c);
+    return;
+  }
+  /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+      c->maintenance_q = NULL;
+      /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */
+      if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd)
+        schedule_next_keepalive (c, fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+      if (GNUNET_YES == sent)
+      {
+        GNUNET_assert (NULL != q);
+        fc->last_pid_sent = pid; // FIXME
+        GMC_send_ack (c, fwd, GNUNET_NO);
+        connection_reset_timeout (c, fwd);
+      }
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "!  Q_N- %p %u\n", fc, fc->queue_n);
+      if (GNUNET_NO == forced)
+      {
+        fc->queue_n--;
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+            "!   accounting pid %u\n",
+            fc->last_pid_sent);
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "!   forced, Q_N not accounting pid %u\n",
+             fc->last_pid_sent);
+      }
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_KX:
+      if (GNUNET_YES == sent)
+        connection_reset_timeout (c, fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+      fc->poll_msg = NULL;
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+      fc->ack_msg = NULL;
+      break;
+
+    default:
+      break;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "!  message sent!\n");
+
+  if (NULL == c->perf)
+    return; /* Only endpoints are interested in timing. */
+
+  p = c->perf;
+  usecsperbyte = ((double) wait.rel_value_us) / size;
+  if (p->size == AVG_MSGS)
+  {
+    /* Array is full. Substract oldest value, add new one and store. */
+    p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
+    p->usecsperbyte[p->idx] = usecsperbyte;
+    p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
+  }
+  else
+  {
+    /* Array not yet full. Add current value to avg and store. */
+    p->usecsperbyte[p->idx] = usecsperbyte;
+    p->avg *= p->size;
+    p->avg += p->usecsperbyte[p->idx];
+    p->size++;
+    p->avg /= p->size;
+  }
+  p->idx = (p->idx + 1) % AVG_MSGS;
+}
+
+
+/**
+ * Get the previous hop in a connection
+ *
+ * @param c Connection.
+ *
+ * @return Previous peer in the connection.
+ */
+static struct CadetPeer *
+get_prev_hop (const struct CadetConnection *c)
+{
+  GNUNET_PEER_Id id;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " get prev hop %s [%u/%u]\n",
+       GMC_2s (c), c->own_pos, c->path->length);
+  if (0 == c->own_pos || c->path->length < 2)
+    id = c->path->peers[0];
+  else
+    id = c->path->peers[c->own_pos - 1];
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ID: %s (%u)\n",
+       GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
+
+  return GMP_get_short (id);
+}
+
+
+/**
+ * Get the next hop in a connection
+ *
+ * @param c Connection.
+ *
+ * @return Next peer in the connection.
+ */
+static struct CadetPeer *
+get_next_hop (const struct CadetConnection *c)
+{
+  GNUNET_PEER_Id id;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n",
+       GMC_2s (c), c->own_pos, c->path->length);
+  if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
+    id = c->path->peers[c->path->length - 1];
+  else
+    id = c->path->peers[c->own_pos + 1];
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ID: %s (%u)\n",
+       GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
+
+  return GMP_get_short (id);
+}
+
+
+/**
+ * Get the hop in a connection.
+ *
+ * @param c Connection.
+ * @param fwd Next hop?
+ *
+ * @return Next peer in the connection.
+ */
+static struct CadetPeer *
+get_hop (struct CadetConnection *c, int fwd)
+{
+  if (fwd)
+    return get_next_hop (c);
+  return get_prev_hop (c);
+}
+
+
+/**
+ * Is traffic coming from this sender 'FWD' traffic?
+ *
+ * @param c Connection to check.
+ * @param sender Peer identity of neighbor.
+ *
+ * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore
+ *         the traffic is 'FWD'.
+ *         #GNUNET_NO for BCK.
+ *         #GNUNET_SYSERR for errors.
+ */
+static int
+is_fwd (const struct CadetConnection *c,
+        const struct GNUNET_PeerIdentity *sender)
+{
+  GNUNET_PEER_Id id;
+
+  id = GNUNET_PEER_search (sender);
+  if (GMP_get_short_id (get_prev_hop (c)) == id)
+    return GNUNET_YES;
+
+  if (GMP_get_short_id (get_next_hop (c)) == id)
+    return GNUNET_NO;
+
+  GNUNET_break (0);
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
+ * or a first CONNECTION_ACK directed to us.
+ *
+ * @param connection Connection to confirm.
+ * @param fwd Should we send it FWD? (root->dest)
+ *            (First (~SYNACK) goes BCK, second (~ACK) goes FWD)
+ */
+static void
+send_connection_ack (struct CadetConnection *connection, int fwd)
+{
+  struct CadetTunnel3 *t;
+
+  t = connection->t;
+  LOG (GNUNET_ERROR_TYPE_INFO, "===> {%14s ACK} on connection %s\n",
+       GM_f2s (!fwd), GMC_2s (connection));
+  GMP_queue_add (get_hop (connection, fwd), NULL,
+                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK,
+                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0,
+                 sizeof (struct GNUNET_CADET_ConnectionACK),
+                 connection, fwd, &conn_message_sent, NULL);
+  connection->pending_messages++;
+  if (CADET_TUNNEL3_NEW == GMT_get_cstate (t))
+    GMT_change_cstate (t, CADET_TUNNEL3_WAITING);
+  if (CADET_CONNECTION_READY != connection->state)
+    connection_change_state (connection, CADET_CONNECTION_SENT);
+}
+
+
+/**
+ * Send a notification that a connection is broken.
+ *
+ * @param c Connection that is broken.
+ * @param id1 Peer that has disconnected.
+ * @param id2 Peer that has disconnected.
+ * @param fwd Direction towards which to send it.
+ */
+static void
+send_broken (struct CadetConnection *c,
+             const struct GNUNET_PeerIdentity *id1,
+             const struct GNUNET_PeerIdentity *id2,
+             int fwd)
+{
+  struct GNUNET_CADET_ConnectionBroken msg;
+
+  msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
+  msg.cid = c->id;
+  msg.peer1 = *id1;
+  msg.peer2 = *id2;
+  GMC_send_prebuilt_message (&msg.header,
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0,
+                             c, fwd, GNUNET_YES, NULL, NULL);
+}
+
+
+/**
+ * Send a notification that a connection is broken, when a connection
+ * isn't even known to the local peer.
+ *
+ * @param connection_id Connection ID.
+ * @param id1 Peer that has disconnected, probably local peer.
+ * @param id2 Peer that has disconnected can be NULL if unknown.
+ * @param peer Peer to notify (neighbor who sent the connection).
+ */
+static void
+send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id,
+                     const struct GNUNET_PeerIdentity *id1,
+                     const struct GNUNET_PeerIdentity *id2,
+                     const struct GNUNET_PeerIdentity *peer_id)
+{
+  struct GNUNET_CADET_ConnectionBroken *msg;
+  struct CadetPeer *neighbor;
+
+  LOG (GNUNET_ERROR_TYPE_INFO, "===> BROKEN on unknown connection %s\n",
+       GNUNET_h2s (GM_h2hc (connection_id)));
+
+  msg = GNUNET_new (struct GNUNET_CADET_ConnectionBroken);
+  msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
+  msg->cid = *connection_id;
+  msg->peer1 = *id1;
+  if (NULL != id2)
+    msg->peer2 = *id2;
+  else
+    memset (&msg->peer2, 0, sizeof (msg->peer2));
+  neighbor = GMP_get (peer_id);
+  GMP_queue_add (neighbor, msg,
+                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
+                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 2,
+                 sizeof (struct GNUNET_CADET_ConnectionBroken),
+                 NULL, GNUNET_SYSERR, /* connection, fwd */
+                 NULL, NULL); /* continuation */
+}
+
+
+/**
+ * Send keepalive packets for a connection.
+ *
+ * @param c Connection to keep alive..
+ * @param fwd Is this a FWD keepalive? (owner -> dest).
+ */
+static void
+send_connection_keepalive (struct CadetConnection *c, int fwd)
+{
+  struct GNUNET_MessageHeader msg;
+  struct CadetFlowControl *fc;
+
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "keepalive %s for connection %s\n",
+       GM_f2s (fwd), GMC_2s (c));
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  if (0 < fc->queue_n)
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n");
+  }
+
+  GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
+
+  GNUNET_assert (NULL != c->t);
+  msg.size = htons (sizeof (msg));
+  msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE);
+
+  GNUNET_assert (NULL ==
+                 GMT_send_prebuilt_message (&msg, c->t, c,
+                                            GNUNET_NO, NULL, NULL));
+}
+
+
+/**
+ * Send CONNECTION_{CREATE/ACK} packets for a connection.
+ *
+ * @param c Connection for which to send the message.
+ * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK.
+ */
+static void
+connection_recreate (struct CadetConnection *c, int fwd)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
+  if (fwd)
+    GMC_send_create (c);
+  else
+    send_connection_ack (c, GNUNET_NO);
+}
+
+
+/**
+ * Generic connection timer management.
+ * Depending on the role of the peer in the connection will send the
+ * appropriate message (build or keepalive)
+ *
+ * @param c Conncetion to maintain.
+ * @param fwd Is FWD?
+ */
+static void
+connection_maintain (struct CadetConnection *c, int fwd)
+{
+  if (GNUNET_NO != c->destroy)
+    return;
+
+  if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (c->t))
+  {
+    /* TODO DHT GET with RO_BART */
+    return;
+  }
+  switch (c->state)
+  {
+    case CADET_CONNECTION_NEW:
+      GNUNET_break (0);
+      /* fall-through */
+    case CADET_CONNECTION_SENT:
+      connection_recreate (c, fwd);
+      break;
+    case CADET_CONNECTION_READY:
+      send_connection_keepalive (c, fwd);
+      break;
+    default:
+      break;
+  }
+}
+
+
+
+/**
+ * Keep the connection alive.
+ *
+ * @param c Connection to keep alive.
+ * @param fwd Direction.
+ * @param shutdown Are we shutting down? (Don't send traffic)
+ *                 Non-zero value for true, not necessarily GNUNET_YES.
+ */
+static void
+connection_keepalive (struct CadetConnection *c, int fwd, int shutdown)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s keepalive for %s\n",
+       GM_f2s (fwd), GMC_2s (c));
+
+  if (fwd)
+    c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
+  else
+    c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if (GNUNET_NO != shutdown)
+    return;
+
+  connection_maintain (c, fwd);
+
+  /* Next execution will be scheduled by message_sent */
+}
+
+
+/**
+ * Keep the connection alive in the FWD direction.
+ *
+ * @param cls Closure (connection to keepalive).
+ * @param tc TaskContext.
+ */
+static void
+connection_fwd_keepalive (void *cls,
+                          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  connection_keepalive ((struct CadetConnection *) cls,
+                        GNUNET_YES,
+                        tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN);
+}
+
+
+/**
+ * Keep the connection alive in the BCK direction.
+ *
+ * @param cls Closure (connection to keepalive).
+ * @param tc TaskContext.
+ */
+static void
+connection_bck_keepalive (void *cls,
+                          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  connection_keepalive ((struct CadetConnection *) cls,
+                        GNUNET_NO,
+                        tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN);
+}
+
+
+/**
+ * Schedule next keepalive task, taking in consideration
+ * the connection state and number of retries.
+ *
+ * If the peer is not the origin, do nothing.
+ *
+ * @param c Connection for which to schedule the next keepalive.
+ * @param fwd Direction for the next keepalive.
+ */
+static void
+schedule_next_keepalive (struct CadetConnection *c, int fwd)
+{
+  struct GNUNET_TIME_Relative delay;
+  GNUNET_SCHEDULER_TaskIdentifier *task_id;
+  GNUNET_SCHEDULER_Task keepalive_task;
+
+  if (GNUNET_NO == GMC_is_origin (c, fwd))
+    return;
+
+  /* Calculate delay to use, depending on the state of the connection */
+  if (CADET_CONNECTION_READY == c->state)
+  {
+    delay = refresh_connection_time;
+  }
+  else
+  {
+    if (1 > c->create_retry)
+      c->create_retry = 1;
+    delay = GNUNET_TIME_relative_multiply (create_connection_time,
+                                           c->create_retry);
+    if (c->create_retry < 64)
+      c->create_retry *= 2;
+  }
+
+  /* Select direction-dependent parameters */
+  if (GNUNET_YES == fwd)
+  {
+    task_id = &c->fwd_maintenance_task;
+    keepalive_task = &connection_fwd_keepalive;
+  }
+  else
+  {
+    task_id = &c->bck_maintenance_task;
+    keepalive_task = &connection_bck_keepalive;
+  }
+
+  /* Check that no one scheduled it before us */
+  if (GNUNET_SCHEDULER_NO_TASK != *task_id)
+  {
+    /* No need for a _break. It can happen for instance when sending a SYNACK
+     * for a duplicate SYN: the first SYNACK scheduled the task. */
+    GNUNET_SCHEDULER_cancel (*task_id);
+  }
+
+  /* Schedule the task */
+  *task_id = GNUNET_SCHEDULER_add_delayed (delay, keepalive_task, c);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "next keepalive in %s\n",
+       GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
+}
+
+
+/**
+ * @brief Re-initiate traffic on this connection if necessary.
+ *
+ * Check if there is traffic queued towards this peer
+ * and the core transmit handle is NULL (traffic was stalled).
+ * If so, call core tmt rdy.
+ *
+ * @param c Connection on which initiate traffic.
+ * @param fwd Is this about fwd traffic?
+ */
+static void
+connection_unlock_queue (struct CadetConnection *c, int fwd)
+{
+  struct CadetPeer *peer;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+              "connection_unlock_queue %s on %s\n",
+              GM_f2s (fwd), GMC_2s (c));
+
+  if (GMC_is_terminal (c, fwd))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
+    return;
+  }
+
+  peer = get_hop (c, fwd);
+  GMP_queue_unlock (peer, c);
+}
+
+
+/**
+ * Cancel all transmissions that belong to a certain connection.
+ *
+ * If the connection is scheduled for destruction and no more messages are 
left,
+ * the connection will be destroyed by the continuation call.
+ *
+ * @param c Connection which to cancel. Might be destroyed during this call.
+ * @param fwd Cancel fwd traffic?
+ */
+static void
+connection_cancel_queues (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+  struct CadetPeer *peer;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       " *** Cancel %s queues for connection %s\n",
+       GM_f2s (fwd), GMC_2s (c));
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
+  {
+    GNUNET_SCHEDULER_cancel (fc->poll_task);
+    fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc);
+  }
+  peer = get_hop (c, fwd);
+  GMP_queue_cancel (peer, c);
+}
+
+
+/**
+ * Function called if a connection has been stalled for a while,
+ * possibly due to a missed ACK. Poll the neighbor about its ACK status.
+ *
+ * @param cls Closure (poll ctx).
+ * @param tc TaskContext.
+ */
+static void
+connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Callback called when a queued POLL message is sent.
+ *
+ * @param cls Closure (FC).
+ * @param c Connection this message was on.
+ * @param q Queue handler this call invalidates.
+ * @param type Type of message sent.
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ */
+static void
+poll_sent (void *cls,
+           struct CadetConnection *c,
+           struct CadetConnectionQueue *q,
+           uint16_t type, int fwd, size_t size)
+{
+  struct CadetFlowControl *fc = cls;
+
+  if (2 == c->destroy)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n");
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       " *** POLL sent for , scheduling new one!\n");
+  fc->poll_msg = NULL;
+  fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
+  fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
+                                                &connection_poll, fc);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
+
+}
+
+/**
+ * Function called if a connection has been stalled for a while,
+ * possibly due to a missed ACK. Poll the neighbor about its ACK status.
+ *
+ * @param cls Closure (poll ctx).
+ * @param tc TaskContext.
+ */
+static void
+connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetFlowControl *fc = cls;
+  struct GNUNET_CADET_Poll msg;
+  struct CadetConnection *c;
+
+  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    return;
+  }
+
+  c = fc->c;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling connection %s %s\n",
+       GMC_2s (c), fc == &c->fwd_fc ? "FWD" : "BCK");
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_POLL);
+  msg.header.size = htons (sizeof (msg));
+  msg.pid = htonl (fc->last_pid_sent);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", 
fc->last_pid_sent);
+  fc->poll_msg =
+      GMC_send_prebuilt_message (&msg.header,
+                                 GNUNET_MESSAGE_TYPE_CADET_POLL,
+                                 fc->last_pid_sent,
+                                 c, fc == &c->fwd_fc, GNUNET_YES,
+                                 &poll_sent, fc);
+}
+
+
+/**
+ * Timeout function due to lack of keepalive/traffic from the owner.
+ * Destroys connection if called.
+ *
+ * @param cls Closure (connection to destroy).
+ * @param tc TaskContext.
+ */
+static void
+connection_fwd_timeout (void *cls,
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetConnection *c = cls;
+
+  c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s FWD timed out. Destroying.\n",
+       GMC_2s (c));
+  if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  GMC_destroy (c);
+}
+
+
+/**
+ * Timeout function due to lack of keepalive/traffic from the destination.
+ * Destroys connection if called.
+ *
+ * @param cls Closure (connection to destroy).
+ * @param tc TaskContext
+ */
+static void
+connection_bck_timeout (void *cls,
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetConnection *c = cls;
+
+  c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s BCK timed out. Destroying.\n",
+       GMC_2s (c));
+
+  if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  GMC_destroy (c);
+}
+
+
+/**
+ * Resets the connection timeout task, some other message has done the
+ * task's job.
+ * - For the first peer on the direction this means to send
+ *   a keepalive or a path confirmation message (either create or ACK).
+ * - For all other peers, this means to destroy the connection,
+ *   due to lack of activity.
+ * Starts the timeout if no timeout was running (connection just created).
+ *
+ * @param c Connection whose timeout to reset.
+ * @param fwd Is this forward?
+ *
+ * TODO use heap to improve efficiency of scheduler.
+ */
+static void
+connection_reset_timeout (struct CadetConnection *c, int fwd)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd));
+
+  if (GMC_is_origin (c, fwd)) /* Startpoint */
+  {
+    schedule_next_keepalive (c, fwd);
+  }
+  else /* Relay, endpoint. */
+  {
+    struct GNUNET_TIME_Relative delay;
+    GNUNET_SCHEDULER_TaskIdentifier *ti;
+    GNUNET_SCHEDULER_Task f;
+
+    ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
+
+    if (GNUNET_SCHEDULER_NO_TASK != *ti)
+      GNUNET_SCHEDULER_cancel (*ti);
+    delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
+    f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
+    *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
+  }
+}
+
+
+/**
+ * Add the connection to the list of both neighbors.
+ *
+ * @param c Connection.
+ *
+ * @return #GNUNET_OK if everything went fine
+ *         #GNUNET_SYSERR if the was an error and @c c is malformed.
+ */
+static int
+register_neighbors (struct CadetConnection *c)
+{
+  struct CadetPeer *next_peer;
+  struct CadetPeer *prev_peer;
+
+  next_peer = get_next_hop (c);
+  prev_peer = get_prev_hop (c);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "register neighbors for connection %s\n",
+       GMC_2s (c));
+  path_debug (c->path);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "own pos %u\n", c->own_pos);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to next peer %p\n",
+       GMC_2s (c), next_peer);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", next_peer, GMP_2s 
(next_peer));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to prev peer %p\n",
+       GMC_2s (c), prev_peer);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "prev peer %p %s\n", prev_peer, GMP_2s 
(prev_peer));
+
+  if (GNUNET_NO == GMP_is_neighbor (next_peer)
+      || GNUNET_NO == GMP_is_neighbor (prev_peer))
+  {
+    if (GMC_is_origin (c, GNUNET_YES))
+      GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO);
+    GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO);
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  register neighbors failed\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  prev: %s, neighbor?: %d\n",
+         GMP_2s (prev_peer), GMP_is_neighbor (prev_peer));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  next: %s, neighbor?: %d\n",
+         GMP_2s (next_peer), GMP_is_neighbor (next_peer));
+    return GNUNET_SYSERR;
+  }
+
+  GMP_add_connection (next_peer, c);
+  GMP_add_connection (prev_peer, c);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Remove the connection from the list of both neighbors.
+ *
+ * @param c Connection.
+ */
+static void
+unregister_neighbors (struct CadetConnection *c)
+{
+  struct CadetPeer *peer;
+
+  peer = get_next_hop (c);
+  if (GNUNET_OK != GMP_remove_connection (peer, c))
+  {
+    GNUNET_assert (CADET_CONNECTION_NEW == c->state
+                  || CADET_CONNECTION_DESTROYED == c->state);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate: %u\n", c->state);
+    if (NULL != c->t) GMT_debug (c->t);
+  }
+
+  peer = get_prev_hop (c);
+  if (GNUNET_OK != GMP_remove_connection (peer, c))
+  {
+    GNUNET_assert (CADET_CONNECTION_NEW == c->state
+                  || CADET_CONNECTION_DESTROYED == c->state);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate: %u\n", c->state);
+    if (NULL != c->t) GMT_debug (c->t);
+  }
+}
+
+
+/**
+ * Bind the connection to the peer and the tunnel to that peer.
+ *
+ * If the peer has no tunnel, create one. Update tunnel and connection
+ * data structres to reflect new status.
+ *
+ * @param c Connection.
+ * @param peer Peer.
+ */
+static void
+add_to_peer (struct CadetConnection *c, struct CadetPeer *peer)
+{
+  GMP_add_tunnel (peer);
+  c->t = GMP_get_tunnel (peer);
+  GMT_add_connection (c->t, c);
+}
+
+
+/**
+ * Builds a path from a PeerIdentity array.
+ *
+ * @param peers PeerIdentity array.
+ * @param size Size of the @c peers array.
+ * @param own_pos Output parameter: own position in the path.
+ *
+ * @return Fixed and shortened path.
+ */
+static struct CadetPeerPath *
+build_path_from_peer_ids (struct GNUNET_PeerIdentity *peers,
+                          unsigned int size,
+                          unsigned int *own_pos)
+{
+  struct CadetPeerPath *path;
+  GNUNET_PEER_Id shortid;
+  unsigned int i;
+  unsigned int j;
+  unsigned int offset;
+
+  /* Create path */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
+  path = path_new (size);
+  *own_pos = 0;
+  offset = 0;
+  for (i = 0; i < size; i++)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  - %u: taking %s\n",
+         i, GNUNET_i2s (&peers[i]));
+    shortid = GNUNET_PEER_intern (&peers[i]);
+
+    /* Check for loops / duplicates */
+    for (j = 0; j < i - offset; j++)
+    {
+      if (path->peers[j] == shortid)
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "    already exists at pos %u\n", j);
+        offset = i - j;
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "    offset now %u\n", offset);
+        GNUNET_PEER_change_rc (shortid, -1);
+      }
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    storing at %u\n", i - offset);
+    path->peers[i - offset] = shortid;
+    if (path->peers[i - offset] == myid)
+      *own_pos = i - offset;
+  }
+  path->length -= offset;
+
+  if (path->peers[*own_pos] != myid)
+  {
+    /* create path: self not found in path through self */
+    GNUNET_break_op (0);
+    path_destroy (path);
+    return NULL;
+  }
+
+  return path;
+}
+
+
+/**
+ * Log receipt of message on stderr (INFO level).
+ *
+ * @param message Message received.
+ * @param peer Peer who sent the message.
+ * @param hash Connection ID.
+ */
+static void
+log_message (const struct GNUNET_MessageHeader *message,
+             const struct GNUNET_PeerIdentity *peer,
+             const struct GNUNET_CADET_Hash *hash)
+{
+  LOG (GNUNET_ERROR_TYPE_INFO, "<-- %s on connection %s from %s\n",
+       GM_m2s (ntohs (message->type)), GNUNET_h2s (GM_h2hc (hash)),
+       GNUNET_i2s (peer));
+}
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * 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)
+ */
+int
+GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
+                   const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_ConnectionCreate *msg;
+  struct GNUNET_PeerIdentity *id;
+  struct GNUNET_CADET_Hash *cid;
+  struct CadetPeerPath *path;
+  struct CadetPeer *dest_peer;
+  struct CadetPeer *orig_peer;
+  struct CadetConnection *c;
+  unsigned int own_pos;
+  uint16_t size;
+
+  /* Check size */
+  size = ntohs (message->size);
+  if (size < sizeof (struct GNUNET_CADET_ConnectionCreate))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+
+  /* Calculate hops */
+  size -= sizeof (struct GNUNET_CADET_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;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
+
+  /* Get parameters */
+  msg = (struct GNUNET_CADET_ConnectionCreate *) message;
+  cid = &msg->cid;
+  log_message (message, peer, cid);
+  id = (struct GNUNET_PeerIdentity *) &msg[1];
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "    origin: %s\n", GNUNET_i2s (id));
+
+  /* Create connection */
+  c = connection_get (cid);
+  if (NULL == c)
+  {
+    path = build_path_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1],
+                                     size, &own_pos);
+    if (NULL == path)
+      return GNUNET_OK;
+    if (0 == own_pos)
+    {
+      GNUNET_break_op (0);
+      path_destroy (path);
+      return GNUNET_OK;
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
+    c = GMC_new (cid, NULL, path_duplicate (path), own_pos);
+    if (NULL == c)
+    {
+      if (path->length - 1 == own_pos)
+      {
+        /* If we are destination, why did the creation fail? */
+        GNUNET_break (0);
+        return GNUNET_OK;
+      }
+      send_broken_unknown (cid, &my_full_id,
+                           GNUNET_PEER_resolve2 (path->peers[own_pos + 1]),
+                           peer);
+      path_destroy (path);
+      return GNUNET_OK;
+    }
+    GMP_add_path_to_all (path, GNUNET_NO);
+    connection_reset_timeout (c, GNUNET_YES);
+  }
+  else
+  {
+    path = path_duplicate (c->path);
+  }
+  if (CADET_CONNECTION_NEW == c->state)
+    connection_change_state (c, CADET_CONNECTION_SENT);
+
+  /* Remember peers */
+  dest_peer = GMP_get (&id[size - 1]);
+  orig_peer = GMP_get (&id[0]);
+
+  /* Is it a connection to us? */
+  if (c->own_pos == path->length - 1)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
+    GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES);
+
+    add_to_peer (c, orig_peer);
+    if (CADET_TUNNEL3_NEW == GMT_get_cstate (c->t))
+      GMT_change_cstate (c->t,  CADET_TUNNEL3_WAITING);
+
+    send_connection_ack (c, GNUNET_NO);
+    if (CADET_CONNECTION_SENT == c->state)
+      connection_change_state (c, CADET_CONNECTION_ACK);
+  }
+  else
+  {
+    /* It's for somebody else! Retransmit. */
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
+    GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
+    GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
+    GMC_send_prebuilt_message (message,
+                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0,
+                               c, GNUNET_YES, GNUNET_YES,
+                               NULL, NULL);
+  }
+  path_destroy (path);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for path confirmations.
+ *
+ * @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)
+ */
+int
+GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
+                    const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_ConnectionACK *msg;
+  struct CadetConnection *c;
+  struct CadetPeerPath *p;
+  struct CadetPeer *pi;
+  enum CadetConnectionState oldstate;
+  int fwd;
+
+  msg = (struct GNUNET_CADET_ConnectionACK *) message;
+  log_message (message, peer, &msg->cid);
+  c = connection_get (&msg->cid);
+  if (NULL == c)
+  {
+    GNUNET_STATISTICS_update (stats, "# control on unknown connection",
+                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
+    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+    return GNUNET_OK;
+  }
+
+  if (GNUNET_NO != c->destroy)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection being destroyed\n");
+    return GNUNET_OK;
+  }
+
+  oldstate = c->state;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n", GNUNET_i2s (peer));
+  pi = GMP_get (peer);
+  if (get_next_hop (c) == pi)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
+    fwd = GNUNET_NO;
+    if (CADET_CONNECTION_SENT == oldstate)
+      connection_change_state (c, CADET_CONNECTION_ACK);
+  }
+  else if (get_prev_hop (c) == pi)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
+    fwd = GNUNET_YES;
+    connection_change_state (c, CADET_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)
+  {
+    GMP_add_path_to_all (p, GNUNET_YES);
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+
+  /* Message for us as creator? */
+  if (GMC_is_origin (c, GNUNET_YES))
+  {
+    if (GNUNET_NO != fwd)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_OK;
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
+
+    /* If just created, cancel the short timeout and start a long one */
+    if (CADET_CONNECTION_SENT == oldstate)
+      connection_reset_timeout (c, GNUNET_YES);
+
+    /* Change connection state */
+    connection_change_state (c, CADET_CONNECTION_READY);
+    send_connection_ack (c, GNUNET_YES);
+
+    /* Change tunnel state, trigger KX */
+    if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t))
+      GMT_change_cstate (c->t, CADET_TUNNEL3_READY);
+
+    return GNUNET_OK;
+  }
+
+  /* Message for us as destination? */
+  if (GMC_is_terminal (c, GNUNET_YES))
+  {
+    if (GNUNET_YES != fwd)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_OK;
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
+
+    /* If just created, cancel the short timeout and start a long one */
+    if (CADET_CONNECTION_ACK == oldstate)
+      connection_reset_timeout (c, GNUNET_NO);
+
+    /* Change tunnel state */
+    if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t))
+      GMT_change_cstate (c->t, CADET_TUNNEL3_READY);
+
+    return GNUNET_OK;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
+  GMC_send_prebuilt_message (message,
+                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0,
+                             c, fwd, GNUNET_YES, NULL, NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for notifications of broken connections.
+ *
+ * @param cls Closure (unused).
+ * @param id Peer identity of sending neighbor.
+ * @param message Message.
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+GMC_handle_broken (void* cls,
+                   const struct GNUNET_PeerIdentity* id,
+                   const struct GNUNET_MessageHeader* message)
+{
+  struct GNUNET_CADET_ConnectionBroken *msg;
+  struct CadetConnection *c;
+  int fwd;
+
+  msg = (struct GNUNET_CADET_ConnectionBroken *) message;
+  log_message (message, id, &msg->cid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
+              GNUNET_i2s (&msg->peer1));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
+              GNUNET_i2s (&msg->peer2));
+  c = connection_get (&msg->cid);
+  if (NULL == c)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  duplicate CONNECTION_BROKEN\n");
+    return GNUNET_OK;
+  }
+
+  fwd = is_fwd (c, id);
+  if (GMC_is_terminal (c, fwd))
+  {
+    struct GNUNET_MessageHeader *out_msg;
+    struct CadetPeer *neighbor;
+    struct CadetPeer *endpoint;
+
+    neighbor = get_hop (c, !fwd);
+    endpoint = GMP_get_short (c->path->peers[c->path->length - 1]);
+    path_invalidate (c->path);
+    GMP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2);
+    c->state = CADET_CONNECTION_DESTROYED;
+    while (NULL != (out_msg = GMP_connection_pop (neighbor, c)))
+    {
+      GNUNET_assert (NULL ==
+                     GMT_send_prebuilt_message (out_msg, c->t, NULL, 
GNUNET_YES,
+                                                NULL, NULL));
+    }
+
+    GMC_destroy (c);
+  }
+  else
+  {
+    GMC_send_prebuilt_message (message,
+                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0,
+                               c, fwd, GNUNET_YES, NULL, NULL);
+    c->destroy = GNUNET_YES;
+    connection_cancel_queues (c, !fwd);
+  }
+
+  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)
+ */
+int
+GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
+                    const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_ConnectionDestroy *msg;
+  struct CadetConnection *c;
+  int fwd;
+
+  msg = (struct GNUNET_CADET_ConnectionDestroy *) message;
+  log_message (message, peer, &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 connection",
+                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection unknown: already 
destroyed?\n");
+    return GNUNET_OK;
+  }
+  fwd = is_fwd (c, peer);
+  if (GNUNET_SYSERR == fwd)
+  {
+    GNUNET_break_op (0); /* FIXME */
+    return GNUNET_OK;
+  }
+  if (GNUNET_NO == GMC_is_terminal (c, fwd))
+    GMC_send_prebuilt_message (message,
+                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0,
+                               c, fwd, GNUNET_YES, NULL, NULL);
+  else if (0 == c->pending_messages)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  directly destroying connection!\n");
+    GMC_destroy (c);
+    return GNUNET_OK;
+  }
+  c->destroy = GNUNET_YES;
+  c->state = CADET_CONNECTION_DESTROYED;
+  if (NULL != c->t)
+  {
+    GMT_remove_connection (c->t, c);
+    c->t = NULL;
+  }
+
+  return GNUNET_OK;
+}
+
+/**
+ * Generic handler for cadet network encrypted traffic.
+ *
+ * @param peer Peer identity this notification is about.
+ * @param msg Encrypted message.
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer,
+                       const struct GNUNET_CADET_Encrypted *msg)
+{
+  struct CadetConnection *c;
+  struct CadetPeer *neighbor;
+  struct CadetFlowControl *fc;
+  GNUNET_PEER_Id peer_id;
+  uint32_t pid;
+  uint32_t ttl;
+  size_t size;
+  int fwd;
+
+  log_message (&msg->header, peer, &msg->cid);
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size <
+      sizeof (struct GNUNET_CADET_Encrypted) +
+      sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+
+  /* Check connection */
+  c = connection_get (&msg->cid);
+  if (NULL == c)
+  {
+    GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "enc on unknown connection %s\n",
+         GNUNET_h2s (GM_h2hc (&msg->cid)));
+    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+    return GNUNET_OK;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection %s\n", GMC_2s (c));
+
+  /* Check if origin is as expected */
+  neighbor = get_prev_hop (c);
+  peer_id = GNUNET_PEER_search (peer);
+  if (peer_id == GMP_get_short_id (neighbor))
+  {
+    fwd = GNUNET_YES;
+  }
+  else
+  {
+    neighbor = get_next_hop (c);
+    if (peer_id == GMP_get_short_id (neighbor))
+    {
+      fwd = GNUNET_NO;
+    }
+    else
+    {
+      /* Unexpected peer sending traffic on a connection. */
+      GNUNET_break_op (0);
+      return GNUNET_OK;
+    }
+  }
+
+  /* Check PID */
+  fc = fwd ? &c->bck_fc : &c->fwd_fc;
+  pid = ntohl (msg->pid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n",
+       pid, fc->last_pid_recv + 1);
+  if (GM_is_pid_bigger (pid, fc->last_ack_sent))
+  {
+    GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
+    GNUNET_break_op (0);
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Received PID %u, (prev %u), ACK %u\n",
+         pid, fc->last_pid_recv, fc->last_ack_sent);
+    return GNUNET_OK;
+  }
+  if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv))
+  {
+    GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+                " PID %u not expected (%u+), dropping!\n",
+                pid, fc->last_pid_recv + 1);
+    return GNUNET_OK;
+  }
+  if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state)
+    connection_change_state (c, CADET_CONNECTION_READY);
+  connection_reset_timeout (c, fwd);
+  fc->last_pid_recv = pid;
+
+  /* Is this message for us? */
+  if (GMC_is_terminal (c, fwd))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
+    GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
+
+    if (NULL == c->t)
+    {
+      GNUNET_break (GNUNET_NO != c->destroy);
+      return GNUNET_OK;
+    }
+    fc->last_pid_recv = pid;
+    GMT_handle_encrypted (c->t, msg);
+    GMC_send_ack (c, fwd, GNUNET_NO);
+    return GNUNET_OK;
+  }
+
+  /* Message not for us: forward to next hop */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
+  ttl = ntohl (msg->ttl);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
+  if (ttl == 0)
+  {
+    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
+    GMC_send_ack (c, fwd, GNUNET_NO);
+    return GNUNET_OK;
+  }
+
+  GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
+  GMC_send_prebuilt_message (&msg->header,
+                             GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0,
+                             c, fwd, GNUNET_NO, NULL, NULL);
+
+  return GNUNET_OK;
+}
+
+/**
+ * Generic handler for cadet network encrypted traffic.
+ *
+ * @param peer Peer identity this notification is about.
+ * @param msg Encrypted message.
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_cadet_kx (const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_CADET_KX *msg)
+{
+  struct CadetConnection *c;
+  struct CadetPeer *neighbor;
+  GNUNET_PEER_Id peer_id;
+  size_t size;
+  int fwd;
+
+  log_message (&msg->header, peer, &msg->cid);
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size <
+      sizeof (struct GNUNET_CADET_KX) +
+      sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+
+  /* Check connection */
+  c = connection_get (&msg->cid);
+  if (NULL == c)
+  {
+    GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "kx on unknown connection %s\n",
+         GNUNET_h2s (GM_h2hc (&msg->cid)));
+    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+    return GNUNET_OK;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", GMC_2s (c));
+
+  /* Check if origin is as expected */
+  neighbor = get_prev_hop (c);
+  peer_id = GNUNET_PEER_search (peer);
+  if (peer_id == GMP_get_short_id (neighbor))
+  {
+    fwd = GNUNET_YES;
+  }
+  else
+  {
+    neighbor = get_next_hop (c);
+    if (peer_id == GMP_get_short_id (neighbor))
+    {
+      fwd = GNUNET_NO;
+    }
+    else
+    {
+      /* Unexpected peer sending traffic on a connection. */
+      GNUNET_break_op (0);
+      return GNUNET_OK;
+    }
+  }
+
+  /* Count as connection confirmation. */
+  if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state)
+  {
+    connection_change_state (c, CADET_CONNECTION_READY);
+    if (NULL != c->t)
+    {
+      if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t))
+        GMT_change_cstate (c->t, CADET_TUNNEL3_READY);
+    }
+  }
+  connection_reset_timeout (c, fwd);
+
+  /* Is this message for us? */
+  if (GMC_is_terminal (c, fwd))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
+    GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
+    if (NULL == c->t)
+    {
+      GNUNET_break (0);
+      return GNUNET_OK;
+    }
+    GMT_handle_kx (c->t, &msg[1].header);
+    return GNUNET_OK;
+  }
+
+  /* Message not for us: forward to next hop */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
+  GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
+  GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX, 0,
+                             c, fwd, GNUNET_NO, NULL, NULL);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Core handler for encrypted cadet network traffic (channel mgmt, data).
+ *
+ * @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)
+ */
+int
+GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_MessageHeader *message)
+{
+  return handle_cadet_encrypted (peer,
+                                (struct GNUNET_CADET_Encrypted *)message);
+}
+
+
+/**
+ * Core handler for key exchange traffic (ephemeral key, ping, pong).
+ *
+ * @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)
+ */
+int
+GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
+               const struct GNUNET_MessageHeader *message)
+{
+  return handle_cadet_kx (peer,
+                         (struct GNUNET_CADET_KX *) message);
+}
+
+
+/**
+ * Core handler for cadet 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)
+ */
+int
+GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_ACK *msg;
+  struct CadetConnection *c;
+  struct CadetFlowControl *fc;
+  GNUNET_PEER_Id id;
+  uint32_t ack;
+  int fwd;
+
+  msg = (struct GNUNET_CADET_ACK *) message;
+  log_message (message, peer, &msg->cid);
+  c = connection_get (&msg->cid);
+  if (NULL == c)
+  {
+    GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
+                              GNUNET_NO);
+    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+    return GNUNET_OK;
+  }
+
+  /* Is this a forward or backward ACK? */
+  id = GNUNET_PEER_search (peer);
+  if (GMP_get_short_id (get_next_hop (c)) == id)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
+    fc = &c->fwd_fc;
+    fwd = GNUNET_YES;
+  }
+  else if (GMP_get_short_id (get_prev_hop (c)) == id)
+  {
+    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);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
+              ack, fc->last_ack_recv);
+  if (GM_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 &&
+      GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
+  {
+    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;
+}
+
+
+/**
+ * Core handler for cadet 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)
+ */
+int
+GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
+                 const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_Poll *msg;
+  struct CadetConnection *c;
+  struct CadetFlowControl *fc;
+  GNUNET_PEER_Id id;
+  uint32_t pid;
+  int fwd;
+
+  msg = (struct GNUNET_CADET_Poll *) message;
+  log_message (message, peer, &msg->cid);
+  c = connection_get (&msg->cid);
+  if (NULL == c)
+  {
+    GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
+                              GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL message on unknown connection %s!\n",
+         GNUNET_h2s (GM_h2hc (&msg->cid)));
+    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+    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 (GMP_get_short_id (get_next_hop (c)) == id)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
+    fc = &c->fwd_fc;
+  }
+  else if (GMP_get_short_id (get_prev_hop (c)) == id)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
+    fc = &c->bck_fc;
+  }
+  else
+  {
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  }
+
+  pid = ntohl (msg->pid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n", pid, fc->last_pid_recv);
+  fc->last_pid_recv = pid;
+  fwd = fc == &c->bck_fc;
+  GMC_send_ack (c, fwd, GNUNET_YES);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * 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 fwd Is this a fwd ACK? (will go dest->root).
+ * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
+ */
+void
+GMC_send_ack (struct CadetConnection *c, int fwd, int force)
+{
+  unsigned int buffer;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "GMC send %s ACK on %s\n",
+       GM_f2s (fwd), GMC_2s (c));
+
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  if (GNUNET_NO != c->destroy)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  being destroyed, why bother...\n");
+    return;
+  }
+
+  /* Get available buffer space */
+  if (GMC_is_terminal (c, fwd))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all channels\n");
+    buffer = GMT_get_channels_buffer (c->t);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
+    buffer = GMC_get_buffer (c, fwd);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
+  if (0 == buffer && GNUNET_NO == force)
+    return;
+
+  /* Send available buffer space */
+  if (GMC_is_origin (c, fwd))
+  {
+    GNUNET_assert (NULL != c->t);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channels...\n");
+    GMT_unchoke_channels (c->t);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
+    send_ack (c, buffer, fwd, force);
+  }
+}
+
+
+/**
+ * Initialize the connections subsystem
+ *
+ * @param c Configuration handle.
+ */
+void
+GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE",
+                                             &max_msgs_queue))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "CADET", "MAX_MSGS_QUEUE", "MISSING");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS",
+                                             &max_connections))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "CADET", "MAX_CONNECTIONS", "MISSING");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c, "CADET", 
"REFRESH_CONNECTION_TIME",
+                                           &refresh_connection_time))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "CADET", "REFRESH_CONNECTION_TIME", "MISSING");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  create_connection_time = GNUNET_TIME_UNIT_SECONDS;
+  connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO);
+}
+
+
+/**
+ * Destroy each connection on shutdown.
+ *
+ * @param cls Closure (unused).
+ * @param key Current key code (CID, unused).
+ * @param value Value in the hash map (connection)
+ *
+ * @return #GNUNET_YES, because we should continue to iterate,
+ */
+static int
+shutdown_iterator (void *cls,
+                   const struct GNUNET_HashCode *key,
+                   void *value)
+{
+  struct CadetConnection *c = value;
+
+  GMC_destroy (c);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Shut down the connections subsystem.
+ */
+void
+GMC_shutdown (void)
+{
+  GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, 
NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (connections);
+  connections = NULL;
+}
+
+
+struct CadetConnection *
+GMC_new (const struct GNUNET_CADET_Hash *cid,
+         struct CadetTunnel3 *t,
+         struct CadetPeerPath *p,
+         unsigned int own_pos)
+{
+  struct CadetConnection *c;
+
+  c = GNUNET_new (struct CadetConnection);
+  c->id = *cid;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multihashmap_put (connections,
+                                                    GMC_get_h (c), c,
+                                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  fc_init (&c->fwd_fc);
+  fc_init (&c->bck_fc);
+  c->fwd_fc.c = c;
+  c->bck_fc.c = c;
+
+  c->t = t;
+  GNUNET_assert (own_pos <= p->length - 1);
+  c->own_pos = own_pos;
+  c->path = p;
+  p->c = c;
+
+  if (GNUNET_OK != register_neighbors (c))
+  {
+    if (0 == own_pos)
+    {
+      path_invalidate (c->path);
+      c->t = NULL;
+      c->path = NULL;
+    }
+    GMC_destroy (c);
+    return NULL;
+  }
+
+  return c;
+}
+
+
+void
+GMC_destroy (struct CadetConnection *c)
+{
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */
+    return;            /* -> message_sent -> GMC_destroy. Don't loop. */
+  c->destroy = 2;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n",
+       &c->fwd_fc, &c->bck_fc);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
+       c->fwd_fc.poll_task, c->bck_fc.poll_task);
+
+  /* Cancel all traffic */
+  if (NULL != c->path)
+  {
+    connection_cancel_queues (c, GNUNET_YES);
+    connection_cancel_queues (c, GNUNET_NO);
+    unregister_neighbors (c);
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
+       c->fwd_fc.poll_task, c->bck_fc.poll_task);
+
+  /* Cancel maintainance task (keepalive/timeout) */
+  if (NULL != c->fwd_fc.poll_msg)
+  {
+    GMC_cancel (c->fwd_fc.poll_msg);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n");
+  }
+  if (NULL != c->bck_fc.poll_msg)
+  {
+    GMC_cancel (c->bck_fc.poll_msg);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n");
+  }
+
+  /* Delete from tunnel */
+  if (NULL != c->t)
+    GMT_remove_connection (c->t, c);
+
+  if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES) && NULL != c->path)
+    path_destroy (c->path);
+  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
+    GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
+  if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
+    GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
+  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task)
+  {
+    GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n");
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task)
+  {
+    GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n");
+  }
+
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (connections,
+                                                      GMC_get_h (c), c));
+
+  GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
+  GNUNET_free (c);
+}
+
+/**
+ * Get the connection ID.
+ *
+ * @param c Connection to get the ID from.
+ *
+ * @return ID of the connection.
+ */
+const struct GNUNET_CADET_Hash *
+GMC_get_id (const struct CadetConnection *c)
+{
+  return &c->id;
+}
+
+
+/**
+ * Get the connection ID.
+ *
+ * @param c Connection to get the ID from.
+ *
+ * @return ID of the connection.
+ */
+const struct GNUNET_HashCode *
+GMC_get_h (const struct CadetConnection *c)
+{
+  return GM_h2hc (&c->id);
+}
+
+
+/**
+ * Get the connection path.
+ *
+ * @param c Connection to get the path from.
+ *
+ * @return path used by the connection.
+ */
+const struct CadetPeerPath *
+GMC_get_path (const struct CadetConnection *c)
+{
+  if (GNUNET_NO == c->destroy)
+    return c->path;
+  return NULL;
+}
+
+
+/**
+ * Get the connection state.
+ *
+ * @param c Connection to get the state from.
+ *
+ * @return state of the connection.
+ */
+enum CadetConnectionState
+GMC_get_state (const struct CadetConnection *c)
+{
+  return c->state;
+}
+
+/**
+ * Get the connection tunnel.
+ *
+ * @param c Connection to get the tunnel from.
+ *
+ * @return tunnel of the connection.
+ */
+struct CadetTunnel3 *
+GMC_get_tunnel (const struct CadetConnection *c)
+{
+  return c->t;
+}
+
+
+/**
+ * Get free buffer space in a connection.
+ *
+ * @param c Connection.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Free buffer space [0 - max_msgs_queue/max_connections]
+ */
+unsigned int
+GMC_get_buffer (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+
+  return (fc->queue_max - fc->queue_n);
+}
+
+/**
+ * Get how many messages have we allowed to send to us from a direction.
+ *
+ * @param c Connection.
+ * @param fwd Are we asking about traffic from FWD (BCK messages)?
+ *
+ * @return last_ack_sent - last_pid_recv
+ */
+unsigned int
+GMC_get_allowed (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent))
+  {
+    return 0;
+  }
+  return (fc->last_ack_sent - fc->last_pid_recv);
+}
+
+/**
+ * Get messages queued in a connection.
+ *
+ * @param c Connection.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Number of messages queued.
+ */
+unsigned int
+GMC_get_qn (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+
+  return fc->queue_n;
+}
+
+
+/**
+ * Get next PID to use.
+ *
+ * @param c Connection.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Last PID used + 1.
+ */
+unsigned int
+GMC_get_pid (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+
+  return fc->last_pid_sent + 1;
+}
+
+
+/**
+ * Allow the connection to advertise a buffer of the given size.
+ *
+ * The connection will send an @c fwd ACK message (so: in direction !fwd)
+ * allowing up to last_pid_recv + buffer.
+ *
+ * @param c Connection.
+ * @param buffer How many more messages the connection can accept.
+ * @param fwd Is this about FWD traffic? (The ack will go dest->root).
+ */
+void
+GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  allowing %s %u messages %s\n",
+       GMC_2s (c), buffer, GM_f2s (fwd));
+  send_ack (c, buffer, fwd, GNUNET_NO);
+}
+
+
+/**
+ * Notify other peers on a connection of a broken link. Mark connections
+ * to destroy after all traffic has been sent.
+ *
+ * @param c Connection on which there has been a disconnection.
+ * @param peer Peer that disconnected.
+ */
+void
+GMC_notify_broken (struct CadetConnection *c,
+                   struct CadetPeer *peer)
+{
+  int fwd;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       " notify broken on %s due to %s disconnect\n",
+       GMC_2s (c), GMP_2s (peer));
+
+  fwd = peer == get_prev_hop (c);
+
+  if (GNUNET_YES == GMC_is_terminal (c, fwd))
+  {
+    /* Local shutdown, no one to notify about this. */
+    GMC_destroy (c);
+    return;
+  }
+  if (GNUNET_NO == c->destroy)
+    send_broken (c, &my_full_id, GMP_get_id (peer), fwd);
+
+  /* Connection will have at least one pending message
+   * (the one we just scheduled), so no point in checking whether to
+   * destroy immediately. */
+  c->destroy = GNUNET_YES;
+  c->state = CADET_CONNECTION_DESTROYED;
+
+  /**
+   * Cancel all queues, if no message is left, connection will be destroyed.
+   */
+  connection_cancel_queues (c, !fwd);
+
+  return;
+}
+
+
+/**
+ * Is this peer the first one on the connection?
+ *
+ * @param c Connection.
+ * @param fwd Is this about fwd traffic?
+ *
+ * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
+ */
+int
+GMC_is_origin (struct CadetConnection *c, int fwd)
+{
+  if (!fwd && c->path->length - 1 == c->own_pos )
+    return GNUNET_YES;
+  if (fwd && 0 == c->own_pos)
+    return GNUNET_YES;
+  return GNUNET_NO;
+}
+
+
+/**
+ * Is this peer the last one on the connection?
+ *
+ * @param c Connection.
+ * @param fwd Is this about fwd traffic?
+ *            Note that the ROOT is the terminal for BCK traffic!
+ *
+ * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
+ */
+int
+GMC_is_terminal (struct CadetConnection *c, int fwd)
+{
+  return GMC_is_origin (c, !fwd);
+}
+
+
+/**
+ * See if we are allowed to send by the next hop in the given direction.
+ *
+ * @param c Connection.
+ * @param fwd Is this about fwd traffic?
+ *
+ * @return #GNUNET_YES in case it's OK to send.
+ */
+int
+GMC_is_sendable (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " checking sendability of %s traffic on %s\n",
+       GM_f2s (fwd), GMC_2s (c));
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return GNUNET_YES;
+  }
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       " last ack recv: %u, last pid sent: %u\n",
+       fc->last_ack_recv, fc->last_pid_sent);
+  if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n");
+    return GNUNET_YES;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n");
+  return GNUNET_NO;
+}
+
+
+/**
+ * Check if this connection is a direct one (never trim a direct connection).
+ *
+ * @param c Connection.
+ *
+ * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
+ */
+int
+GMC_is_direct (struct CadetConnection *c)
+{
+  return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO;
+}
+
+/**
+ * Sends an already built message on a connection, properly registering
+ * all used resources.
+ *
+ * @param message Message to send. Function makes a copy of it.
+ *                If message is not hop-by-hop, decrements TTL of copy.
+ * @param payload_type Type of payload, in case the message is encrypted.
+ * @param c Connection on which this message is transmitted.
+ * @param fwd Is this a fwd message?
+ * @param force Force the connection to accept the message (buffer overfill).
+ * @param cont Continuation called once message is sent. Can be NULL.
+ * @param cont_cls Closure for @c cont.
+ *
+ * @return Handle to cancel the message before it's sent.
+ *         NULL on error or if @c cont is NULL.
+ *         Invalid on @c cont call.
+ */
+struct CadetConnectionQueue *
+GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                           uint16_t payload_type, uint32_t payload_id,
+                           struct CadetConnection *c, int fwd, int force,
+                           GMC_sent cont, void *cont_cls)
+{
+  struct CadetFlowControl *fc;
+  struct CadetConnectionQueue *q;
+  void *data;
+  size_t size;
+  uint16_t type;
+  int droppable;
+
+  size = ntohs (message->size);
+  data = GNUNET_malloc (size);
+  memcpy (data, message, size);
+  type = ntohs (message->type);
+  LOG (GNUNET_ERROR_TYPE_INFO, "--> %s (%s %u) on connection %s (%u bytes)\n",
+       GM_m2s (type), GM_m2s (payload_type), payload_id, GMC_2s (c), size);
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  droppable = GNUNET_NO == force;
+  switch (type)
+  {
+    struct GNUNET_CADET_Encrypted *emsg;
+    struct GNUNET_CADET_KX        *kmsg;
+    struct GNUNET_CADET_ACK       *amsg;
+    struct GNUNET_CADET_Poll      *pmsg;
+    struct GNUNET_CADET_ConnectionDestroy *dmsg;
+    struct GNUNET_CADET_ConnectionBroken  *bmsg;
+    uint32_t ttl;
+
+    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+      emsg = (struct GNUNET_CADET_Encrypted *) data;
+      ttl = ntohl (emsg->ttl);
+      if (0 == ttl)
+      {
+        GNUNET_break_op (0);
+        GNUNET_free (data);
+        return NULL;
+      }
+      emsg->cid = c->id;
+      emsg->ttl = htonl (ttl - 1);
+      emsg->pid = htonl (0);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  Q_N+ %p %u\n", fc, fc->queue_n);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "     ack recv %u\n", fc->last_ack_recv);
+      if (GNUNET_YES == droppable)
+      {
+        fc->queue_n++;
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "  not droppable, Q_N stays the same\n");
+      }
+      if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
+      {
+        GMC_start_poll (c, fwd);
+      }
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_KX:
+      kmsg = (struct GNUNET_CADET_KX *) data;
+      kmsg->cid = c->id;
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+      amsg = (struct GNUNET_CADET_ACK *) data;
+      amsg->cid = c->id;
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
+      droppable = GNUNET_NO;
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+      pmsg = (struct GNUNET_CADET_Poll *) data;
+      pmsg->cid = c->id;
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
+      droppable = GNUNET_NO;
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
+      dmsg = (struct GNUNET_CADET_ConnectionDestroy *) data;
+      dmsg->cid = c->id;
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
+      bmsg = (struct GNUNET_CADET_ConnectionBroken *) data;
+      bmsg->cid = c->id;
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+      GNUNET_break (0);
+      /* falltrough */
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+      break;
+
+    default:
+      GNUNET_break (0);
+      GNUNET_free (data);
+      return NULL;
+  }
+
+  if (fc->queue_n > fc->queue_max && droppable)
+  {
+    GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
+                              1, GNUNET_NO);
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+                "queue full: %u/%u\n",
+                fc->queue_n, fc->queue_max);
+    if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type)
+    {
+      fc->queue_n--;
+    }
+    GNUNET_free (data);
+    return NULL; /* Drop this message */
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u\n", c, c->pending_messages);
+//   c->pending_messages++;
+
+  q = GNUNET_new (struct CadetConnectionQueue);
+  q->forced = !droppable;
+  q->q = GMP_queue_add (get_hop (c, fwd), data, type, payload_type, payload_id,
+                        size, c, fwd, &conn_message_sent, q);
+  if (NULL == q->q)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING dropping msg on %s\n", GMC_2s (c));
+    GNUNET_free (data);
+    GNUNET_free (q);
+    return NULL;
+  }
+  q->cont = cont;
+  q->cont_cls = cont_cls;
+  return (NULL == cont) ? NULL : q;
+}
+
+
+/**
+ * Cancel a previously sent message while it's in the queue.
+ *
+ * ONLY can be called before the continuation given to the send function
+ * is called. Once the continuation is called, the message is no longer in the
+ * queue.
+ *
+ * @param q Handle to the queue.
+ */
+void
+GMC_cancel (struct CadetConnectionQueue *q)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "!  GMC cancel message\n");
+
+  /* queue destroy calls message_sent, which calls q->cont and frees q */
+  GMP_queue_destroy (q->q, GNUNET_YES, GNUNET_NO, 0);
+}
+
+
+/**
+ * Sends a CREATE CONNECTION message for a path to a peer.
+ * Changes the connection and tunnel states if necessary.
+ *
+ * @param connection Connection to create.
+ */
+void
+GMC_send_create (struct CadetConnection *connection)
+{
+  enum CadetTunnel3CState state;
+  size_t size;
+
+  size = sizeof (struct GNUNET_CADET_ConnectionCreate);
+  size += connection->path->length * sizeof (struct GNUNET_PeerIdentity);
+
+  LOG (GNUNET_ERROR_TYPE_INFO, "===> %s on connection %s  (%u bytes)\n",
+       GM_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE),
+       GMC_2s (connection), size);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u (create)\n",
+       connection, connection->pending_messages);
+  connection->pending_messages++;
+
+  connection->maintenance_q =
+    GMP_queue_add (get_next_hop (connection), NULL,
+                   GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
+                   GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0,
+                   size, connection, GNUNET_YES, &conn_message_sent, NULL);
+
+  state = GMT_get_cstate (connection->t);
+  if (CADET_TUNNEL3_SEARCHING == state || CADET_TUNNEL3_NEW == state)
+    GMT_change_cstate (connection->t, CADET_TUNNEL3_WAITING);
+  if (CADET_CONNECTION_NEW == connection->state)
+    connection_change_state (connection, CADET_CONNECTION_SENT);
+}
+
+
+/**
+ * Send a message to all peers in this connection that the connection
+ * is no longer valid.
+ *
+ * If some peer should not receive the message, it should be zero'ed out
+ * before calling this function.
+ *
+ * @param c The connection whose peers to notify.
+ */
+void
+GMC_send_destroy (struct CadetConnection *c)
+{
+  struct GNUNET_CADET_ConnectionDestroy msg;
+
+  if (GNUNET_YES == c->destroy)
+    return;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);;
+  msg.cid = c->id;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+              "  sending connection destroy for connection %s\n",
+              GMC_2s (c));
+
+  if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
+    GMC_send_prebuilt_message (&msg.header,
+                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0,
+                               c, GNUNET_YES, GNUNET_YES, NULL, NULL);
+  if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
+    GMC_send_prebuilt_message (&msg.header,
+                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0,
+                               c, GNUNET_NO, GNUNET_YES, NULL, NULL);
+  c->destroy = GNUNET_YES;
+  c->state = CADET_CONNECTION_DESTROYED;
+}
+
+
+/**
+ * @brief Start a polling timer for the connection.
+ *
+ * When a neighbor does not accept more traffic on the connection it could be
+ * caused by a simple congestion or by a lost ACK. Polling enables to check
+ * for the lastest ACK status for a connection.
+ *
+ * @param c Connection.
+ * @param fwd Should we poll in the FWD direction?
+ */
+void
+GMC_start_poll (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL %s requested\n",
+       GM_f2s (fwd));
+  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task || NULL != fc->poll_msg)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   not needed (%u, %p)\n",
+         fc->poll_task, fc->poll_msg);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL started on request\n");
+  fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
+                                                &connection_poll,
+                                                fc);
+}
+
+
+/**
+ * @brief Stop polling a connection for ACKs.
+ *
+ * Once we have enough ACKs for future traffic, polls are no longer necessary.
+ *
+ * @param c Connection.
+ * @param fwd Should we stop the poll in the FWD direction?
+ */
+void
+GMC_stop_poll (struct CadetConnection *c, int fwd)
+{
+  struct CadetFlowControl *fc;
+
+  fc = fwd ? &c->fwd_fc : &c->bck_fc;
+  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
+  {
+    GNUNET_SCHEDULER_cancel (fc->poll_task);
+    fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+}
+
+/**
+ * Get a (static) string for a connection.
+ *
+ * @param c Connection.
+ */
+const char *
+GMC_2s (const struct CadetConnection *c)
+{
+  if (NULL == c)
+    return "NULL";
+
+  if (NULL != c->t)
+  {
+    static char buf[128];
+
+    sprintf (buf, "%s (->%s)",
+             GNUNET_h2s (GM_h2hc (GMC_get_id (c))), GMT_2s (c->t));
+    return buf;
+  }
+  return GNUNET_h2s (GM_h2hc (&c->id));
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_connection.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_connection.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_connection.h                          
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_connection.h  2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,566 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_connection.h
+ * @brief cadet service; dealing with connections
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GMC (Gnunet Cadet 
Connection)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
+#define GNUNET_SERVICE_CADET_CONNECTION_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_util_lib.h"
+
+
+/**
+ * All the states a connection can be in.
+ */
+enum CadetConnectionState
+{
+  /**
+   * Uninitialized status, should never appear in operation.
+   */
+  CADET_CONNECTION_NEW,
+
+  /**
+   * Connection create message sent, waiting for ACK.
+   */
+  CADET_CONNECTION_SENT,
+
+  /**
+   * Connection ACK sent, waiting for ACK.
+   */
+  CADET_CONNECTION_ACK,
+
+  /**
+   * Connection confirmed, ready to carry traffic.
+   */
+  CADET_CONNECTION_READY,
+
+  /**
+   * Connection to be destroyed, just waiting to empty queues.
+   */
+  CADET_CONNECTION_DESTROYED,
+};
+
+
+/**
+ * Struct containing all information regarding a connection to a peer.
+ */
+struct CadetConnection;
+
+/**
+ * Handle for messages queued but not yet sent.
+ */
+struct CadetConnectionQueue;
+
+#include "cadet_path.h"
+#include "gnunet-service-cadet_channel.h"
+#include "gnunet-service-cadet_peer.h"
+
+
+
+/**
+ * Callback called when a queued message is sent.
+ *
+ * @param cls Closure.
+ * @param c Connection this message was on.
+ * @param type Type of message sent.
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ */
+typedef void (*GMC_sent) (void *cls,
+                          struct CadetConnection *c,
+                          struct CadetConnectionQueue *q,
+                          uint16_t type, int fwd, size_t size);
+
+/**
+ * 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)
+ */
+int
+GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
+                   const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for path confirmations.
+ *
+ * @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)
+ */
+int
+GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
+                    const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for notifications of broken paths
+ *
+ * @param cls Closure (unused).
+ * @param id Peer identity of sending neighbor.
+ * @param message Message.
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+GMC_handle_broken (void* cls,
+                   const struct GNUNET_PeerIdentity* id,
+                   const struct GNUNET_MessageHeader* message);
+
+/**
+ * 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)
+ */
+int
+GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
+                    const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for encrypted cadet network traffic (channel mgmt, data).
+ *
+ * @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)
+ */
+int
+GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for key exchange traffic (ephemeral key, ping, pong).
+ *
+ * @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)
+ */
+int
+GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
+               const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for cadet 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)
+ */
+int
+GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for cadet 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)
+ */
+int
+GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
+                 const struct GNUNET_MessageHeader *message);
+
+/**
+ * Core handler for cadet 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.
+ */
+int
+GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_MessageHeader *message);
+
+/**
+ * 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 fwd Is this a fwd ACK? (will go dest->root).
+ * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
+ */
+void
+GMC_send_ack (struct CadetConnection *c, int fwd, int force);
+
+/**
+ * Initialize the connections subsystem
+ *
+ * @param c Configuration handle.
+ */
+void
+GMC_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+/**
+ * Shut down the connections subsystem.
+ */
+void
+GMC_shutdown (void);
+
+/**
+ * Create a connection.
+ *
+ * @param cid Connection ID (either created locally or imposed remotely).
+ * @param t Tunnel this connection belongs to (or NULL);
+ * @param p Path this connection has to use.
+ * @param own_pos Own position in the @c p path.
+ *
+ * @return Newly created connection, NULL in case of error (own id not in 
path).
+ */
+struct CadetConnection *
+GMC_new (const struct GNUNET_CADET_Hash *cid,
+         struct CadetTunnel3 *t,
+         struct CadetPeerPath *p,
+         unsigned int own_pos);
+
+/**
+ * Connection is no longer needed: destroy it.
+ *
+ * Cancels all pending traffic (including possible DESTROY messages), all
+ * maintenance tasks and removes the connection from neighbor peers and tunnel.
+ *
+ * @param c Connection to destroy.
+ */
+void
+GMC_destroy (struct CadetConnection *c);
+
+/**
+ * Get the connection ID.
+ *
+ * @param c Connection to get the ID from.
+ *
+ * @return ID of the connection.
+ */
+const struct GNUNET_CADET_Hash *
+GMC_get_id (const struct CadetConnection *c);
+
+
+/**
+ * Get a hash for the connection ID.
+ *
+ * @param c Connection to get the hash.
+ *
+ * @return Hash expanded from the ID of the connection.
+ */
+const struct GNUNET_HashCode *
+GMC_get_h (const struct CadetConnection *c);
+
+
+/**
+ * Get the connection path.
+ *
+ * @param c Connection to get the path from.
+ *
+ * @return path used by the connection.
+ */
+const struct CadetPeerPath *
+GMC_get_path (const struct CadetConnection *c);
+
+/**
+ * Get the connection state.
+ *
+ * @param c Connection to get the state from.
+ *
+ * @return state of the connection.
+ */
+enum CadetConnectionState
+GMC_get_state (const struct CadetConnection *c);
+
+/**
+ * Get the connection tunnel.
+ *
+ * @param c Connection to get the tunnel from.
+ *
+ * @return tunnel of the connection.
+ */
+struct CadetTunnel3 *
+GMC_get_tunnel (const struct CadetConnection *c);
+
+/**
+ * Get free buffer space in a connection.
+ *
+ * @param c Connection.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Free buffer space [0 - max_msgs_queue/max_connections]
+ */
+unsigned int
+GMC_get_buffer (struct CadetConnection *c, int fwd);
+
+/**
+ * Get how many messages have we allowed to send to us from a direction.
+ *
+ * @param c Connection.
+ * @param fwd Are we asking about traffic from FWD (BCK messages)?
+ *
+ * @return last_ack_sent - last_pid_recv
+ */
+unsigned int
+GMC_get_allowed (struct CadetConnection *c, int fwd);
+
+/**
+ * Get messages queued in a connection.
+ *
+ * @param c Connection.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Number of messages queued.
+ */
+unsigned int
+GMC_get_qn (struct CadetConnection *c, int fwd);
+
+/**
+ * Get next PID to use.
+ *
+ * @param c Connection.
+ * @param fwd Is query about FWD traffic?
+ *
+ * @return Last PID used + 1.
+ */
+unsigned int
+GMC_get_pid (struct CadetConnection *c, int fwd);
+
+/**
+ * Allow the connection to advertise a buffer of the given size.
+ *
+ * The connection will send an @c fwd ACK message (so: in direction !fwd)
+ * allowing up to last_pid_recv + buffer.
+ *
+ * @param c Connection.
+ * @param buffer How many more messages the connection can accept.
+ * @param fwd Is this about FWD traffic? (The ack will go dest->root).
+ */
+void
+GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd);
+
+/**
+ * Send FWD keepalive packets for a connection.
+ *
+ * @param cls Closure (connection for which to send the keepalive).
+ * @param tc Notification context.
+ */
+void
+GMC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Send BCK keepalive packets for a connection.
+ *
+ * @param cls Closure (connection for which to send the keepalive).
+ * @param tc Notification context.
+ */
+void
+GMC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Notify other peers on a connection of a broken link. Mark connections
+ * to destroy after all traffic has been sent.
+ *
+ * @param c Connection on which there has been a disconnection.
+ * @param peer Peer that disconnected.
+ */
+void
+GMC_notify_broken (struct CadetConnection *c,
+                   struct CadetPeer *peer);
+
+/**
+ * Is this peer the first one on the connection?
+ *
+ * @param c Connection.
+ * @param fwd Is this about fwd traffic?
+ *
+ * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
+ */
+int
+GMC_is_origin (struct CadetConnection *c, int fwd);
+
+/**
+ * Is this peer the last one on the connection?
+ *
+ * @param c Connection.
+ * @param fwd Is this about fwd traffic?
+ *            Note that the ROOT is the terminal for BCK traffic!
+ *
+ * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
+ */
+int
+GMC_is_terminal (struct CadetConnection *c, int fwd);
+
+/**
+ * See if we are allowed to send by the next hop in the given direction.
+ *
+ * @param c Connection.
+ * @param fwd Is this about fwd traffic?
+ *
+ * @return #GNUNET_YES in case it's OK to send.
+ */
+int
+GMC_is_sendable (struct CadetConnection *c, int fwd);
+
+/**
+ * Check if this connection is a direct one (never trim a direct connection).
+ *
+ * @param c Connection.
+ *
+ * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
+ */
+int
+GMC_is_direct (struct CadetConnection *c);
+
+/**
+ * Cancel a previously sent message while it's in the queue.
+ *
+ * ONLY can be called before the continuation given to the send function
+ * is called. Once the continuation is called, the message is no longer in the
+ * queue.
+ *
+ * @param q Handle to the queue.
+ */
+void
+GMC_cancel (struct CadetConnectionQueue *q);
+
+/**
+ * Sends an already built message on a connection, properly registering
+ * all used resources.
+ *
+ * @param message Message to send. Function makes a copy of it.
+ *                If message is not hop-by-hop, decrements TTL of copy.
+ * @param payload_type Type of payload, in case the message is encrypted.
+ * @param c Connection on which this message is transmitted.
+ * @param fwd Is this a fwd message?
+ * @param force Force the connection to accept the message (buffer overfill).
+ * @param cont Continuation called once message is sent. Can be NULL.
+ * @param cont_cls Closure for @c cont.
+ *
+ * @return Handle to cancel the message before it's sent.
+ *         NULL on error or if @c cont is NULL.
+ *         Invalid on @c cont call.
+ */
+struct CadetConnectionQueue *
+GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                           uint16_t payload_type, uint32_t payload_id,
+                           struct CadetConnection *c, int fwd, int force,
+                           GMC_sent cont, void *cont_cls);
+
+/**
+ * Sends a CREATE CONNECTION message for a path to a peer.
+ * Changes the connection and tunnel states if necessary.
+ *
+ * @param connection Connection to create.
+ */
+void
+GMC_send_create (struct CadetConnection *connection);
+
+/**
+ * Send a message to all peers in this connection that the connection
+ * is no longer valid.
+ *
+ * If some peer should not receive the message, it should be zero'ed out
+ * before calling this function.
+ *
+ * @param c The connection whose peers to notify.
+ */
+void
+GMC_send_destroy (struct CadetConnection *c);
+
+/**
+ * @brief Start a polling timer for the connection.
+ *
+ * When a neighbor does not accept more traffic on the connection it could be
+ * caused by a simple congestion or by a lost ACK. Polling enables to check
+ * for the lastest ACK status for a connection.
+ *
+ * @param c Connection.
+ * @param fwd Should we poll in the FWD direction?
+ */
+void
+GMC_start_poll (struct CadetConnection *c, int fwd);
+
+
+/**
+ * @brief Stop polling a connection for ACKs.
+ *
+ * Once we have enough ACKs for future traffic, polls are no longer necessary.
+ *
+ * @param c Connection.
+ * @param fwd Should we stop the poll in the FWD direction?
+ */
+void
+GMC_stop_poll (struct CadetConnection *c, int fwd);
+
+/**
+ * Get a (static) string for a connection.
+ *
+ * @param c Connection.
+ */
+const char *
+GMC_2s (const struct CadetConnection *c);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_SERVICE_CADET_CONNECTION_H */
+#endif
+/* end of gnunet-service-cadet_connection.h */

Copied: gnunet/src/cadet/gnunet-service-cadet_dht.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_dht.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_dht.c                         (rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_dht.c 2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,423 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_dht_service.h"
+#include "gnunet_statistics_service.h"
+
+#include "cadet_path.h"
+#include "gnunet-service-cadet_dht.h"
+#include "gnunet-service-cadet_peer.h"
+#include "gnunet-service-cadet_hello.h"
+
+#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
+
+
+/******************************************************************************/
+/********************************   STRUCTS  
**********************************/
+/******************************************************************************/
+
+/**
+ * Handle for DHT searches.
+ */
+struct GMD_search_handle
+{
+  /** DHT_GET handle. */
+  struct GNUNET_DHT_GetHandle *dhtget;
+
+  /** Provided callback to call when a path is found. */
+  GMD_search_callback callback;
+
+  /** Provided closure. */
+  void *cls;
+
+  /** Peer ID searched for */
+  GNUNET_PEER_Id peer_id;
+};
+
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Own ID (short value).
+ */
+extern GNUNET_PEER_Id myid;
+
+/**
+ * Own ID (full value).
+ */
+extern struct GNUNET_PeerIdentity my_full_id;
+
+/**
+ * Handle to use DHT.
+ */
+static struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * How often to PUT own ID in the DHT.
+ */
+static struct GNUNET_TIME_Relative id_announce_time;
+
+/**
+ * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
+ */
+static unsigned long long dht_replication_level;
+
+/**
+ * Task to periodically announce itself in the network.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
+
+/**
+ * GET requests to stop on shutdown.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests;
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+
+/**
+ * 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
+ *
+ * FIXME refactor and use build_path_from_peer_ids
+ */
+static struct CadetPeerPath *
+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 CadetPeerPath *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;
+  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])
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
+      GNUNET_PEER_change_rc (id, -1);
+    }
+    else
+    {
+      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;
+  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])
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
+      GNUNET_PEER_change_rc (id, -1);
+    }
+    else
+    {
+      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 CADET_DEBUG
+  if (get_path_length > 0)
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "   (first of GET: %s)\n",
+                GNUNET_i2s (&get_path[0]));
+  if (put_path_length > 0)
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "   (first of PUT: %s)\n",
+                GNUNET_i2s (&put_path[0]));
+  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);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "       %u: %s\n", p->peers[i],
+                GNUNET_i2s (&peer_id));
+  }
+#endif
+  return p;
+}
+
+
+/**
+ * Function to process paths received for a new peer addition. The recorded
+ * paths form the initial tunnel, which can be optimized later.
+ * Called on each result obtained for the DHT search.
+ *
+ * @param cls closure
+ * @param exp when will this value expire
+ * @param key key of the result
+ * @param get_path path of the get request
+ * @param get_path_length lenght of get_path
+ * @param put_path path of the put request
+ * @param put_path_length length of the put_path
+ * @param type type of the result
+ * @param size number of bytes in data
+ * @param data pointer to the result data
+ */
+static void
+dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
+                    const struct GNUNET_HashCode * key,
+                    const struct GNUNET_PeerIdentity *get_path,
+                    unsigned int get_path_length,
+                    const struct GNUNET_PeerIdentity *put_path,
+                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
+                    size_t size, const void *data)
+{
+  struct GMD_search_handle *h = cls;
+  struct GNUNET_HELLO_Message *hello;
+  struct CadetPeerPath *p;
+  struct CadetPeer *peer;
+  char *s;
+
+  p = path_build_from_dht (get_path, get_path_length,
+                           put_path, put_path_length);
+  s = path_2s (p);
+  LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s);
+  GNUNET_free_non_null (s);
+  peer = GMP_get_short (p->peers[p->length - 1]);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GMP_2s (peer));
+  h->callback (h->cls, p);
+  path_destroy (p);
+  hello = (struct GNUNET_HELLO_Message *) data;
+  GMP_set_hello (peer, hello);
+  GMP_try_connect (peer);
+  return;
+}
+
+
+/**
+ * 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 GNUNET_HashCode phash;
+  const struct GNUNET_HELLO_Message *hello;
+  size_t size;
+  struct GNUNET_TIME_Absolute expiration;
+  struct GNUNET_TIME_Relative retry_time;
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+  {
+    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
+
+  /* TODO
+   * - Set data expiration in function of X
+   * - Adapt X to churn
+   */
+  hello = GMH_get_mine ();
+  if (NULL == hello || (size = GNUNET_HELLO_size (hello)) == 0)
+  {
+    /* Peerinfo gave us no hello yet, try again in a second. */
+    announce_id_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                                     &announce_id, cls);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  no hello, waiting!\n");
+    return;
+  }
+  expiration = GNUNET_HELLO_get_last_expiration (hello);
+  retry_time = GNUNET_TIME_absolute_get_remaining (expiration);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size);
+  memset (&phash, 0, sizeof (phash));
+  memcpy (&phash, &my_full_id, sizeof (my_full_id));
+  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_DHT_HELLO,       /* Block type */
+                  size,  /* Size of the data */
+                  (const char *) hello, /* Data itself */
+                  expiration,  /* Data expiration */
+                  retry_time, /* Retry time */
+                  NULL,         /* Continuation */
+                  NULL);        /* Continuation closure */
+  announce_id_task =
+      GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
+}
+
+/**
+ * Iterator over hash map entries and stop GET requests before disconnecting
+ * from the DHT.
+ *
+ * @param cls Closure (unused)
+ * @param key Current peer ID.
+ * @param value Value in the hash map (GMD_search_handle).
+ *
+ * @return #GNUNET_YES, we should continue to iterate,
+ */
+int
+stop_get (void *cls,
+          uint32_t key,
+          void *value)
+{
+  struct GMD_search_handle *h = value;
+
+  GMD_search_stop (h);
+  return GNUNET_YES;
+}
+
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize the DHT subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GMD_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET", 
"DHT_REPLICATION_LEVEL",
+                                             &dht_replication_level))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               "CADET", "DHT_REPLICATION_LEVEL", "USING 
DEFAULT");
+    dht_replication_level = 3;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME",
+                                           &id_announce_time))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "CADET", "ID_ANNOUNCE_TIME", "MISSING");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  dht_handle = GNUNET_DHT_connect (c, 64);
+  if (NULL == dht_handle)
+  {
+    GNUNET_break (0);
+  }
+
+  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL);
+  get_requests = GNUNET_CONTAINER_multihashmap32_create (32);
+}
+
+
+/**
+ * Shut down the DHT subsystem.
+ */
+void
+GMD_shutdown (void)
+{
+  GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL);
+  GNUNET_CONTAINER_multihashmap32_destroy (get_requests);
+  if (dht_handle != NULL)
+  {
+    GNUNET_DHT_disconnect (dht_handle);
+    dht_handle = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
+  {
+    GNUNET_SCHEDULER_cancel (announce_id_task);
+    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+}
+
+struct GMD_search_handle *
+GMD_search (const struct GNUNET_PeerIdentity *peer_id,
+            GMD_search_callback callback, void *cls)
+{
+  struct GNUNET_HashCode phash;
+  struct GMD_search_handle *h;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  Starting DHT GET for peer %s\n", GNUNET_i2s (peer_id));
+  memset (&phash, 0, sizeof (phash));
+  memcpy (&phash, peer_id, sizeof (*peer_id));
+  h = GNUNET_new (struct GMD_search_handle);
+  h->peer_id = GNUNET_PEER_intern (peer_id);
+  h->callback = callback;
+  h->cls = cls;
+  h->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
+                                    GNUNET_BLOCK_TYPE_DHT_HELLO, /* 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, h);
+  GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+  return h;
+}
+
+void
+GMD_search_stop (struct GMD_search_handle *h)
+{
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_CONTAINER_multihashmap32_remove (get_requests,
+                                                        h->peer_id, h));
+  GNUNET_DHT_get_stop (h->dhtget);
+  GNUNET_free (h);
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_dht.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_dht.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_dht.h                         (rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_dht.h 2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,92 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_dht.h
+ * @brief cadet service; dealing with DHT requests and results
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GMD (Gnunet Cadet Dht)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_DHT_H
+#define GNUNET_SERVICE_CADET_DHT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+struct GMD_search_handle;
+
+
+/**
+ * Callback called on each path found over the DHT.
+ *
+ * @param cls Closure.
+ * @param path An unchecked, unoptimized path to the target node.
+ *             After callback will no longer be valid!
+ */
+typedef void (*GMD_search_callback) (void *cls,
+                                     const struct CadetPeerPath *path);
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize the DHT subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GMD_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+/**
+ * Shut down the DHT subsystem.
+ */
+void
+GMD_shutdown (void);
+
+
+struct GMD_search_handle *
+GMD_search (const struct GNUNET_PeerIdentity *peer_id,
+            GMD_search_callback callback, void *cls);
+
+
+void
+GMD_search_stop (struct GMD_search_handle *h);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
+#endif
+/* end of gnunet-cadet-service_LOCAL.h */
\ No newline at end of file

Copied: gnunet/src/cadet/gnunet-service-cadet_hello.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_hello.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_hello.c                               
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_hello.c       2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,198 @@
+/*
+     This file is part of GNUnet.
+     (C) 2014 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_statistics_service.h"
+#include "gnunet_peerinfo_service.h"
+
+#include "cadet_protocol.h"
+#include "cadet_path.h"
+
+#include "gnunet-service-cadet_hello.h"
+#include "gnunet-service-cadet_peer.h"
+
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
+
+
+/******************************************************************************/
+/********************************   STRUCTS  
**********************************/
+/******************************************************************************/
+
+
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Local peer own ID (memory efficient handle).
+ */
+extern GNUNET_PEER_Id myid;
+
+/**
+ * Local peer own ID (full value).
+ */
+extern struct GNUNET_PeerIdentity my_full_id;
+
+
+/**
+ * Don't try to recover tunnels if shutting down.
+ */
+extern int shutting_down;
+
+
+/**
+ * Hello message of local peer.
+ */
+const struct GNUNET_HELLO_Message *mine;
+
+/**
+ * Handle to peerinfo service.
+ */
+static struct GNUNET_PEERINFO_Handle *peerinfo;
+
+/**
+ * Iterator context.
+ */
+struct GNUNET_PEERINFO_NotifyContext* nc;
+
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+/**
+ * Process each hello message received from peerinfo.
+ *
+ * @param cls Closure (unused).
+ * @param peer Identity of the peer.
+ * @param hello Hello of the peer.
+ * @param err_msg Error message.
+ */
+static void
+got_hello (void *cls, const struct GNUNET_PeerIdentity *id,
+           const struct GNUNET_HELLO_Message *hello,
+           const char *err_msg)
+{
+  struct CadetPeer *peer;
+
+  if (NULL == id || NULL == hello)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n",
+       GNUNET_i2s (id), GNUNET_HELLO_size (hello),
+       GNUNET_STRINGS_absolute_time_to_string 
(GNUNET_HELLO_get_last_expiration(hello)));
+  peer = GMP_get (id);
+  GMP_set_hello (peer, hello);
+
+  if (GMP_get_short_id (peer) == myid)
+  {
+    mine = GMP_get_hello (peer);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " updated mine to %p\n", mine);
+  }
+}
+
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize the hello subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GMH_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
+  GNUNET_assert (NULL == nc);
+  peerinfo = GNUNET_PEERINFO_connect (c);
+  nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL);
+}
+
+
+/**
+ * Shut down the hello subsystem.
+ */
+void
+GMH_shutdown ()
+{
+  if (NULL != nc)
+  {
+    GNUNET_PEERINFO_notify_cancel (nc);
+    nc = NULL;
+  }
+  if (NULL != peerinfo)
+  {
+    GNUNET_PEERINFO_disconnect (peerinfo);
+    peerinfo = NULL;
+  }
+}
+
+
+/**
+ * Get own hello message.
+ *
+ * @return Own hello message.
+ */
+const struct GNUNET_HELLO_Message *
+GMH_get_mine (void)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " mine is %p\n", mine);
+  return mine;
+}
+
+
+/**
+ * Get another peer's hello message.
+ *
+ * @param id ID of the peer whose hello message is requested.
+ *
+ * @return Hello message, if any (NULL possible).
+ */
+const struct GNUNET_HELLO_Message *
+GMH_get (const struct GNUNET_PeerIdentity *id)
+{
+  return GMP_get_hello (GMP_get (id));
+}
+
+
+/**
+ * Convert a hello message to a string.
+ *
+ * @param h Hello message.
+ */
+char *
+GMH_2s (const struct GNUNET_HELLO_Message *h)
+{
+  return "hello (TODO)";
+}
+
+

Copied: gnunet/src/cadet/gnunet-service-cadet_hello.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_hello.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_hello.h                               
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_hello.h       2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,76 @@
+/*
+     This file is part of GNUnet.
+     (C) 2014 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_hello.h
+ * @brief cadet service; dealing with hello messages
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GMH (Gnunet Cadet Hello)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_HELLO_H
+#define GNUNET_SERVICE_CADET_HELLO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_hello_lib.h"
+
+
+/**
+ * Initialize the hello subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GMH_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+/**
+ * Shut down the hello subsystem.
+ */
+void
+GMH_shutdown ();
+
+/**
+ * Get own hello message.
+ *
+ * @return Own hello message.
+ */
+const struct GNUNET_HELLO_Message *
+GMH_get_mine (void);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
+#endif
+/* end of gnunet-cadet-service_hello.h */

Copied: gnunet/src/cadet/gnunet-service-cadet_local.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_local.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_local.c                               
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_local.c       2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,1242 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_statistics_service.h"
+
+#include "cadet.h"
+#include "cadet_protocol.h" /* GNUNET_CADET_Data is shared */
+
+#include "gnunet-service-cadet_local.h"
+#include "gnunet-service-cadet_channel.h"
+
+/* INFO DEBUG */
+#include "gnunet-service-cadet_tunnel.h"
+#include "gnunet-service-cadet_peer.h"
+
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-loc",__VA_ARGS__)
+
+/******************************************************************************/
+/********************************   STRUCTS  
**********************************/
+/******************************************************************************/
+
+/**
+ * Struct containing information about a client of the service
+ *
+ * TODO: add a list of 'waiting' ports
+ */
+struct CadetClient
+{
+    /**
+     * Linked list next
+     */
+  struct CadetClient *next;
+
+    /**
+     * Linked list prev
+     */
+  struct CadetClient *prev;
+
+    /**
+     * Tunnels that belong to this client, indexed by local id
+     */
+  struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
+
+    /**
+     * Tunnels this client has accepted, indexed by incoming local id
+     */
+  struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
+
+    /**
+     * Channel ID for the next incoming channel.
+     */
+  CADET_ChannelNumber next_chid;
+
+    /**
+     * Handle to communicate with the client
+     */
+  struct GNUNET_SERVER_Client *handle;
+
+    /**
+     * Ports that this client has declared interest in.
+     * Indexed by port, contains *Client.
+     */
+  struct GNUNET_CONTAINER_MultiHashMap32 *ports;
+
+    /**
+     * Whether the client is active or shutting down (don't send confirmations
+     * to a client that is shutting down.
+     */
+  int shutting_down;
+
+    /**
+     * ID of the client, mainly for debug messages
+     */
+  unsigned int id;
+};
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Handle to server lib.
+ */
+static struct GNUNET_SERVER_Handle *server_handle;
+
+/**
+ * DLL with all the clients, head.
+ */
+static struct CadetClient *clients_head;
+
+/**
+ * DLL with all the clients, tail.
+ */
+static struct CadetClient *clients_tail;
+
+/**
+ * Next ID to assign to a client.
+ */
+unsigned int next_client_id;
+
+/**
+ * All ports clients of this peer have opened.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap32 *ports;
+
+/**
+ * Notification context, to send messages to local clients.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+/**
+ * Remove client's ports from the global hashmap on disconnect.
+ *
+ * @param cls Closure (unused).
+ * @param key Port.
+ * @param value Client structure.
+ *
+ * @return GNUNET_OK, keep iterating.
+ */
+static int
+client_release_ports (void *cls,
+                      uint32_t key,
+                      void *value)
+{
+  int res;
+
+  res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value);
+  if (GNUNET_YES != res)
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+                "Port %u by client %p was not registered.\n",
+                key, value);
+  }
+  return GNUNET_OK;
+}
+
+
+
+/******************************************************************************/
+/********************************  HANDLES  
***********************************/
+/******************************************************************************/
+
+
+/**
+ * Handler for client connection.
+ *
+ * @param cls Closure (unused).
+ * @param client Client handler.
+ */
+static void
+handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  struct CadetClient *c;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "client connected: %p\n", client);
+  if (NULL == client)
+    return;
+  c = GNUNET_new (struct CadetClient);
+  c->handle = client;
+  c->id = next_client_id++; /* overflow not important: just for debug */
+  c->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+  GNUNET_SERVER_client_keep (client);
+  GNUNET_SERVER_client_set_user_context (client, c);
+  GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
+}
+
+
+/**
+ * Iterator for deleting each channel whose client endpoint disconnected.
+ *
+ * @param cls Closure (client that has disconnected).
+ * @param key The local channel id (used to access the hashmap).
+ * @param value The value stored at the key (channel to destroy).
+ *
+ * @return GNUNET_OK, keep iterating.
+ */
+static int
+channel_destroy_iterator (void *cls,
+                          uint32_t key,
+                          void *value)
+{
+  struct CadetChannel *ch = value;
+  struct CadetClient *c = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+              " Channel %s destroy, due to client %s shutdown.\n",
+              GMCH_2s (ch), GML_2s (c));
+
+  GMCH_handle_local_destroy (ch, c, key < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV);
+  return GNUNET_OK;
+}
+
+/**
+ * Handler for client disconnection
+ *
+ * @param cls closure
+ * @param client identification of the client; NULL
+ *        for the last call when the server is destroyed
+ */
+static void
+handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  struct CadetClient *c;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
+  if (client == NULL)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
+    return;
+  }
+
+  c = GML_client_get (client);
+  if (NULL != c)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n",
+                c->id, c);
+    GNUNET_SERVER_client_drop (c->handle);
+    c->shutting_down = GNUNET_YES;
+    if (NULL != c->own_channels)
+    {
+      GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
+                                               &channel_destroy_iterator, c);
+      GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
+    }
+
+    if (NULL != c->incoming_channels)
+    {
+      GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
+                                               &channel_destroy_iterator, c);
+      GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
+    }
+
+    if (NULL != c->ports)
+    {
+      GNUNET_CONTAINER_multihashmap32_iterate (c->ports,
+                                               &client_release_ports, c);
+      GNUNET_CONTAINER_multihashmap32_destroy (c->ports);
+    }
+    GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
+    GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  client free (%p)\n", c);
+    GNUNET_free (c);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n");
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
+  return;
+}
+
+
+/**
+ * Handler for new clients
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message, which includes messages the client wants
+ */
+static void
+handle_new_client (void *cls, struct GNUNET_SERVER_Client *client,
+                   const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_ClientConnect *cc_msg;
+  struct CadetClient *c;
+  unsigned int size;
+  uint32_t *p;
+  unsigned int i;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
+
+  /* Check data sanity */
+  size = ntohs (message->size) - sizeof (struct GNUNET_CADET_ClientConnect);
+  cc_msg = (struct GNUNET_CADET_ClientConnect *) message;
+  if (0 != (size % sizeof (uint32_t)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  size /= sizeof (uint32_t);
+
+  /* Initialize new client structure */
+  c = GNUNET_SERVER_client_get_user_context (client, struct CadetClient);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  client id %u\n", c->id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  client has %u ports\n", size);
+  if (size > 0)
+  {
+    uint32_t u32;
+
+    p = (uint32_t *) &cc_msg[1];
+    c->ports = GNUNET_CONTAINER_multihashmap32_create (size);
+    for (i = 0; i < size; i++)
+    {
+      u32 = ntohl (p[i]);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "    port: %u\n", u32);
+
+      /* store in client's hashmap */
+      GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c,
+                                           
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+      /* store in global hashmap */
+      /* FIXME only allow one client to have the port open,
+       *       have a backup hashmap with waiting clients */
+      GNUNET_CONTAINER_multihashmap32_put (ports, u32, c,
+                                           
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+    }
+  }
+
+  c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
+  c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
+  GNUNET_SERVER_notification_context_add (nc, client);
+  GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
+}
+
+
+/**
+ * Handler for requests of new tunnels
+ *
+ * @param cls Closure.
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
+                       const struct GNUNET_MessageHeader *message)
+{
+  struct CadetClient *c;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  /* Message size sanity check */
+  if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GMCH_handle_local_create (c,
+                                (struct GNUNET_CADET_ChannelMessage *) 
message))
+  {
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+}
+
+
+/**
+ * Handler for requests of deleting tunnels
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
+                        const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_ChannelMessage *msg;
+  struct CadetClient *c;
+  struct CadetChannel *ch;
+  CADET_ChannelNumber chid;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  /* Message sanity check */
+  if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  msg = (struct GNUNET_CADET_ChannelMessage *) message;
+
+  /* Retrieve tunnel */
+  chid = ntohl (msg->channel_id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  for channel %X\n", chid);
+  ch = GML_channel_get (c, chid);
+  if (NULL == ch)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  channel %X not found\n", chid);
+    GNUNET_STATISTICS_update (stats,
+                              "# client destroy messages on unknown channel",
+                              1, GNUNET_NO);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+
+  GMCH_handle_local_destroy (ch, c, chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV);
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  return;
+}
+
+
+/**
+ * Handler for client traffic
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_data (void *cls, struct GNUNET_SERVER_Client *client,
+             const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalData *msg;
+  struct CadetClient *c;
+  struct CadetChannel *ch;
+  CADET_ChannelNumber chid;
+  size_t size;
+  int fwd;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client!\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  msg = (struct GNUNET_CADET_LocalData *) message;
+
+  /* Sanity check for message size */
+  size = ntohs (message->size) - sizeof (struct GNUNET_CADET_LocalData);
+  if (size < sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  /* Channel exists? */
+  chid = ntohl (msg->id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
+  fwd = chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+  ch = GML_channel_get (c, chid);
+  if (NULL == ch)
+  {
+    GNUNET_STATISTICS_update (stats,
+                              "# client data messages on unknown channel",
+                              1, GNUNET_NO);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GMCH_handle_local_data (ch, c,
+                              (struct GNUNET_MessageHeader *)&msg[1], fwd))
+  {
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+
+  return;
+}
+
+
+/**
+ * Handler for client's ACKs for payload traffic.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
+            const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_CADET_LocalAck *msg;
+  struct CadetChannel *ch;
+  struct CadetClient *c;
+  CADET_ChannelNumber chid;
+  int fwd;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
+
+  msg = (struct GNUNET_CADET_LocalAck *) message;
+
+  /* Channel exists? */
+  chid = ntohl (msg->channel_id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
+  ch = GML_channel_get (c, chid);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "   -- ch %p\n", ch);
+  if (NULL == ch)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  for client %u.\n", c->id);
+    GNUNET_STATISTICS_update (stats,
+                              "# client ack messages on unknown channel",
+                              1, GNUNET_NO);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+
+  /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
+  /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
+  fwd = chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+
+  GMCH_handle_local_ack (ch, fwd);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+
+  return;
+}
+
+
+
+/**
+ * Iterator over all peers to send a monitoring client info about each peer.
+ *
+ * @param cls Closure ().
+ * @param peer Peer ID (tunnel remote peer).
+ * @param value Peer info.
+ *
+ * @return #GNUNET_YES, to keep iterating.
+ */
+static int
+get_all_peers_iterator (void *cls,
+                        const struct GNUNET_PeerIdentity * peer,
+                        void *value)
+{
+  struct GNUNET_SERVER_Client *client = cls;
+  struct CadetPeer *p = value;
+  struct GNUNET_CADET_LocalInfoPeer msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
+  msg.destination = *peer;
+  msg.paths = htons (GMP_count_paths (p));
+  msg.tunnel = htons (NULL != GMP_get_tunnel (p));
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n",
+       GNUNET_i2s (peer));
+
+  GNUNET_SERVER_notification_context_unicast (nc, client,
+                                              &msg.header, GNUNET_NO);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's INFO PEERS request.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client,
+                    const struct GNUNET_MessageHeader *message)
+{
+  struct CadetClient *c;
+  struct GNUNET_MessageHeader reply;
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received get peers request from client %u (%p)\n",
+       c->id, client);
+
+  GMP_iterate_all (get_all_peers_iterator, client);
+  reply.size = htons (sizeof (reply));
+  reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
+  GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Get peers request from client %u completed\n", c->id);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Iterator over all tunnels to send a monitoring client info about each 
tunnel.
+ *
+ * @param cls Closure ().
+ * @param peer Peer ID (tunnel remote peer).
+ * @param value Tunnel info.
+ *
+ * @return #GNUNET_YES, to keep iterating.
+ */
+static int
+get_all_tunnels_iterator (void *cls,
+                          const struct GNUNET_PeerIdentity * peer,
+                          void *value)
+{
+  struct GNUNET_SERVER_Client *client = cls;
+  struct CadetTunnel3 *t = value;
+  struct GNUNET_CADET_LocalInfoTunnel msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
+  msg.destination = *peer;
+  msg.channels = htonl (GMT_count_channels (t));
+  msg.connections = htonl (GMT_count_connections (t));
+  msg.cstate = htons ((uint16_t) GMT_get_cstate (t));
+  msg.estate = htons ((uint16_t) GMT_get_estate (t));
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n",
+       GNUNET_i2s (peer));
+
+  GNUNET_SERVER_notification_context_unicast (nc, client,
+                                              &msg.header, GNUNET_NO);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handler for client's INFO TUNNELS request.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
+                    const struct GNUNET_MessageHeader *message)
+{
+  struct CadetClient *c;
+  struct GNUNET_MessageHeader reply;
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received get tunnels request from client %u (%p)\n",
+       c->id, client);
+
+  GMT_iterate_all (get_all_tunnels_iterator, client);
+  reply.size = htons (sizeof (reply));
+  reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
+  GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Get tunnels request from client %u completed\n", c->id);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+static void
+iter_connection (void *cls, struct CadetConnection *c)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
+  struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1];
+
+  h[msg->connections] = *(GMC_get_id (c));
+  msg->connections++;
+}
+
+static void
+iter_channel (void *cls, struct CadetChannel *ch)
+{
+  struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
+  struct GNUNET_HashCode *h = (struct GNUNET_HashCode *) &msg[1];
+  CADET_ChannelNumber *chn = (CADET_ChannelNumber *) &h[msg->connections];
+
+  chn[msg->channels] = GMCH_get_id (ch);
+  msg->channels++;
+}
+
+
+/**
+ * Handler for client's SHOW_TUNNEL request.
+ *
+ * @param cls Closure (unused).
+ * @param client Identification of the client.
+ * @param message The actual message.
+ */
+void
+handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
+                    const struct GNUNET_MessageHeader *message)
+{
+  const struct GNUNET_CADET_LocalInfo *msg;
+  struct GNUNET_CADET_LocalInfoTunnel *resp;
+  struct CadetClient *c;
+  struct CadetTunnel3 *t;
+  unsigned int ch_n;
+  unsigned int c_n;
+  size_t size;
+
+  /* Sanity check for client registration */
+  if (NULL == (c = GML_client_get (client)))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+
+  msg = (struct GNUNET_CADET_LocalInfo *) message;
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Received tunnel info request from client %u for tunnel %s\n",
+       c->id, GNUNET_i2s_full(&msg->peer));
+
+  t = GMP_get_tunnel (GMP_get (&msg->peer));
+  if (NULL == t)
+  {
+    /* We don't know the tunnel */
+    struct GNUNET_CADET_LocalInfoTunnel warn;
+
+    LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n",
+         GNUNET_i2s_full(&msg->peer), sizeof (warn));
+    warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
+    warn.header.size = htons (sizeof (warn));
+    warn.destination = msg->peer;
+    warn.channels = htonl (0);
+    warn.connections = htonl (0);
+    warn.cstate = htons (0);
+    warn.estate = htons (0);
+
+    GNUNET_SERVER_notification_context_unicast (nc, client,
+                                                &warn.header,
+                                                GNUNET_NO);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+
+  /* Initialize context */
+  ch_n = GMT_count_channels (t);
+  c_n = GMT_count_connections (t);
+
+  size = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
+  size += c_n * sizeof (struct GNUNET_CADET_Hash);
+  size += ch_n * sizeof (CADET_ChannelNumber);
+
+  resp = GNUNET_malloc (size);
+  resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
+  resp->header.size = htons (size);
+  GMT_iterate_connections (t, &iter_connection, resp);
+  GMT_iterate_channels (t, &iter_channel, resp);
+  /* Do not interleave with iterators, iter_channel needs conn in HBO */
+  resp->destination = msg->peer;
+  resp->connections = htonl (resp->connections);
+  resp->channels = htonl (resp->channels);
+  resp->cstate = htons (GMT_get_cstate (t));
+  resp->estate = htons (GMT_get_estate (t));
+  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
+                                              &resp->header, GNUNET_NO);
+  GNUNET_free (resp);
+
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Show tunnel request from client %u completed. %u conn, %u ch\n",
+       c->id, c_n, ch_n);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Functions to handle messages from clients
+ */
+static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
+  {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT, 0},
+  {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE,
+   sizeof (struct GNUNET_CADET_ChannelMessage)},
+  {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
+   sizeof (struct GNUNET_CADET_ChannelMessage)},
+  {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
+  {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
+   sizeof (struct GNUNET_CADET_LocalAck)},
+  {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
+   sizeof (struct GNUNET_MessageHeader)},
+  {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
+   sizeof (struct GNUNET_MessageHeader)},
+  {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
+   sizeof (struct GNUNET_CADET_LocalInfo)},
+  {NULL, NULL, 0, 0}
+};
+
+
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize server subsystem.
+ *
+ * @param handle Server handle.
+ */
+void
+GML_init (struct GNUNET_SERVER_Handle *handle)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
+  server_handle = handle;
+  GNUNET_SERVER_suspend (server_handle);
+  ports = GNUNET_CONTAINER_multihashmap32_create (32);
+}
+
+
+/**
+ * Install server (service) handlers and start listening to clients.
+ */
+void
+GML_start (void)
+{
+  GNUNET_SERVER_add_handlers (server_handle, client_handlers);
+  GNUNET_SERVER_connect_notify (server_handle,  &handle_client_connect, NULL);
+  GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
+                                   NULL);
+  nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
+
+  clients_head = NULL;
+  clients_tail = NULL;
+  next_client_id = 0;
+  GNUNET_SERVER_resume (server_handle);
+}
+
+
+/**
+ * Shutdown server.
+ */
+void
+GML_shutdown (void)
+{
+  if (nc != NULL)
+  {
+    GNUNET_SERVER_notification_context_destroy (nc);
+    nc = NULL;
+  }
+}
+
+
+/**
+ * Get a channel from a client.
+ *
+ * @param c Client to check.
+ * @param chid Channel ID, must be local (> 0x800...).
+ *
+ * @return non-NULL if channel exists in the clients lists
+ */
+struct CadetChannel *
+GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
+{
+  struct GNUNET_CONTAINER_MultiHashMap32 *map;
+
+  if (0 == (chid & GNUNET_CADET_LOCAL_CHANNEL_ID_CLI))
+  {
+    GNUNET_break_op (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
+    return NULL;
+  }
+
+  if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+    map = c->incoming_channels;
+  else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+    map = c->own_channels;
+  else
+  {
+    GNUNET_break (0);
+    map = NULL;
+  }
+  if (NULL == map)
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Client %s does no t have a valid map for CHID %X\n",
+         GML_2s (c), chid);
+    return NULL;
+  }
+  return GNUNET_CONTAINER_multihashmap32_get (map, chid);
+}
+
+
+/**
+ * Add a channel to a client
+ *
+ * @param client Client.
+ * @param chid Channel ID.
+ * @param ch Channel.
+ */
+void
+GML_channel_add (struct CadetClient *client,
+                 uint32_t chid,
+                 struct CadetChannel *ch)
+{
+  if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
+    GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+    GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+  else
+    GNUNET_break (0);
+}
+
+
+/**
+ * Remove a channel from a client.
+ *
+ * @param client Client.
+ * @param chid Channel ID.
+ * @param ch Channel.
+ */
+void
+GML_channel_remove (struct CadetClient *client,
+                    uint32_t chid,
+                    struct CadetChannel *ch)
+{
+  if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= chid)
+    GNUNET_break (GNUNET_YES ==
+                  GNUNET_CONTAINER_multihashmap32_remove 
(client->incoming_channels,
+                                                          chid, ch));
+  else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= chid)
+    GNUNET_break (GNUNET_YES ==
+                  GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
+                                                          chid, ch));
+  else
+    GNUNET_break (0);
+}
+
+
+/**
+ * Get the tunnel's next free local channel ID.
+ *
+ * @param c Client.
+ *
+ * @return LID of a channel free to use.
+ */
+CADET_ChannelNumber
+GML_get_next_chid (struct CadetClient *c)
+{
+  CADET_ChannelNumber chid;
+
+  while (NULL != GML_channel_get (c, c->next_chid))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid);
+    c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+  }
+  chid = c->next_chid;
+  c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
+
+  return chid;
+}
+
+
+/**
+ * Check if client has registered with the service and has not disconnected
+ *
+ * @param client the client to check
+ *
+ * @return non-NULL if client exists in the global DLL
+ */
+struct CadetClient *
+GML_client_get (struct GNUNET_SERVER_Client *client)
+{
+  return GNUNET_SERVER_client_get_user_context (client, struct CadetClient);
+}
+
+/**
+ * Find a client that has opened a port
+ *
+ * @param port Port to check.
+ *
+ * @return non-NULL if a client has the port.
+ */
+struct CadetClient *
+GML_client_get_by_port (uint32_t port)
+{
+  return GNUNET_CONTAINER_multihashmap32_get (ports, port);
+}
+
+
+/**
+ * Deletes a channel from a client (either owner or destination).
+ *
+ * @param c Client whose tunnel to delete.
+ * @param ch Channel which should be deleted.
+ * @param id Channel ID.
+ */
+void
+GML_client_delete_channel (struct CadetClient *c,
+                           struct CadetChannel *ch,
+                           CADET_ChannelNumber id)
+{
+  int res;
+
+  if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= id)
+  {
+    res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
+                                                  id, ch);
+    if (GNUNET_YES != res)
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
+  }
+  else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= id)
+  {
+    res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
+                                                  id, ch);
+    if (GNUNET_YES != res)
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+}
+
+/**
+ * Build a local ACK message and send it to a local client, if needed.
+ *
+ * If the client was already allowed to send data, do nothing.
+ *
+ * @param c Client to whom send the ACK.
+ * @param id Channel ID to use
+ */
+void
+GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id)
+{
+  struct GNUNET_CADET_LocalAck msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+              "send local %s ack on %X towards %p\n",
+              id < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c);
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
+  msg.channel_id = htonl (id);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              c->handle,
+                                              &msg.header,
+                                              GNUNET_NO);
+
+}
+
+
+
+/**
+ * Notify the client that a new incoming channel was created.
+ *
+ * @param c Client to notify.
+ * @param id Channel ID.
+ * @param port Channel's destination port.
+ * @param opt Options (bit array).
+ * @param peer Origin peer.
+ */
+void
+GML_send_channel_create (struct CadetClient *c,
+                         uint32_t id, uint32_t port, uint32_t opt,
+                         const struct GNUNET_PeerIdentity *peer)
+{
+  struct GNUNET_CADET_ChannelMessage msg;
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
+  msg.channel_id = htonl (id);
+  msg.port = htonl (port);
+  msg.opt = htonl (opt);
+  msg.peer = *peer;
+  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
+                                              &msg.header, GNUNET_NO);
+}
+
+
+/**
+ * Build a local channel NACK message and send it to a local client.
+ *
+ * @param c Client to whom send the NACK.
+ * @param id Channel ID to use
+ */
+void
+GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id)
+{
+  struct GNUNET_CADET_LocalAck msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "send local nack on %X towards %p\n",
+       id, c);
+
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK);
+  msg.channel_id = htonl (id);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              c->handle,
+                                              &msg.header,
+                                              GNUNET_NO);
+
+}
+
+/**
+ * Notify a client that a channel is no longer valid.
+ *
+ * @param c Client.
+ * @param id ID of the channel that is destroyed.
+ */
+void
+GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
+{
+  struct GNUNET_CADET_ChannelMessage msg;
+
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  if (GNUNET_YES == c->shutting_down)
+    return;
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
+  msg.channel_id = htonl (id);
+  msg.port = htonl (0);
+  memset (&msg.peer, 0, sizeof (msg.peer));
+  msg.opt = htonl (0);
+  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
+                                              &msg.header, GNUNET_NO);
+}
+
+
+/**
+ * Modify the cadet message ID from global to local and send to client.
+ *
+ * @param c Client to send to.
+ * @param msg Message to modify and send.
+ * @param id Channel ID to use (c can be both owner and client).
+ */
+void
+GML_send_data (struct CadetClient *c,
+               const struct GNUNET_CADET_Data *msg,
+               CADET_ChannelNumber id)
+{
+  struct GNUNET_CADET_LocalData *copy;
+  uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_Data);
+  char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)];
+
+  if (size < sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (NULL == c)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  copy = (struct GNUNET_CADET_LocalData *) cbuf;
+  memcpy (&copy[1], &msg[1], size);
+  copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size);
+  copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
+  copy->id = htonl (id);
+  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
+                                              &copy->header, GNUNET_NO);
+}
+
+
+/**
+ * Get the static string to represent a client.
+ *
+ * @param c Client.
+ *
+ * @return Static string for the client.
+ */
+const char *
+GML_2s (const struct CadetClient *c)
+{
+  static char buf[32];
+
+  sprintf (buf, "%u", c->id);
+  return buf;
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_local.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_local.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_local.h                               
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_local.h       2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,226 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_local.h
+ * @brief cadet service; dealing with local clients
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GML (Gnunet Cadet Local)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_LOCAL_H
+#define GNUNET_SERVICE_CADET_LOCAL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+/**
+ * Struct containing information about a client of the service
+ */
+struct CadetClient;
+
+#include "gnunet-service-cadet_channel.h"
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize server subsystem.
+ *
+ * @param handle Server handle.
+ */
+void
+GML_init (struct GNUNET_SERVER_Handle *handle);
+
+/**
+ * Install server (service) handlers and start listening to clients.
+ */
+void
+GML_start (void);
+
+/**
+ * Shutdown server.
+ */
+void
+GML_shutdown (void);
+
+/**
+ * Get a channel from a client.
+ *
+ * @param c Client to check.
+ * @param chid Channel ID, must be local (> 0x800...).
+ *
+ * @return non-NULL if channel exists in the clients lists
+ */
+struct CadetChannel *
+GML_channel_get (struct CadetClient *c, uint32_t chid);
+
+/**
+ * Add a channel to a client
+ *
+ * @param client Client.
+ * @param chid Channel ID.
+ * @param ch Channel.
+ */
+void
+GML_channel_add (struct CadetClient *client,
+                 uint32_t chid,
+                 struct CadetChannel *ch);
+
+/**
+ * Remove a channel from a client
+ *
+ * @param client Client.
+ * @param chid Channel ID.
+ * @param ch Channel.
+ */
+void
+GML_channel_remove (struct CadetClient *client,
+                    uint32_t chid,
+                    struct CadetChannel *ch);
+
+/**
+ * Get the tunnel's next free local channel ID.
+ *
+ * @param c Client.
+ *
+ * @return LID of a channel free to use.
+ */
+CADET_ChannelNumber
+GML_get_next_chid (struct CadetClient *c);
+
+/**
+ * Check if client has registered with the service and has not disconnected
+ *
+ * @param client the client to check
+ *
+ * @return non-NULL if client exists in the global DLL
+ */
+struct CadetClient *
+GML_client_get (struct GNUNET_SERVER_Client *client);
+
+/**
+ * Find a client that has opened a port
+ *
+ * @param port Port to check.
+ *
+ * @return non-NULL if a client has the port.
+ */
+struct CadetClient *
+GML_client_get_by_port (uint32_t port);
+
+/**
+ * Deletes a tunnel from a client (either owner or destination).
+ *
+ * @param c Client whose tunnel to delete.
+ * @param ch Channel which should be deleted.
+ * @param id Channel ID.
+ */
+void
+GML_client_delete_channel (struct CadetClient *c,
+                           struct CadetChannel *ch,
+                           CADET_ChannelNumber id);
+
+/**
+ * Build a local ACK message and send it to a local client, if needed.
+ *
+ * If the client was already allowed to send data, do nothing.
+ *
+ * @param c Client to whom send the ACK.
+ * @param id Channel ID to use
+ */
+void
+GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id);
+
+/**
+ * Notify the appropriate client that a new incoming channel was created.
+ *
+ * @param c Client to notify.
+ * @param id Channel ID.
+ * @param port Channel's destination port.
+ * @param opt Options (bit array).
+ * @param peer Origin peer.
+ */
+void
+GML_send_channel_create (struct CadetClient *c,
+                         uint32_t id, uint32_t port, uint32_t opt,
+                         const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Build a local channel NACK message and send it to a local client.
+ *
+ * @param c Client to whom send the NACK.
+ * @param id Channel ID to use
+ */
+void
+GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id);
+
+/**
+ * Notify a client that a channel is no longer valid.
+ *
+ * @param c Client.
+ * @param id ID of the channel that is destroyed.
+ */
+void
+GML_send_channel_destroy (struct CadetClient *c, uint32_t id);
+
+/**
+ * Modify the cadet message ID from global to local and send to client.
+ *
+ * @param c Client to send to.
+ * @param msg Message to modify and send.
+ * @param id Channel ID to use (c can be both owner and client).
+ */
+void
+GML_send_data (struct CadetClient *c,
+               const struct GNUNET_CADET_Data *msg,
+               CADET_ChannelNumber id);
+
+/**
+ * Get the static string to represent a client.
+ *
+ * @param c Client.
+ *
+ * @return Static string for the client.
+ */
+const char *
+GML_2s (const struct CadetClient *c);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
+#endif
+/* end of gnunet-cadet-service_LOCAL.h */

Copied: gnunet/src/cadet/gnunet-service-cadet_peer.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_peer.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_peer.c                                
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_peer.c        2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,2219 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_transport_service.h"
+#include "gnunet_core_service.h"
+#include "gnunet_statistics_service.h"
+
+#include "cadet_protocol.h"
+
+#include "gnunet-service-cadet_peer.h"
+#include "gnunet-service-cadet_dht.h"
+#include "gnunet-service-cadet_connection.h"
+#include "gnunet-service-cadet_tunnel.h"
+#include "cadet_path.h"
+
+#define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__)
+
+/******************************************************************************/
+/********************************   STRUCTS  
**********************************/
+/******************************************************************************/
+
+/**
+ * Struct containing info about a queued transmission to this peer
+ */
+struct CadetPeerQueue
+{
+    /**
+      * DLL next
+      */
+  struct CadetPeerQueue *next;
+
+    /**
+      * DLL previous
+      */
+  struct CadetPeerQueue *prev;
+
+    /**
+     * Peer this transmission is directed to.
+     */
+  struct CadetPeer *peer;
+
+    /**
+     * Connection this message belongs to.
+     */
+  struct CadetConnection *c;
+
+    /**
+     * Is FWD in c?
+     */
+  int fwd;
+
+    /**
+     * Pointer to info stucture used as cls.
+     */
+  void *cls;
+
+  /**
+   * Type of message
+   */
+  uint16_t type;
+
+  /**
+   * Type of message
+   */
+  uint16_t payload_type;
+
+  /**
+   * Type of message
+   */
+  uint32_t payload_id;
+
+  /**
+     * Size of the message
+     */
+  size_t size;
+
+    /**
+     * Set when this message starts waiting for CORE.
+     */
+  struct GNUNET_TIME_Absolute start_waiting;
+
+    /**
+     * Function to call on sending.
+     */
+  GMP_sent callback;
+
+    /**
+     * Closure for callback.
+     */
+  void *callback_cls;
+};
+
+/**
+ * Struct containing all information regarding a given peer
+ */
+struct CadetPeer
+{
+    /**
+     * 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 CadetPeerPath *path_head;
+
+    /**
+     * Paths to reach the peer, ordered by ascending hop count
+     */
+  struct CadetPeerPath *path_tail;
+
+    /**
+     * Handle to stop the DHT search for paths to this peer
+     */
+  struct GMD_search_handle *search_h;
+
+    /**
+     * Tunnel to this peer, if any.
+     */
+  struct CadetTunnel3 *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 CadetPeerQueue *queue_head;
+
+  /**
+   * Transmission queue to core DLL tail
+   */
+  struct CadetPeerQueue *queue_tail;
+
+  /**
+   * How many messages are in the queue to this peer.
+   */
+  unsigned int queue_n;
+
+  /**
+   * Hello message.
+   */
+  struct GNUNET_HELLO_Message* hello;
+};
+
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Local peer own ID (full value).
+ */
+extern struct GNUNET_PeerIdentity my_full_id;
+
+/**
+ * Local peer own ID (short)
+ */
+extern GNUNET_PEER_Id myid;
+
+/**
+ * Peers known, indexed by PeerIdentity (CadetPeer).
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *peers;
+
+/**
+ * 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;
+
+/**
+ * Handle to communicate with core.
+ */
+static struct GNUNET_CORE_Handle *core_handle;
+
+/**
+ * Handle to try to start new connections.
+ */
+static struct GNUNET_TRANSPORT_Handle *transport_handle;
+
+
+/******************************************************************************/
+/*****************************     DEBUG      
*********************************/
+/******************************************************************************/
+
+static void
+queue_debug (struct CadetPeer *peer)
+{
+  struct CadetPeerQueue *q;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ Messages queued towards %s\n", GMP_2s 
(peer));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ  core tmt rdy: %p\n", 
peer->core_transmit);
+
+  for (q = peer->queue_head; NULL != q; q = q->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ  - %s %s on %s\n",
+         GM_m2s (q->type), GM_f2s (q->fwd), GMC_2s (q->c));
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ End queued towards %s\n", GMP_2s (peer));
+}
+
+
+/******************************************************************************/
+/*****************************  CORE HELPERS  
*********************************/
+/******************************************************************************/
+
+
+/**
+ * Iterator to notify all connections of a broken link. Mark connections
+ * to destroy after all traffic has been sent.
+ *
+ * @param cls Closure (peer disconnected).
+ * @param key Current key code (peer id).
+ * @param value Value in the hash map (connection).
+ *
+ * @return #GNUNET_YES to continue to iterate.
+ */
+static int
+notify_broken (void *cls,
+               const struct GNUNET_HashCode *key,
+               void *value)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *c = value;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  notifying %s due to %s\n",
+       GMC_2s (c), GMP_2s (peer));
+  GMC_notify_broken (c, peer);
+
+  return GNUNET_YES;
+}
+
+
+/**
+ * Remove the direct path to the peer.
+ *
+ * @param peer Peer to remove the direct path from.
+ *
+ */
+static struct CadetPeerPath *
+pop_direct_path (struct CadetPeer *peer)
+{
+  struct CadetPeerPath *iter;
+
+  for (iter = peer->path_head; NULL != iter; iter = iter->next)
+  {
+    if (2 <= iter->length)
+    {
+      GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter);
+      return iter;
+    }
+  }
+  return NULL;
+}
+
+
+/******************************************************************************/
+/***************************** CORE CALLBACKS 
*********************************/
+/******************************************************************************/
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+  struct CadetPeer *mp;
+  struct CadetPeerPath *path;
+  char own_id[16];
+
+  strncpy (own_id, GNUNET_i2s (&my_full_id), 15);
+  mp = GMP_get (peer);
+  if (myid == mp->id)
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s (self)\n", own_id);
+    path = path_new (1);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s <= %s\n",
+         own_id, GNUNET_i2s (peer));
+    path = path_new (2);
+    path->peers[1] = mp->id;
+    GNUNET_PEER_change_rc (mp->id, 1);
+    GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
+  }
+  path->peers[0] = myid;
+  GNUNET_PEER_change_rc (myid, 1);
+  GMP_add_path (mp, path, GNUNET_YES);
+
+  mp->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
+
+  if (NULL != GMP_get_tunnel (mp) &&
+      0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer))
+  {
+    GMP_connect (mp);
+  }
+
+  return;
+}
+
+
+/**
+ * Method called whenever a peer disconnects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+  struct CadetPeer *p;
+  struct CadetPeerPath *direct_path;
+  char own_id[16];
+
+  strncpy (own_id, GNUNET_i2s (&my_full_id), 15);
+  p = GNUNET_CONTAINER_multipeermap_get (peers, peer);
+  if (NULL == p)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  if (myid == p->id)
+    LOG (GNUNET_ERROR_TYPE_INFO, "DISCONNECTED %s (self)\n", own_id);
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "DISCONNECTED %s <= %s\n",
+         own_id, GNUNET_i2s (peer));
+  direct_path = pop_direct_path (p);
+  GNUNET_CONTAINER_multihashmap_iterate (p->connections, &notify_broken, p);
+  GNUNET_CONTAINER_multihashmap_destroy (p->connections);
+  p->connections = NULL;
+  if (NULL != p->core_transmit)
+    {
+      GNUNET_CORE_notify_transmit_ready_cancel (p->core_transmit);
+      p->core_transmit = NULL;
+    }
+  GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
+
+  path_destroy (direct_path);
+  return;
+}
+
+
+/**
+ * Functions to handle messages from core
+ */
+static struct GNUNET_CORE_MessageHandler core_handlers[] = {
+  {&GMC_handle_create, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0},
+  {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK,
+    sizeof (struct GNUNET_CADET_ConnectionACK)},
+  {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
+    sizeof (struct GNUNET_CADET_ConnectionBroken)},
+  {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
+    sizeof (struct GNUNET_CADET_ConnectionDestroy)},
+  {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_CADET_ACK,
+    sizeof (struct GNUNET_CADET_ACK)},
+  {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_CADET_POLL,
+    sizeof (struct GNUNET_CADET_Poll)},
+  {&GMC_handle_encrypted, GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0},
+  {&GMC_handle_kx, GNUNET_MESSAGE_TYPE_CADET_KX, 0},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * 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;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
+  if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
+    LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity));
+    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 CADET 
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();
+  }
+  GML_start ();
+  return;
+}
+
+
+/**
+  * Core callback to write a pre-constructed data packet to core buffer
+  *
+  * @param cls Closure (CadetTransmissionDescriptor 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 CadetConnection *c, size_t size, void *buf)
+{
+  struct GNUNET_CADET_ConnectionCreate *msg;
+  struct GNUNET_PeerIdentity *peer_ptr;
+  const struct CadetPeerPath *p = GMC_get_path (c);
+  size_t size_needed;
+  int i;
+
+  if (NULL == p)
+    return 0;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
+  size_needed =
+      sizeof (struct GNUNET_CADET_ConnectionCreate) +
+      p->length * sizeof (struct GNUNET_PeerIdentity);
+
+  if (size < size_needed || NULL == buf)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  msg = (struct GNUNET_CADET_ConnectionCreate *) buf;
+  msg->header.size = htons (size_needed);
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
+  msg->cid = *GMC_get_id (c);
+
+  peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
+  for (i = 0; i < p->length; i++)
+  {
+    GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
+  }
+
+  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 CadetConnection *c, size_t size, void *buf)
+{
+  struct GNUNET_CADET_ConnectionACK *msg = buf;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
+  if (sizeof (struct GNUNET_CADET_ConnectionACK) > size)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionACK));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK);
+  msg->cid = *GMC_get_id (c);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
+  return sizeof (struct GNUNET_CADET_ConnectionACK);
+}
+
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+
+/**
+ * Get priority for a queued message.
+ *
+ * @param q Queued message
+ *
+ * @return CORE priority to use.
+ */
+static enum GNUNET_CORE_Priority
+get_priority (struct CadetPeerQueue *q)
+{
+  enum GNUNET_CORE_Priority low;
+  enum GNUNET_CORE_Priority high;
+
+  if (NULL == q)
+  {
+    GNUNET_break (0);
+    return GNUNET_CORE_PRIO_BACKGROUND;
+  }
+
+  /* Relayed traffic has lower priority, our own traffic has higher */
+  if (NULL == q->c || GNUNET_NO == GMC_is_origin (q->c, q->fwd))
+  {
+    low = GNUNET_CORE_PRIO_BEST_EFFORT;
+    high = GNUNET_CORE_PRIO_URGENT;
+  }
+  else
+  {
+    low = GNUNET_CORE_PRIO_URGENT;
+    high = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
+  }
+
+  /* Bulky payload has lower priority, control traffic has higher. */
+  if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == q->type)
+    return low;
+  else
+    return high;
+}
+
+
+/**
+ * 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 CadetPeer *p = value;
+  struct CadetTunnel3 *t = p->tunnel;
+
+  if (NULL != t)
+    GMT_destroy (t);
+  return GNUNET_YES;
+}
+
+
+/**
+ * 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 CadetPeer *peer)
+{
+  struct GNUNET_PeerIdentity id;
+  struct CadetPeerPath *p;
+  struct CadetPeerPath *nextp;
+
+  GNUNET_PEER_resolve (peer->id, &id);
+  GNUNET_PEER_change_rc (peer->id, -1);
+
+  LOG (GNUNET_ERROR_TYPE_WARNING, "destroying peer %s\n", GNUNET_i2s (&id));
+
+  if (GNUNET_YES !=
+    GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_WARNING, " not in peermap!!\n");
+  }
+  if (NULL != peer->search_h)
+  {
+    GMD_search_stop (peer->search_h);
+  }
+  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;
+  }
+  GMT_destroy_empty (peer->tunnel);
+  GNUNET_free (peer);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Returns if peer is used (has a tunnel or is neighbor).
+ *
+ * @param peer Peer to check.
+ *
+ * @return #GNUNET_YES if peer is in use.
+ */
+static int
+peer_is_used (struct CadetPeer *peer)
+{
+  struct CadetPeerPath *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 CadetPeer *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 CadetPeer *p = value;
+  struct GNUNET_TIME_Absolute *abs = cls;
+
+  LOG (GNUNET_ERROR_TYPE_WARNING,
+       "peer %s timeout\n", GNUNET_i2s (key));
+
+  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);
+}
+
+
+/**
+ * Choose the best (yet unused) 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 CadetPeerPath *
+peer_get_best_path (const struct CadetPeer *peer)
+{
+  struct CadetPeerPath *best_p;
+  struct CadetPeerPath *p;
+  unsigned int best_cost;
+  unsigned int cost;
+
+  best_cost = UINT_MAX;
+  best_p = NULL;
+  for (p = peer->path_head; NULL != p; p = p->next)
+  {
+    if (GNUNET_NO == path_is_valid (p))
+      continue; /* Don't use invalid paths. */
+    if (GNUNET_YES == GMT_is_path_used (peer->tunnel, p))
+      continue; /* If path is already in use, skip it. */
+
+    if ((cost = GMT_get_path_cost (peer->tunnel, p)) < best_cost)
+    {
+      best_cost = cost;
+      best_p = p;
+    }
+  }
+  return best_p;
+}
+
+
+/**
+ * Is this queue element sendable?
+ *
+ * - All management traffic is always sendable.
+ * - For payload traffic, check the connection flow control.
+ *
+ * @param q Queue element to inspect.
+ *
+ * @return #GNUNET_YES if it is sendable, #GNUNET_NO otherwise.
+ */
+static int
+queue_is_sendable (struct CadetPeerQueue *q)
+{
+  /* Is PID-independent? */
+  switch (q->type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+    case GNUNET_MESSAGE_TYPE_CADET_KX:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
+      return GNUNET_YES;
+
+    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+      break;
+
+    default:
+      GNUNET_break (0);
+  }
+
+  return GMC_is_sendable (q->c, q->fwd);
+}
+
+
+/**
+ * Get first sendable message.
+ *
+ * @param peer The destination peer.
+ *
+ * @return First transmittable message, if any. Otherwise, NULL.
+ */
+static struct CadetPeerQueue *
+peer_get_first_message (const struct CadetPeer *peer)
+{
+  struct CadetPeerQueue *q;
+
+  for (q = peer->queue_head; NULL != q; q = q->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking %p towards %s\n", q, GMC_2s 
(q->c));
+    if (queue_is_sendable (q))
+      return q;
+  }
+
+  return NULL;
+}
+
+
+/**
+ * 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 path
+ */
+static void
+search_handler (void *cls, const struct CadetPeerPath *path)
+{
+  struct CadetPeer *peer = cls;
+  unsigned int connection_count;
+
+  GMP_add_path_to_all (path, GNUNET_NO);
+
+  /* Count connections */
+  connection_count = GMT_count_connections (peer->tunnel);
+
+  /* If we already have 3 (or more (?!)) connections, it's enough */
+  if (3 <= connection_count)
+    return;
+
+  if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
+    GMP_connect (peer);
+  }
+  return;
+}
+
+
+
+/**
+ * Core callback to write a queued packet to core buffer
+ *
+ * @param cls Closure (peer info).
+ * @param size Number of bytes available in buf.
+ * @param buf Where the to write the message.
+ *
+ * @return number of bytes written to buf
+ */
+static size_t
+queue_send (void *cls, size_t size, void *buf)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetConnection *c;
+  struct CadetPeerQueue *queue;
+  const struct GNUNET_PeerIdentity *dst_id;
+  size_t data_size;
+  uint32_t pid;
+
+  pid = 0;
+  peer->core_transmit = NULL;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue send towards %s (max %u)\n",
+       GMP_2s (peer), size);
+
+  if (NULL == buf || 0 == size)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Buffer size 0.\n");
+    return 0;
+  }
+
+  /* Initialize */
+  queue = peer_get_first_message (peer);
+  if (NULL == queue)
+  {
+    GNUNET_assert (0); /* Core tmt_rdy should've been canceled */
+    return 0;
+  }
+  c = queue->c;
+
+  dst_id = GNUNET_PEER_resolve2 (peer->id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s %s\n",
+       GMC_2s (c), GM_f2s(queue->fwd));
+  /* Check if buffer size is enough for the message */
+  if (queue->size > size)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, "not enough room (%u vs %u), reissue\n",
+         queue->size, size);
+    peer->core_transmit =
+      GNUNET_CORE_notify_transmit_ready (core_handle,
+                                         GNUNET_NO, get_priority (queue),
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         dst_id,
+                                         queue->size,
+                                         &queue_send,
+                                         peer);
+    return 0;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  size %u ok\n", queue->size);
+
+  /* Fill buf */
+  switch (queue->type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+      pid = GMC_get_pid (queue->c, queue->fwd);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  payload ID %u\n", pid);
+      data_size = send_core_data_raw (queue->cls, size, buf);
+      ((struct GNUNET_CADET_Encrypted *) buf)->pid = htonl (pid);
+      break;
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
+    case GNUNET_MESSAGE_TYPE_CADET_KX:
+    case GNUNET_MESSAGE_TYPE_CADET_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_POLL:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  raw %s\n", GM_m2s (queue->type));
+      data_size = send_core_data_raw (queue->cls, size, buf);
+      break;
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  path create\n");
+      if (GMC_is_origin (c, GNUNET_YES))
+        data_size = send_core_connection_create (queue->c, size, buf);
+      else
+        data_size = send_core_data_raw (queue->cls, size, buf);
+      break;
+    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  path ack\n");
+      if (GMC_is_origin (c, GNUNET_NO) ||
+          GMC_is_origin (c, GNUNET_YES))
+        data_size = send_core_connection_ack (queue->c, size, buf);
+      else
+        data_size = send_core_data_raw (queue->cls, size, buf);
+      break;
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+      /* This should be encapsulted */
+      GNUNET_break (0);
+      data_size = 0;
+      break;
+    default:
+      GNUNET_break (0);
+      LOG (GNUNET_ERROR_TYPE_WARNING, "  type unknown: %u\n", queue->type);
+      data_size = 0;
+  }
+
+  if (0 < drop_percent &&
+      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < 
drop_percent)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s on connection %s\n",
+         GM_m2s (queue->type), GMC_2s (c));
+    data_size = 0;
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         "snd %s (%s %u) on connection %s (%p) %s (size %u)\n",
+         GM_m2s (queue->type), GM_m2s (queue->payload_type),
+         queue->payload_type, GMC_2s (c), c, GM_f2s (queue->fwd), data_size);
+  }
+
+  /* Free queue, but cls was freed by send_core_* */
+  GMP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid);
+
+  /* If more data in queue, send next */
+  queue = peer_get_first_message (peer);
+  if (NULL != queue)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  more data!\n");
+    if (NULL == peer->core_transmit)
+    {
+      peer->core_transmit =
+          GNUNET_CORE_notify_transmit_ready (core_handle,
+                                             GNUNET_NO, get_priority (queue),
+                                             GNUNET_TIME_UNIT_FOREVER_REL,
+                                             dst_id,
+                                             queue->size,
+                                             &queue_send,
+                                             peer);
+      queue->start_waiting = GNUNET_TIME_absolute_get ();
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+                  "*   tmt rdy called somewhere else\n");
+    }
+//     GMC_start_poll (); FIXME needed?
+  }
+  else
+  {
+//     GMC_stop_poll(); FIXME needed?
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  return %d\n", data_size);
+  queue_debug (peer);
+  return data_size;
+}
+
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+
+/**
+ * Free a transmission that was already queued with all resources
+ * associated to the request.
+ *
+ * @param queue Queue handler to cancel.
+ * @param clear_cls Is it necessary to free associated cls?
+ * @param sent Was it really sent? (Could have been canceled)
+ * @param pid PID, if relevant (was sent and was a payload message).
+ */
+void
+GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
+                   int sent, uint32_t pid)
+{
+  struct CadetPeer *peer;
+
+  peer = queue->peer;
+
+  if (GNUNET_YES == clear_cls)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy type %s\n",
+         GM_m2s (queue->type));
+    switch (queue->type)
+    {
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
+        LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
+        /* fall through */
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
+      case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+      case GNUNET_MESSAGE_TYPE_CADET_KX:
+      case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+      case GNUNET_MESSAGE_TYPE_CADET_ACK:
+      case GNUNET_MESSAGE_TYPE_CADET_POLL:
+        GNUNET_free_non_null (queue->cls);
+        break;
+
+      default:
+        GNUNET_break (0);
+        LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n",
+             GM_m2s (queue->type));
+    }
+  }
+  GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
+
+  if (queue->type != GNUNET_MESSAGE_TYPE_CADET_ACK &&
+      queue->type != GNUNET_MESSAGE_TYPE_CADET_POLL)
+  {
+    peer->queue_n--;
+  }
+
+  if (NULL != queue->callback)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n");
+    queue->callback (queue->callback_cls,
+                     queue->c, sent, queue->type, pid,
+                     queue->fwd, queue->size,
+                     GNUNET_TIME_absolute_get_duration (queue->start_waiting));
+  }
+
+  if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit)
+  {
+    GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
+    peer->core_transmit = NULL;
+  }
+
+  GNUNET_free (queue);
+}
+
+
+/**
+ * @brief Queue and pass message to core when possible.
+ *
+ * @param peer Peer towards which to queue the message.
+ * @param cls Closure (@c type dependant). It will be used by queue_send to
+ *            build the message to be sent if not already prebuilt.
+ * @param type Type of the message, 0 for a raw message.
+ * @param size Size of the message.
+ * @param c Connection this message belongs to (can be NULL).
+ * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
+ * @param cont Continuation to be called once CORE has taken the message.
+ * @param cont_cls Closure for @c cont.
+ *
+ * @return Handle to cancel the message before it is sent. Once cont is called
+ *         message has been sent and therefore the handle is no longer valid.
+ */
+struct CadetPeerQueue *
+GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
+               uint16_t payload_type, uint32_t payload_id, size_t size,
+               struct CadetConnection *c, int fwd,
+               GMP_sent cont, void *cont_cls)
+{
+  struct CadetPeerQueue *queue;
+  int priority;
+  int call_core;
+
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "que %s (%s %u) on connection %s (%p) %s towards %s (size %u)\n",
+       GM_m2s (type), GM_m2s (payload_type), payload_id,
+       GMC_2s (c), c, GM_f2s (fwd), GMP_2s (peer), size);
+
+  if (NULL == peer->connections)
+  {
+    /* We are not connected to this peer, ignore request. */
+    LOG (GNUNET_ERROR_TYPE_WARNING, "%s not a neighbor\n", GMP_2s (peer));
+    GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
+                              GNUNET_NO);
+    return NULL;
+  }
+
+  priority = 0;
+
+  if (GNUNET_MESSAGE_TYPE_CADET_POLL == type ||
+      GNUNET_MESSAGE_TYPE_CADET_ACK == type)
+  {
+    priority = 100;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
+
+  call_core = NULL == c ? GNUNET_YES : GMC_is_sendable (c, fwd);
+  queue = GNUNET_new (struct CadetPeerQueue);
+  queue->cls = cls;
+  queue->type = type;
+  queue->payload_type = payload_type;
+  queue->payload_id = payload_id;
+  queue->size = size;
+  queue->peer = peer;
+  queue->c = c;
+  queue->fwd = fwd;
+  queue->callback = cont;
+  queue->callback_cls = cont_cls;
+  if (100 > priority)
+  {
+    GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, 
queue);
+    peer->queue_n++;
+  }
+  else
+  {
+    GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
+    call_core = GNUNET_YES;
+  }
+
+  if (NULL == peer->core_transmit && GNUNET_YES == call_core)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "calling core tmt rdy towards %s for %u bytes\n",
+         GMP_2s (peer), size);
+    peer->core_transmit =
+        GNUNET_CORE_notify_transmit_ready (core_handle,
+                                           GNUNET_NO, get_priority (queue),
+                                           GNUNET_TIME_UNIT_FOREVER_REL,
+                                           GNUNET_PEER_resolve2 (peer->id),
+                                           size,
+                                           &queue_send,
+                                           peer);
+    queue->start_waiting = GNUNET_TIME_absolute_get ();
+  }
+  else if (GNUNET_NO == call_core)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s not needed\n",
+         GMP_2s (peer));
+
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s already called\n",
+         GMP_2s (peer));
+
+  }
+  queue_debug (peer);
+  return queue;
+}
+
+
+/**
+ * Cancel all queued messages to a peer that belong to a certain connection.
+ *
+ * @param peer Peer towards whom to cancel.
+ * @param c Connection whose queued messages to cancel. Might be destroyed by
+ *          the sent continuation call.
+ */
+void
+GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
+{
+  struct CadetPeerQueue *q;
+  struct CadetPeerQueue *next;
+  struct CadetPeerQueue *prev;
+
+  for (q = peer->queue_head; NULL != q; q = next)
+  {
+    prev = q->prev;
+    if (q->c == c)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GM_m2s (q->type));
+      if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY != q->type)
+      {
+        q->c = NULL;
+      }
+      else
+      {
+        GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
+      }
+
+      /* Get next from prev, q->next might be already freed:
+       * queue destroy -> callback -> GMC_destroy -> cancel_queues -> here
+       */
+      if (NULL == prev)
+        next = peer->queue_head;
+      else
+        next = prev->next;
+    }
+    else
+    {
+      next = q->next;
+    }
+  }
+  if (NULL == peer->queue_head)
+  {
+    if (NULL != peer->core_transmit)
+    {
+      GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
+      peer->core_transmit = NULL;
+    }
+  }
+}
+
+
+/**
+ * Get the first transmittable message for a connection.
+ *
+ * @param peer Neighboring peer.
+ * @param c Connection.
+ *
+ * @return First transmittable message.
+ */
+static struct CadetPeerQueue *
+connection_get_first_message (struct CadetPeer *peer, struct CadetConnection 
*c)
+{
+  struct CadetPeerQueue *q;
+
+  for (q = peer->queue_head; NULL != q; q = q->next)
+  {
+    if (q->c != c)
+      continue;
+    if (queue_is_sendable (q))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  sendable!!\n");
+      return q;
+    }
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  not sendable\n");
+  }
+
+  return NULL;
+}
+
+
+/**
+ * Get the first message for a connection and unqueue it.
+ *
+ * @param peer Neighboring peer.
+ * @param c Connection.
+ *
+ * @return First message for this connection.
+ */
+struct GNUNET_MessageHeader *
+GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c)
+{
+  struct CadetPeerQueue *q;
+  struct CadetPeerQueue *next;
+  struct GNUNET_MessageHeader *msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on %s\n", GMC_2s (c));
+  for (q = peer->queue_head; NULL != q; q = next)
+  {
+    next = q->next;
+    if (q->c != c)
+      continue;
+    switch (q->type)
+    {
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
+      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
+      case GNUNET_MESSAGE_TYPE_CADET_ACK:
+      case GNUNET_MESSAGE_TYPE_CADET_POLL:
+        GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
+        continue;
+
+      case GNUNET_MESSAGE_TYPE_CADET_KX:
+      case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
+        msg = (struct GNUNET_MessageHeader *) q->cls;
+        GMP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0);
+        return msg;
+
+      default:
+        GNUNET_break (0);
+    }
+  }
+
+  return NULL;
+}
+
+
+void
+GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c)
+{
+  struct CadetPeerQueue *q;
+  size_t size;
+
+  if (NULL != peer->core_transmit)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  already unlocked!\n");
+    return; /* Already unlocked */
+  }
+
+  q = connection_get_first_message (peer, c);
+  if (NULL == q)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  queue empty!\n");
+    return; /* Nothing to transmit */
+  }
+
+  size = q->size;
+  peer->core_transmit =
+      GNUNET_CORE_notify_transmit_ready (core_handle,
+                                         GNUNET_NO, get_priority (q),
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         GNUNET_PEER_resolve2 (peer->id),
+                                         size,
+                                         &queue_send,
+                                         peer);
+}
+
+
+/**
+ * Initialize the peer subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GMP_init (const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
+  peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS",
+                                             &max_peers))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               "CADET", "MAX_PEERS", "USING DEFAULT");
+    max_peers = 1000;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT",
+                                             &drop_percent))
+  {
+    drop_percent = 0;
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
+  }
+
+  core_handle = GNUNET_CORE_connect (c, /* Main configuration */
+                                     NULL,      /* Closure passed to CADET 
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 (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_yesno (c, "CADET", "DISABLE_TRY_CONNECT"))
+  {
+    transport_handle = GNUNET_TRANSPORT_connect (c, &my_full_id, NULL, /* cls 
*/
+                                                 /* Notify callbacks */
+                                                 NULL, NULL, NULL);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, "*  DISABLE TRYING CONNECT in config  
*\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, "*  Use this only for test purposes.  
*\n");
+    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
+    transport_handle = NULL;
+  }
+
+
+
+  if (NULL == core_handle)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+}
+
+/**
+ * Shut down the peer subsystem.
+ */
+void
+GMP_shutdown (void)
+{
+  GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
+
+  if (core_handle != NULL)
+  {
+    GNUNET_CORE_disconnect (core_handle);
+    core_handle = NULL;
+  }
+  if (transport_handle != NULL)
+  {
+    GNUNET_TRANSPORT_disconnect (transport_handle);
+    transport_handle = NULL;
+  }
+  GNUNET_PEER_change_rc (myid, -1);
+}
+
+/**
+ * Retrieve the CadetPeer stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer_id Full identity of the peer.
+ *
+ * @return Existing or newly created peer structure.
+ */
+struct CadetPeer *
+GMP_get (const struct GNUNET_PeerIdentity *peer_id)
+{
+  struct CadetPeer *peer;
+
+  peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
+  if (NULL == peer)
+  {
+    peer = GNUNET_new (struct CadetPeer);
+    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 CadetPeer 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 structure.
+ */
+struct CadetPeer *
+GMP_get_short (const GNUNET_PEER_Id peer)
+{
+  return GMP_get (GNUNET_PEER_resolve2 (peer));
+}
+
+
+/**
+ * Try to connect to a peer on transport level.
+ *
+ * @param cls Closure (peer).
+ * @param tc TaskContext.
+ */
+static void
+try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetPeer *peer = cls;
+
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    return;
+
+  GNUNET_TRANSPORT_try_connect (transport_handle,
+                                GNUNET_PEER_resolve2 (peer->id), NULL, NULL);
+}
+
+
+/**
+ * Try to establish a new connection to this peer (in its 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 Peer to connect to.
+ */
+void
+GMP_connect (struct CadetPeer *peer)
+{
+  struct CadetTunnel3 *t;
+  struct CadetPeerPath *p;
+  struct CadetConnection *c;
+  int rerun_search;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "peer_connect towards %s\n", GMP_2s (peer));
+
+  /* If we have a current hello, try to connect using it. */
+  GMP_try_connect (peer);
+
+  t = peer->tunnel;
+  c = NULL;
+  rerun_search = GNUNET_NO;
+
+  if (NULL != peer->path_head)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  some path exists\n");
+    p = peer_get_best_path (peer);
+    if (NULL != p)
+    {
+      char *s;
+
+      s = path_2s (p);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  path to use: %s\n", s);
+      GNUNET_free (s);
+
+      c = GMT_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 cadet
+         * 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.
+         *
+         * GMT_use_path -> GMC_new -> register_neighbors takes care of
+         * updating statistics about this issue.
+         */
+        rerun_search = GNUNET_YES;
+      }
+      else
+      {
+        GMC_send_create (c);
+        return;
+      }
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  but is NULL, all paths are in use\n");
+    }
+  }
+
+  if (NULL != peer->search_h && GNUNET_YES == rerun_search)
+  {
+    GMD_search_stop (peer->search_h);
+    peer->search_h = NULL;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "  Stopping DHT GET for peer %s\n",
+         GMP_2s (peer));
+  }
+
+  if (NULL == peer->search_h)
+  {
+    const struct GNUNET_PeerIdentity *id;
+
+    id = GNUNET_PEER_resolve2 (peer->id);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+                "  Starting DHT GET for peer %s\n", GMP_2s (peer));
+    peer->search_h = GMD_search (id, &search_handler, peer);
+    if (CADET_TUNNEL3_NEW == GMT_get_cstate (t))
+      GMT_change_cstate (t, CADET_TUNNEL3_SEARCHING);
+  }
+}
+
+
+/**
+ * Chech whether there is a direct (core level)  connection to peer.
+ *
+ * @param peer Peer to check.
+ *
+ * @return #GNUNET_YES if there is a direct connection.
+ */
+int
+GMP_is_neighbor (const struct CadetPeer *peer)
+{
+  struct CadetPeerPath *path;
+
+  if (NULL == peer->connections)
+    return GNUNET_NO;
+
+  for (path = peer->path_head; NULL != path; path = path->next)
+  {
+    if (3 > path->length)
+      return GNUNET_YES;
+  }
+
+  /* Is not a neighbor but connections is not NULL, probably disconnecting */
+  return GNUNET_NO;
+}
+
+
+/**
+ * Create and initialize a new tunnel towards a peer, in case it has none.
+ * In case the peer already has a tunnel, nothing is done.
+ *
+ * Does not generate any traffic, just creates the local data structures.
+ *
+ * @param peer Peer towards which to create the tunnel.
+ */
+void
+GMP_add_tunnel (struct CadetPeer *peer)
+{
+  if (NULL != peer->tunnel)
+    return;
+  peer->tunnel = GMT_new (peer);
+}
+
+
+/**
+ * Add a connection to a neighboring peer.
+ *
+ * Store that the peer is the first hop of the connection in one
+ * direction and that on peer disconnect the connection must be
+ * notified and destroyed, for it will no longer be valid.
+ *
+ * @param peer Peer to add connection to.
+ * @param c Connection to add.
+ *
+ * @return GNUNET_OK on success.
+ */
+int
+GMP_add_connection (struct CadetPeer *peer,
+                    struct CadetConnection *c)
+{
+  int result;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "adding connection %s\n", GMC_2s (c));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "to peer %s\n", GMP_2s (peer));
+
+  if (NULL == peer->connections)
+  {
+    GNUNET_break (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Peer %s is not a neighbor!\n",
+         GMP_2s (peer));
+    return GNUNET_SYSERR;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "peer %s ok, has %u connections.\n",
+       GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections));
+  result = GNUNET_CONTAINER_multihashmap_put (peer->connections,
+                                              GMC_get_h (c),
+                                              c,
+                                              
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       " now has %u connections.\n",
+       GNUNET_CONTAINER_multihashmap_size (peer->connections));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "result %u\n", result);
+
+  return result;
+}
+
+
+/**
+ * Add the path to the peer and update the path used to reach it in case this
+ * is the shortest.
+ *
+ * @param peer 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?
+ *
+ * @return path if path was taken, pointer to existing duplicate if exists
+ *         NULL on error.
+ */
+struct CadetPeerPath *
+GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *path,
+              int trusted)
+{
+  struct CadetPeerPath *aux;
+  unsigned int l;
+  unsigned int l2;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
+       path->length, GMP_2s (peer));
+
+  if ((NULL == peer) || (NULL == path))
+  {
+    GNUNET_break (0);
+    path_destroy (path);
+    return NULL;
+  }
+  if (path->peers[path->length - 1] != peer->id)
+  {
+    GNUNET_break (0);
+    path_destroy (path);
+    return NULL;
+  }
+
+  for (l = 1; l < path->length; l++)
+  {
+    if (path->peers[l] == myid)
+    {
+      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));
+    }
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length);
+
+  if (2 >= path->length && GNUNET_NO == trusted)
+  {
+    /* Only allow CORE to tell us about direct paths */
+    path_destroy (path);
+    return NULL;
+  }
+
+  l = path_get_length (path);
+  if (0 == l)
+  {
+    path_destroy (path);
+    return NULL;
+  }
+
+  GNUNET_assert (peer->id == path->peers[path->length - 1]);
+  for (aux = peer->path_head; aux != NULL; aux = aux->next)
+  {
+    l2 = path_get_length (aux);
+    if (l2 > l)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  added\n");
+      GNUNET_CONTAINER_DLL_insert_before (peer->path_head,
+                                          peer->path_tail, aux, path);
+      if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel))
+      {
+        GMP_connect (peer);
+      }
+      return path;
+    }
+    else
+    {
+      if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "  already known\n");
+        path_destroy (path);
+        return aux;
+      }
+    }
+  }
+  GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, peer->path_tail,
+                                    path);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  added last\n");
+  if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel))
+  {
+    GMP_connect (peer);
+  }
+  return path;
+}
+
+
+/**
+ * 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 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?
+ *
+ * @return path if path was taken, pointer to existing duplicate if exists
+ *         NULL on error.
+ */
+struct CadetPeerPath *
+GMP_add_path_to_origin (struct CadetPeer *peer,
+                        struct CadetPeerPath *path,
+                        int trusted)
+{
+  if (NULL == path)
+    return NULL;
+  path_invert (path);
+  return GMP_add_path (peer, path, trusted);
+}
+
+
+/**
+ * Adds a path to the info of all the peers in the path
+ *
+ * @param p Path to process.
+ * @param confirmed Whether we know if the path works or not.
+ */
+void
+GMP_add_path_to_all (const struct CadetPeerPath *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 CadetPeer *aux;
+    struct CadetPeerPath *copy;
+
+    aux = GMP_get_short (p->peers[i]);
+    copy = path_duplicate (p);
+    copy->length = i + 1;
+    GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
+  }
+}
+
+
+/**
+ * Remove any path to the peer that has the extact same peers as the one given.
+ *
+ * @param peer Peer to remove the path from.
+ * @param path Path to remove. Is always destroyed .
+ */
+void
+GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path)
+{
+  struct CadetPeerPath *iter;
+  struct CadetPeerPath *next;
+
+  GNUNET_assert (myid == path->peers[0]);
+  GNUNET_assert (peer->id == path->peers[path->length - 1]);
+
+  for (iter = peer->path_head; NULL != iter; iter = next)
+  {
+    next = iter->next;
+    if (0 == memcmp (path->peers, iter->peers,
+                     sizeof (GNUNET_PEER_Id) * path->length))
+    {
+      GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter);
+      if (iter != path)
+        path_destroy (iter);
+    }
+  }
+  path_destroy (path);
+}
+
+
+/**
+ * Remove a connection from a neighboring peer.
+ *
+ * @param peer Peer to remove connection from.
+ * @param c Connection to remove.
+ *
+ * @return GNUNET_OK on success.
+ */
+int
+GMP_remove_connection (struct CadetPeer *peer,
+                       const struct CadetConnection *c)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "removing connection %s\n", GMC_2s (c));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "from peer %s\n", GMP_2s (peer));
+
+  if (NULL == peer || NULL == peer->connections)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Peer %s is not a neighbor!\n",
+         GMP_2s (peer));
+    return GNUNET_SYSERR;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "peer %s ok, has %u connections.\n",
+       GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections));
+
+  return GNUNET_CONTAINER_multihashmap_remove (peer->connections,
+                                               GMC_get_h (c),
+                                               c);
+}
+
+/**
+ * Start the DHT search for new paths towards the peer: we don't have
+ * enough good connections.
+ *
+ * @param peer Destination peer.
+ */
+void
+GMP_start_search (struct CadetPeer *peer)
+{
+  if (NULL != peer->search_h)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  peer->search_h = GMD_search (GMP_get_id (peer), &search_handler, peer);
+}
+
+
+/**
+ * Stop the DHT search for new paths towards the peer: we already have
+ * enough good connections.
+ *
+ * @param peer Destination peer.
+ */
+void
+GMP_stop_search (struct CadetPeer *peer)
+{
+  if (NULL == peer->search_h)
+  {
+    return;
+  }
+
+  GMD_search_stop (peer->search_h);
+  peer->search_h = NULL;
+}
+
+
+/**
+ * Get the Full ID of a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Full ID of peer.
+ */
+const struct GNUNET_PeerIdentity *
+GMP_get_id (const struct CadetPeer *peer)
+{
+  return GNUNET_PEER_resolve2 (peer->id);
+}
+
+
+/**
+ * Get the Short ID of a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Short ID of peer.
+ */
+GNUNET_PEER_Id
+GMP_get_short_id (const struct CadetPeer *peer)
+{
+  return peer->id;
+}
+
+
+/**
+ * Set tunnel.
+ *
+ * @param peer Peer.
+ * @param t Tunnel.
+ */
+void
+GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t)
+{
+  peer->tunnel = t;
+  if (NULL == t && NULL != peer->search_h)
+  {
+    GMP_stop_search (peer);
+  }
+}
+
+
+/**
+ * Get the tunnel towards a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Tunnel towards peer.
+ */
+struct CadetTunnel3 *
+GMP_get_tunnel (const struct CadetPeer *peer)
+{
+  return peer->tunnel;
+}
+
+
+/**
+ * Set the hello message.
+ *
+ * @param peer Peer whose message to set.
+ * @param hello Hello message.
+ */
+void
+GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message 
*hello)
+{
+  struct GNUNET_HELLO_Message *old;
+  size_t size;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GMP_2s (peer));
+  if (NULL == hello)
+    return;
+
+  old = GMP_get_hello (peer);
+  if (NULL == old)
+  {
+    size = GNUNET_HELLO_size (hello);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " new (%u bytes)\n", size);
+    peer->hello = GNUNET_malloc (size);
+    memcpy (peer->hello, hello, size);
+  }
+  else
+  {
+    peer->hello = GNUNET_HELLO_merge (old, hello);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " merge into %p (%u bytes)\n",
+         peer->hello, GNUNET_HELLO_size (hello));
+    GNUNET_free (old);
+  }
+}
+
+
+/**
+ * Get the hello message.
+ *
+ * @param peer Peer whose message to get.
+ *
+ * @return Hello message.
+ */
+struct GNUNET_HELLO_Message *
+GMP_get_hello (struct CadetPeer *peer)
+{
+  struct GNUNET_TIME_Absolute expiration;
+  struct GNUNET_TIME_Relative remaining;
+
+  if (NULL == peer->hello)
+    return NULL;
+
+  expiration = GNUNET_HELLO_get_last_expiration (peer->hello);
+  remaining = GNUNET_TIME_absolute_get_remaining (expiration);
+  if (0 == remaining.rel_value_us)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n",
+         GNUNET_STRINGS_absolute_time_to_string (expiration));
+    GNUNET_free (peer->hello);
+    peer->hello = NULL;
+  }
+  return peer->hello;
+}
+
+
+/**
+ * Try to connect to a peer on TRANSPORT level.
+ *
+ * @param peer Peer to whom to connect.
+ */
+void
+GMP_try_connect (struct CadetPeer *peer)
+{
+  struct GNUNET_HELLO_Message *hello;
+  struct GNUNET_MessageHeader *mh;
+
+  if (NULL == transport_handle)
+    return;
+
+  hello = GMP_get_hello (peer);
+  if (NULL == hello)
+    return;
+
+  mh = GNUNET_HELLO_get_header (hello);
+  GNUNET_TRANSPORT_offer_hello (transport_handle, mh, try_connect, peer);
+}
+
+
+/**
+ * Notify a peer that a link between two other peers is broken. If any path
+ * used that link, eliminate it.
+ *
+ * @param peer Peer affected by the change.
+ * @param peer1 Peer whose link is broken.
+ * @param peer2 Peer whose link is broken.
+ */
+void
+GMP_notify_broken_link (struct CadetPeer *peer,
+                        struct GNUNET_PeerIdentity *peer1,
+                        struct GNUNET_PeerIdentity *peer2)
+{
+  struct CadetPeerPath *iter;
+  struct CadetPeerPath *next;
+  unsigned int i;
+  GNUNET_PEER_Id p1;
+  GNUNET_PEER_Id p2;
+
+  p1 = GNUNET_PEER_search (peer1);
+  p2 = GNUNET_PEER_search (peer2);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2);
+  if (0 == p1 || 0 == p2)
+  {
+    /* We don't even know them */
+    return;
+  }
+
+  for (iter = peer->path_head; NULL != iter; iter = next)
+  {
+    next = iter->next;
+    for (i = 0; i < iter->length - 1; i++)
+    {
+      if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2)
+          || (iter->peers[i] == p2 && iter->peers[i + 1] == p1))
+      {
+        char *s;
+
+        s = path_2s (iter);
+        LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s);
+        GNUNET_free (s);
+
+        path_invalidate (iter);
+      }
+    }
+  }
+}
+
+
+/**
+ * Count the number of known paths toward the peer.
+ *
+ * @param peer Peer to get path info.
+ *
+ * @return Number of known paths.
+ */
+unsigned int
+GMP_count_paths (const struct CadetPeer *peer)
+{
+  struct CadetPeerPath *iter;
+  unsigned int i;
+
+  for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next)
+    i++;
+
+  return i;
+}
+
+
+/**
+ * Iterate all known peers.
+ *
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
+{
+  GNUNET_CONTAINER_multipeermap_iterate (peers, iter, cls);
+}
+
+
+/**
+ * Get the static string for a peer ID.
+ *
+ * @param peer Peer.
+ *
+ * @return Static string for it's ID.
+ */
+const char *
+GMP_2s (const struct CadetPeer *peer)
+{
+  if (NULL == peer)
+    return "(NULL)";
+  return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_peer.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_peer.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_peer.h                                
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_peer.h        2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,418 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_peer.h
+ * @brief cadet service; dealing with remote peers
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GMP (Gnunet Cadet Peer)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_PEER_H
+#define GNUNET_SERVICE_CADET_PEER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+/**
+ * Struct containing all information regarding a given peer
+ */
+struct CadetPeer;
+
+/**
+ * Struct containing info about a queued transmission to this peer
+ */
+struct CadetPeerQueue;
+
+#include "gnunet-service-cadet_connection.h"
+
+/**
+ * Callback called when a queued message is sent.
+ *
+ * @param cls Closure.
+ * @param c Connection this message was on.
+ * @param sent Was it really sent? (Could have been canceled)
+ * @param type Type of message sent.
+ * @param pid Packet ID, or 0 if not applicable (create, destroy, etc).
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ * @param wait Time spent waiting for core (only the time for THIS message)
+ */
+typedef void (*GMP_sent) (void *cls,
+                          struct CadetConnection *c, int sent,
+                          uint16_t type, uint32_t pid, int fwd, size_t size,
+                          struct GNUNET_TIME_Relative wait);
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize peer subsystem.
+ *
+ * @param c Configuration.
+ */
+void
+GMP_init (const struct GNUNET_CONFIGURATION_Handle *c);
+
+/**
+ * Shut down the peer subsystem.
+ */
+void
+GMP_shutdown (void);
+
+
+/**
+ * Retrieve the CadetPeer stucture associated with the peer, create one
+ * and insert it in the appropriate structures if the peer is not known yet.
+ *
+ * @param peer_id Full identity of the peer.
+ *
+ * @return Existing or newly created peer structure.
+ */
+struct CadetPeer *
+GMP_get (const struct GNUNET_PeerIdentity *peer_id);
+
+
+/**
+ * Retrieve the CadetPeer 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 structure.
+ */
+struct CadetPeer *
+GMP_get_short (const GNUNET_PEER_Id peer);
+
+/**
+ * Try to establish a new connection to this peer (in its 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 Peer to connect to.
+ */
+void
+GMP_connect (struct CadetPeer *peer);
+
+/**
+ * Free a transmission that was already queued with all resources
+ * associated to the request.
+ *
+ * @param queue Queue handler to cancel.
+ * @param clear_cls Is it necessary to free associated cls?
+ * @param sent Was it really sent? (Could have been canceled)
+ * @param pid PID, if relevant (was sent and was a payload message).
+ */
+void
+GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
+                   int sent, uint32_t pid);
+
+/**
+ * @brief Queue and pass message to core when possible.
+ *
+ * @param peer Peer towards which to queue the message.
+ * @param cls Closure (@c type dependant). It will be used by queue_send to
+ *            build the message to be sent if not already prebuilt.
+ * @param type Type of the message, 0 for a raw message.
+ * @param size Size of the message.
+ * @param c Connection this message belongs to (cannot be NULL).
+ * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
+ * @param cont Continuation to be called once CORE has taken the message.
+ * @param cont_cls Closure for @c cont.
+ *
+ * @return Handle to cancel the message before it is sent. Once cont is called
+ *         message has been sent and therefore the handle is no longer valid.
+ */
+struct CadetPeerQueue *
+GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
+               uint16_t payload_type, uint32_t payload_id,
+               size_t size, struct CadetConnection *c, int fwd,
+               GMP_sent cont, void *cont_cls);
+
+/**
+ * Cancel all queued messages to a peer that belong to a certain connection.
+ *
+ * @param peer Peer towards whom to cancel.
+ * @param c Connection whose queued messages to cancel. Might be destroyed by
+ *          the sent continuation call.
+ */
+void
+GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c);
+
+/**
+ * Get the first message for a connection and unqueue it.
+ *
+ * @param peer Neighboring peer.
+ * @param c Connection.
+ *
+ * @return First message for this connection.
+ */
+struct GNUNET_MessageHeader *
+GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c);
+
+void
+GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c);
+
+/**
+ * Set tunnel.
+ *
+ * @param peer Peer.
+ * @param t Tunnel.
+ */
+void
+GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t);
+
+/**
+ * Check whether there is a direct (core level)  connection to peer.
+ *
+ * @param peer Peer to check.
+ *
+ * @return #GNUNET_YES if there is a direct connection.
+ */
+int
+GMP_is_neighbor (const struct CadetPeer *peer);
+
+/**
+ * Create and initialize a new tunnel towards a peer, in case it has none.
+ *
+ * Does not generate any traffic, just creates the local data structures.
+ *
+ * @param peer Peer towards which to create the tunnel.
+ */
+void
+GMP_add_tunnel (struct CadetPeer *peer);
+
+/**
+ * Add a connection to a neighboring peer.
+ *
+ * Store that the peer is the first hop of the connection in one
+ * direction and that on peer disconnect the connection must be
+ * notified and destroyed, for it will no longer be valid.
+ *
+ * @param peer Peer to add connection to.
+ * @param c Connection to add.
+ *
+ * @return GNUNET_OK on success.
+ */
+int
+GMP_add_connection (struct CadetPeer *peer, struct CadetConnection *c);
+
+/**
+ * Add the path to the peer and update the path used to reach it in case this
+ * is the shortest.
+ *
+ * @param peer 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?
+ *
+ * @return path if path was taken, pointer to existing duplicate if exists
+ *         NULL on error.
+ */
+struct CadetPeerPath *
+GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *p, int trusted);
+
+/**
+ * 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 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?
+ *
+ * @return path if path was taken, pointer to existing duplicate if exists
+ *         NULL on error.
+ */
+struct CadetPeerPath *
+GMP_add_path_to_origin (struct CadetPeer *peer,
+                        struct CadetPeerPath *path,
+                        int trusted);
+
+/**
+ * Adds a path to the info of all the peers in the path
+ *
+ * @param p Path to process.
+ * @param confirmed Whether we know if the path works or not.
+ */
+void
+GMP_add_path_to_all (const struct CadetPeerPath *p, int confirmed);
+
+/**
+ * Remove any path to the peer that has the extact same peers as the one given.
+ *
+ * @param peer Peer to remove the path from.
+ * @param path Path to remove. Is always destroyed .
+ */
+void
+GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path);
+
+/**
+ * Remove a connection from a neighboring peer.
+ *
+ * @param peer Peer to remove connection from.
+ * @param c Connection to remove.
+ *
+ * @return GNUNET_OK on success.
+ */
+int
+GMP_remove_connection (struct CadetPeer *peer, const struct CadetConnection 
*c);
+
+/**
+ * Start the DHT search for new paths towards the peer: we don't have
+ * enough good connections.
+ *
+ * @param peer Destination peer.
+ */
+void
+GMP_start_search (struct CadetPeer *peer);
+
+/**
+ * Stop the DHT search for new paths towards the peer: we already have
+ * enough good connections.
+ *
+ * @param peer Destination peer.
+ */
+void
+GMP_stop_search (struct CadetPeer *peer);
+
+/**
+ * Get the Full ID of a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Full ID of peer.
+ */
+const struct GNUNET_PeerIdentity *
+GMP_get_id (const struct CadetPeer *peer);
+
+/**
+ * Get the Short ID of a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Short ID of peer.
+ */
+GNUNET_PEER_Id
+GMP_get_short_id (const struct CadetPeer *peer);
+
+/**
+ * Get the tunnel towards a peer.
+ *
+ * @param peer Peer to get from.
+ *
+ * @return Tunnel towards peer.
+ */
+struct CadetTunnel3 *
+GMP_get_tunnel (const struct CadetPeer *peer);
+
+/**
+ * Set the hello message.
+ *
+ * @param peer Peer whose message to set.
+ * @param hello Hello message.
+ */
+void
+GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message 
*hello);
+
+/**
+ * Get the hello message.
+ *
+ * @param peer Peer whose message to get.
+ *
+ * @return Hello message.
+ */
+struct GNUNET_HELLO_Message *
+GMP_get_hello (struct CadetPeer *peer);
+
+
+/**
+ * Try to connect to a peer on TRANSPORT level.
+ *
+ * @param peer Peer to whom to connect.
+ */
+void
+GMP_try_connect (struct CadetPeer *peer);
+
+/**
+ * Notify a peer that a link between two other peers is broken. If any path
+ * used that link, eliminate it.
+ *
+ * @param peer Peer affected by the change.
+ * @param peer1 Peer whose link is broken.
+ * @param peer2 Peer whose link is broken.
+ */
+void
+GMP_notify_broken_link (struct CadetPeer *peer,
+                        struct GNUNET_PeerIdentity *peer1,
+                        struct GNUNET_PeerIdentity *peer2);
+
+/**
+ * Count the number of known paths toward the peer.
+ *
+ * @param peer Peer to get path info.
+ *
+ * @return Number of known paths.
+ */
+unsigned int
+GMP_count_paths (const struct CadetPeer *peer);
+
+/**
+ * Iterate all known peers.
+ *
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
+
+/**
+ * Get the static string for a peer ID.
+ *
+ * @param peer Peer.
+ *
+ * @return Static string for it's ID.
+ */
+const char *
+GMP_2s (const struct CadetPeer *peer);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_PEER_H */
+#endif
+/* end of gnunet-cadet-service_peer.h */

Copied: gnunet/src/cadet/gnunet-service-cadet_tunnel.c (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_tunnel.c)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_tunnel.c                              
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_tunnel.c      2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,2887 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet_signatures.h"
+#include "gnunet_statistics_service.h"
+
+#include "cadet_protocol.h"
+#include "cadet_path.h"
+
+#include "gnunet-service-cadet_tunnel.h"
+#include "gnunet-service-cadet_connection.h"
+#include "gnunet-service-cadet_channel.h"
+#include "gnunet-service-cadet_peer.h"
+
+#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
+
+#define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
+
+#define CONNECTIONS_PER_TUNNEL 3
+
+/******************************************************************************/
+/********************************   STRUCTS  
**********************************/
+/******************************************************************************/
+
+struct CadetTChannel
+{
+  struct CadetTChannel *next;
+  struct CadetTChannel *prev;
+  struct CadetChannel *ch;
+};
+
+
+/**
+ * Connection list and metadata.
+ */
+struct CadetTConnection
+{
+  /**
+   * Next in DLL.
+   */
+  struct CadetTConnection *next;
+
+  /**
+   * Prev in DLL.
+   */
+  struct CadetTConnection *prev;
+
+  /**
+   * Connection handle.
+   */
+  struct CadetConnection *c;
+
+  /**
+   * Creation time, to keep oldest connection alive.
+   */
+  struct GNUNET_TIME_Absolute created;
+
+  /**
+   * Connection throughput, to keep fastest connection alive.
+   */
+  uint32_t throughput;
+};
+
+/**
+ * Structure used during a Key eXchange.
+ */
+struct CadetTunnelKXCtx
+{
+  /**
+   * Decryption ("their") old key, for decrypting traffic sent by the
+   * other end before the key exchange started.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old;
+
+  /**
+   * Challenge to send in a ping and expect in the pong.
+   */
+  uint32_t challenge;
+};
+
+/**
+ * Struct containing all information regarding a tunnel to a peer.
+ */
+struct CadetTunnel3
+{
+    /**
+     * Endpoint of the tunnel.
+     */
+  struct CadetPeer *peer;
+
+    /**
+     * State of the tunnel connectivity.
+     */
+  enum CadetTunnel3CState cstate;
+
+  /**
+   * State of the tunnel encryption.
+   */
+  enum CadetTunnel3EState estate;
+
+  /**
+   * Key eXchange context.
+   */
+  struct CadetTunnelKXCtx *kx_ctx;
+
+  /**
+   * Encryption ("our") key.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
+
+  /**
+   * Decryption ("their") key.
+   */
+  struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
+
+  /**
+   * Task to start the rekey process.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier rekey_task;
+
+  /**
+   * Paths that are actively used to reach the destination peer.
+   */
+  struct CadetTConnection *connection_head;
+  struct CadetTConnection *connection_tail;
+
+  /**
+   * Next connection number.
+   */
+  uint32_t next_cid;
+
+  /**
+   * Channels inside this tunnel.
+   */
+  struct CadetTChannel *channel_head;
+  struct CadetTChannel *channel_tail;
+
+  /**
+   * Channel ID for the next created channel.
+   */
+  CADET_ChannelNumber next_chid;
+
+  /**
+   * Destroy flag: if true, destroy on last message.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier destroy_task;
+
+  /**
+   * Queued messages, to transmit once tunnel gets connected.
+   */
+  struct CadetTunnelDelayed *tq_head;
+  struct CadetTunnelDelayed *tq_tail;
+};
+
+
+/**
+ * Struct used to save messages in a non-ready tunnel to send once connected.
+ */
+struct CadetTunnelDelayed
+{
+  /**
+   * DLL
+   */
+  struct CadetTunnelDelayed *next;
+  struct CadetTunnelDelayed *prev;
+
+  /**
+   * Tunnel.
+   */
+  struct CadetTunnel3 *t;
+
+  /**
+   * Tunnel queue given to the channel to cancel request. Update on 
send_queued.
+   */
+  struct CadetTunnel3Queue *tq;
+
+  /**
+   * Message to send.
+   */
+  /* struct GNUNET_MessageHeader *msg; */
+};
+
+
+/**
+ * Handle for messages queued but not yet sent.
+ */
+struct CadetTunnel3Queue
+{
+  /**
+   * Connection queue handle, to cancel if necessary.
+   */
+  struct CadetConnectionQueue *cq;
+
+  /**
+   * Handle in case message hasn't been given to a connection yet.
+   */
+  struct CadetTunnelDelayed *tqd;
+
+  /**
+   * Continuation to call once sent.
+   */
+  GMT_sent cont;
+
+  /**
+   * Closure for @c cont.
+   */
+  void *cont_cls;
+};
+
+
+/******************************************************************************/
+/*******************************   GLOBALS  
***********************************/
+/******************************************************************************/
+
+/**
+ * Global handle to the statistics service.
+ */
+extern struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Local peer own ID (memory efficient handle).
+ */
+extern GNUNET_PEER_Id myid;
+
+/**
+ * Local peer own ID (full value).
+ */
+extern struct GNUNET_PeerIdentity my_full_id;
+
+
+/**
+ * Don't try to recover tunnels if shutting down.
+ */
+extern int shutting_down;
+
+
+/**
+ * Set of all tunnels, in order to trigger a new exchange on rekey.
+ * Indexed by peer's ID.
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
+
+/**
+ * Default TTL for payload packets.
+ */
+static unsigned long long default_ttl;
+
+/**
+ * Own private key.
+ */
+const static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
+
+/**
+ * Own ephemeral private key.
+ */
+static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
+
+/**
+ * Cached message used to perform a key exchange.
+ */
+static struct GNUNET_CADET_KX_Ephemeral kx_msg;
+
+/**
+ * Task to generate a new ephemeral key.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier rekey_task;
+
+/**
+ * Rekey period.
+ */
+static struct GNUNET_TIME_Relative rekey_period;
+
+/******************************************************************************/
+/********************************   STATIC  
***********************************/
+/******************************************************************************/
+
+/**
+ * Get string description for tunnel connectivity state.
+ *
+ * @param cs Tunnel state.
+ *
+ * @return String representation.
+ */
+static const char *
+cstate2s (enum CadetTunnel3CState cs)
+{
+  static char buf[128];
+
+  switch (cs)
+  {
+    case CADET_TUNNEL3_NEW:
+      return "CADET_TUNNEL3_NEW";
+    case CADET_TUNNEL3_SEARCHING:
+      return "CADET_TUNNEL3_SEARCHING";
+    case CADET_TUNNEL3_WAITING:
+      return "CADET_TUNNEL3_WAITING";
+    case CADET_TUNNEL3_READY:
+      return "CADET_TUNNEL3_READY";
+
+    default:
+      sprintf (buf, "%u (UNKNOWN STATE)", cs);
+      return buf;
+  }
+  return "";
+}
+
+
+/**
+ * Get string description for tunnel encryption state.
+ *
+ * @param es Tunnel state.
+ *
+ * @return String representation.
+ */
+static const char *
+estate2s (enum CadetTunnel3EState es)
+{
+  static char buf[128];
+
+  switch (es)
+  {
+    case CADET_TUNNEL3_KEY_UNINITIALIZED:
+      return "CADET_TUNNEL3_KEY_UNINITIALIZED";
+    case CADET_TUNNEL3_KEY_SENT:
+      return "CADET_TUNNEL3_KEY_SENT";
+    case CADET_TUNNEL3_KEY_PING:
+      return "CADET_TUNNEL3_KEY_PING";
+    case CADET_TUNNEL3_KEY_OK:
+      return "CADET_TUNNEL3_KEY_OK";
+
+    default:
+      sprintf (buf, "%u (UNKNOWN STATE)", es);
+      return buf;
+  }
+  return "";
+}
+
+
+/**
+ * @brief Check if tunnel is ready to send traffic.
+ *
+ * Tunnel must be connected and with encryption correctly set up.
+ *
+ * @param t Tunnel to check.
+ *
+ * @return #GNUNET_YES if ready, #GNUNET_NO otherwise
+ */
+static int
+is_ready (struct CadetTunnel3 *t)
+{
+  int ready;
+
+  GMT_debug (t);
+  ready = (CADET_TUNNEL3_READY == t->cstate && CADET_TUNNEL3_KEY_OK == 
t->estate);
+  ready = ready || GMT_is_loopback (t);
+  return ready;
+}
+
+
+/**
+ * Ephemeral key message purpose size.
+ *
+ * @return Size of the part of the ephemeral key message that must be signed.
+ */
+size_t
+ephemeral_purpose_size (void)
+{
+  return sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+         sizeof (struct GNUNET_TIME_AbsoluteNBO) +
+         sizeof (struct GNUNET_TIME_AbsoluteNBO) +
+         sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
+         sizeof (struct GNUNET_PeerIdentity);
+}
+
+
+/**
+ * Size of the encrypted part of a ping message.
+ *
+ * @return Size of the encrypted part of a ping message.
+ */
+size_t
+ping_encryption_size (void)
+{
+  return sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t);
+}
+
+
+/**
+ * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!!
+ *
+ * @param tch Tunnel's channel handle.
+ *
+ * @return Amount of messages the channel can still buffer towards the client.
+ */
+static unsigned int
+get_channel_buffer (const struct CadetTChannel *tch)
+{
+  int fwd;
+
+  /* If channel is outgoing, is origin in the FWD direction and fwd is YES */
+  fwd = GMCH_is_origin (tch->ch, GNUNET_YES);
+
+  return GMCH_get_buffer (tch->ch, fwd);
+}
+
+
+/**
+ * Get the channel's allowance status.
+ *
+ * @param tch Tunnel's channel handle.
+ *
+ * @return #GNUNET_YES if we allowed the client to send data to us.
+ */
+static int
+get_channel_allowed (const struct CadetTChannel *tch)
+{
+  int fwd;
+
+  /* If channel is outgoing, is origin in the FWD direction and fwd is YES */
+  fwd = GMCH_is_origin (tch->ch, GNUNET_YES);
+
+  return GMCH_get_allowed (tch->ch, fwd);
+}
+
+
+/**
+ * Get the connection's buffer.
+ *
+ * @param tc Tunnel's connection handle.
+ *
+ * @return Amount of messages the connection can still buffer.
+ */
+static unsigned int
+get_connection_buffer (const struct CadetTConnection *tc)
+{
+  int fwd;
+
+  /* If connection is outgoing, is origin in the FWD direction and fwd is YES 
*/
+  fwd = GMC_is_origin (tc->c, GNUNET_YES);
+
+  return GMC_get_buffer (tc->c, fwd);
+}
+
+
+/**
+ * Get the connection's allowance.
+ *
+ * @param tc Tunnel's connection handle.
+ *
+ * @return Amount of messages we have allowed the next peer to send us.
+ */
+static unsigned int
+get_connection_allowed (const struct CadetTConnection *tc)
+{
+  int fwd;
+
+  /* If connection is outgoing, is origin in the FWD direction and fwd is YES 
*/
+  fwd = GMC_is_origin (tc->c, GNUNET_YES);
+
+  return GMC_get_allowed (tc->c, fwd);
+}
+
+
+/**
+ * Check that a ephemeral key message s well formed and correctly signed.
+ *
+ * @param t Tunnel on which the message came.
+ * @param msg The ephemeral key message.
+ *
+ * @return GNUNET_OK if message is fine, GNUNET_SYSERR otherwise.
+ */
+int
+check_ephemeral (struct CadetTunnel3 *t,
+                 const struct GNUNET_CADET_KX_Ephemeral *msg)
+{
+  /* Check message size */
+  if (ntohs (msg->header.size) != sizeof (struct GNUNET_CADET_KX_Ephemeral))
+    return GNUNET_SYSERR;
+
+  /* Check signature size */
+  if (ntohl (msg->purpose.size) != ephemeral_purpose_size ())
+    return GNUNET_SYSERR;
+
+  /* Check origin */
+  if (0 != memcmp (&msg->origin_identity,
+                   GMP_get_id (t->peer),
+                   sizeof (struct GNUNET_PeerIdentity)))
+    return GNUNET_SYSERR;
+
+  /* Check signature */
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_CADET_KX,
+                                  &msg->purpose,
+                                  &msg->signature,
+                                  &msg->origin_identity.public_key))
+    return GNUNET_SYSERR;
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * 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. Can overlap with @c dst.
+ * @param size Size of the plaintext.
+ * @param iv Initialization Vector to use.
+ */
+static int
+t_encrypt (struct CadetTunnel3 *t,
+           void *dst, const void *src,
+           size_t size, uint32_t iv)
+{
+  struct GNUNET_CRYPTO_SymmetricInitializationVector siv;
+  size_t out_size;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_encrypt start\n");
+  GNUNET_CRYPTO_symmetric_derive_iv (&siv, &t->e_key, &iv, sizeof (iv), NULL);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_encrypt IV derived\n");
+  out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &t->e_key, &siv, dst);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_encrypt end\n");
+
+  return out_size;
+}
+
+
+/**
+ * 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. Can overlap with @c dst.
+ * @param size Size of the encrypted data.
+ * @param iv Initialization Vector to use.
+ */
+static int
+t_decrypt (struct CadetTunnel3 *t,
+           void *dst, const void *src,
+           size_t size, uint32_t iv)
+{
+  struct GNUNET_CRYPTO_SymmetricInitializationVector siv;
+  struct GNUNET_CRYPTO_SymmetricSessionKey *key;
+  size_t out_size;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt start\n");
+  if (t->estate == CADET_TUNNEL3_KEY_OK || t->estate == CADET_TUNNEL3_KEY_PING)
+  {
+    key = &t->d_key;
+  }
+  else if (NULL != t->kx_ctx)
+  {
+    key = &t->kx_ctx->d_key_old;
+  }
+  else
+  {
+    GNUNET_STATISTICS_update (stats, "# non decryptable data", 1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "WARNING got data on %s without a valid key\n",
+         GMT_2s (t));
+    GMT_debug (t);
+    return 0;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt iv\n");
+  GNUNET_CRYPTO_symmetric_derive_iv (&siv, key, &iv, sizeof (iv), NULL);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt iv done\n");
+  out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, key, &siv, dst);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt end\n");
+
+  return out_size;
+}
+
+
+/**
+ * Create key material by doing ECDH on the local and remote ephemeral keys.
+ *
+ * @param key_material Where to store the key material.
+ * @param ephemeral_key Peer's public ephemeral key.
+ */
+void
+derive_key_material (struct GNUNET_HashCode *key_material,
+                     const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key)
+{
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
+                              ephemeral_key,
+                              key_material))
+  {
+    GNUNET_break (0);
+  }
+}
+
+/**
+ * Create a symmetic key from the identities of both ends and the key material
+ * from ECDH.
+ *
+ * @param key Destination for the generated key.
+ * @param sender ID of the peer that will encrypt with @c key.
+ * @param receiver ID of the peer that will decrypt with @c key.
+ * @param key_material Hash created with ECDH with the ephemeral keys.
+ */
+void
+derive_symmertic (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+                  const struct GNUNET_PeerIdentity *sender,
+                  const struct GNUNET_PeerIdentity *receiver,
+                  const struct GNUNET_HashCode *key_material)
+{
+  const char salt[] = "CADET kx salt";
+
+  GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
+                     salt, sizeof (salt),
+                     key_material, sizeof (struct GNUNET_HashCode),
+                     sender, sizeof (struct GNUNET_PeerIdentity),
+                     receiver, sizeof (struct GNUNET_PeerIdentity),
+                     NULL);
+}
+
+/**
+ * Pick a connection on which send the next data message.
+ *
+ * @param t Tunnel on which to send the message.
+ *
+ * @return The connection on which to send the next message.
+ */
+static struct CadetConnection *
+tunnel_get_connection (struct CadetTunnel3 *t)
+{
+  struct CadetTConnection *iter;
+  struct CadetConnection *best;
+  unsigned int qn;
+  unsigned int lowest_q;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GMT_2s (t));
+  best = NULL;
+  lowest_q = UINT_MAX;
+  for (iter = t->connection_head; NULL != iter; iter = iter->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection %s: %u\n",
+         GMC_2s (iter->c), GMC_get_state (iter->c));
+    if (CADET_CONNECTION_READY == GMC_get_state (iter->c))
+    {
+      qn = GMC_get_qn (iter->c, GMC_is_origin (iter->c, GNUNET_YES));
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "    q_n %u, \n", qn);
+      if (qn < lowest_q)
+      {
+        best = iter->c;
+        lowest_q = qn;
+      }
+    }
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GMC_2s (best));
+  return best;
+}
+
+
+/**
+ * Callback called when a queued message is sent.
+ *
+ * Calculates the average time and connection packet tracking.
+ *
+ * @param cls Closure (TunnelQueue handle).
+ * @param c Connection this message was on.
+ * @param q Connection queue handle (unused).
+ * @param type Type of message sent.
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ */
+static void
+tun_message_sent (void *cls,
+              struct CadetConnection *c,
+              struct CadetConnectionQueue *q,
+              uint16_t type, int fwd, size_t size)
+{
+  struct CadetTunnel3Queue *qt = cls;
+  struct CadetTunnel3 *t;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n");
+
+  GNUNET_assert (NULL != qt->cont);
+  t = NULL == c ? NULL : GMC_get_tunnel (c);
+  qt->cont (qt->cont_cls, t, qt, type, size);
+  GNUNET_free (qt);
+}
+
+
+/**
+ * Delete a queued message: either was sent or the channel was destroyed
+ * before the tunnel's key exchange had a chance to finish.
+ *
+ * @param tqd Delayed queue handle.
+ */
+static void
+unqueue_data (struct CadetTunnelDelayed *tqd)
+{
+  GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd);
+  GNUNET_free (tqd);
+}
+
+
+/**
+ * Cache a message to be sent once tunnel is online.
+ *
+ * @param t Tunnel to hold the message.
+ * @param msg Message itself (copy will be made).
+ */
+static struct CadetTunnelDelayed *
+queue_data (struct CadetTunnel3 *t, const struct GNUNET_MessageHeader *msg)
+{
+  struct CadetTunnelDelayed *tqd;
+  uint16_t size = ntohs (msg->size);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t));
+
+  if (GNUNET_YES == is_ready (t))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  tqd = GNUNET_malloc (sizeof (struct CadetTunnelDelayed) + size);
+
+  tqd->t = t;
+  memcpy (&tqd[1], msg, size);
+  GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd);
+  return tqd;
+}
+
+
+/**
+ * Calculate HMAC.
+ *
+ * @param t Tunnel to get keys from.
+ * @param plaintext Content to HMAC.
+ * @param size Size of @c plaintext.
+ * @param iv Initialization vector for the message.
+ * @param outgoing Is this an outgoing message that we encrypted?
+ * @param hmac Destination to store the HMAC.
+ */
+static void
+t_hmac (struct CadetTunnel3 *t, const void *plaintext, size_t size, uint32_t 
iv,
+        int outgoing, struct GNUNET_CADET_Hash *hmac)
+{
+  struct GNUNET_CRYPTO_AuthKey auth_key;
+  static const char ctx[] = "cadet authentication key";
+  struct GNUNET_CRYPTO_SymmetricSessionKey *key;
+  struct GNUNET_HashCode hash;
+
+  key = outgoing ? &t->e_key : &t->d_key;
+  GNUNET_CRYPTO_hmac_derive_key (&auth_key, key,
+                                 &iv, sizeof (iv),
+                                 key, sizeof (*key),
+                                 ctx, sizeof (ctx),
+                                 NULL);
+  GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash);
+  memcpy (hmac, &hash, sizeof (*hmac));
+}
+
+
+/**
+ * Sends an already built message on a tunnel, encrypting it and
+ * choosing the best connection.
+ *
+ * @param message Message to send. Function modifies it.
+ * @param t Tunnel on which this message is transmitted.
+ * @param c Connection to use (autoselect if NULL).
+ * @param force Force the tunnel to take the message (buffer overfill).
+ * @param cont Continuation to call once message is really sent.
+ * @param cont_cls Closure for @c cont.
+ * @param existing_q In case this a transmission of previously queued data,
+ *                   this should be TunnelQueue given to the client.
+ *                   Otherwise, NULL.
+ *
+ * @return Handle to cancel message. NULL if @c cont is NULL.
+ */
+static struct CadetTunnel3Queue *
+send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                       struct CadetTunnel3 *t, struct CadetConnection *c,
+                       int force, GMT_sent cont, void *cont_cls,
+                       struct CadetTunnel3Queue *existing_q)
+{
+  struct CadetTunnel3Queue *tq;
+  struct GNUNET_CADET_Encrypted *msg;
+  size_t size = ntohs (message->size);
+  char cbuf[sizeof (struct GNUNET_CADET_Encrypted) + size];
+  uint32_t mid;
+  uint32_t iv;
+  uint16_t type;
+  int fwd;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t));
+
+  if (GNUNET_NO == is_ready (t))
+  {
+    struct CadetTunnelDelayed *tqd;
+    /* A non null existing_q indicates sending of queued data.
+     * Should only happen after tunnel becomes ready.
+     */
+    GNUNET_assert (NULL == existing_q);
+    tqd = queue_data (t, message);
+    if (NULL == cont)
+      return NULL;
+    tq = GNUNET_new (struct CadetTunnel3Queue);
+    tq->tqd = tqd;
+    tqd->tq = tq;
+    tq->cont = cont;
+    tq->cont_cls = cont_cls;
+    return tq;
+  }
+
+  GNUNET_assert (GNUNET_NO == GMT_is_loopback (t));
+
+  iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+  msg = (struct GNUNET_CADET_Encrypted *) cbuf;
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED);
+  msg->iv = iv;
+  GNUNET_assert (t_encrypt (t, &msg[1], message, size, iv) == size);
+  t_hmac (t, &msg[1], size, iv, GNUNET_YES, &msg->hmac);
+  msg->header.size = htons (sizeof (struct GNUNET_CADET_Encrypted) + size);
+
+  if (NULL == c)
+    c = tunnel_get_connection (t);
+  if (NULL == c)
+  {
+    if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task
+        || CADET_TUNNEL3_SEARCHING != t->cstate)
+    {
+      GNUNET_break (0);
+      GMT_debug (t);
+    }
+    return NULL;
+  }
+
+  mid = 0;
+  type = ntohs (message->type);
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+      if (GNUNET_MESSAGE_TYPE_CADET_DATA == type)
+        mid = ntohl (((struct GNUNET_CADET_Data *) message)->mid);
+      else
+        mid = ntohl (((struct GNUNET_CADET_DataACK *) message)->mid);
+      /* Fall thru */
+    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+      msg->cid = *GMC_get_id (c);
+      msg->ttl = htonl (default_ttl);
+      break;
+    default:
+      GNUNET_break (0);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s\n", GM_m2s (type));
+
+  fwd = GMC_is_origin (c, GNUNET_YES);
+
+  if (NULL == cont)
+  {
+    GNUNET_break (NULL ==
+                  GMC_send_prebuilt_message (&msg->header, type, mid,
+                                             c, fwd, force, NULL, NULL));
+    return NULL;
+  }
+  if (NULL == existing_q)
+  {
+    tq = GNUNET_new (struct CadetTunnel3Queue); /* FIXME valgrind: leak*/
+  }
+  else
+  {
+    tq = existing_q;
+    tq->tqd = NULL;
+  }
+  tq->cq = GMC_send_prebuilt_message (&msg->header, type, mid, c, fwd, force,
+                                      &tun_message_sent, tq);
+  tq->cont = cont;
+  tq->cont_cls = cont_cls;
+
+  return tq;
+}
+
+
+/**
+ * Send all cached messages that we can, tunnel is online.
+ *
+ * @param t Tunnel that holds the messages. Cannot be loopback.
+ */
+static void
+send_queued_data (struct CadetTunnel3 *t)
+{
+  struct CadetTunnelDelayed *tqd;
+  struct CadetTunnelDelayed *next;
+  unsigned int room;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "GMT_send_queued_data on tunnel %s\n",
+       GMT_2s (t));
+
+  if (GMT_is_loopback (t))
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  if (GNUNET_NO == is_ready (t))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  not ready yet: %s/%s\n",
+         estate2s (t->estate), cstate2s (t->cstate));
+    return;
+  }
+
+  room = GMT_get_connections_buffer (t);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer space: %u\n", room);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  tq head: %p\n", t->tq_head);
+  for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n");
+    next = tqd->next;
+    room--;
+    send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1],
+                           tqd->t, NULL, GNUNET_YES,
+                           NULL != tqd->tq ? tqd->tq->cont : NULL,
+                           NULL != tqd->tq ? tqd->tq->cont_cls : NULL,
+                           tqd->tq);
+    unqueue_data (tqd);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data end\n", GMP_2s 
(t->peer));
+}
+
+
+/**
+ * Sends key exchange message on a tunnel, choosing the best connection.
+ * Should not be called on loopback tunnels.
+ *
+ * @param t Tunnel on which this message is transmitted.
+ * @param message Message to send. Function modifies it.
+ */
+static void
+send_kx (struct CadetTunnel3 *t,
+         const struct GNUNET_MessageHeader *message)
+{
+  struct CadetConnection *c;
+  struct GNUNET_CADET_KX *msg;
+  size_t size = ntohs (message->size);
+  char cbuf[sizeof (struct GNUNET_CADET_KX) + size];
+  uint16_t type;
+  int fwd;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT KX on Tunnel %s\n", GMT_2s (t));
+
+  /* Avoid loopback. */
+  if (GMT_is_loopback (t))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  loopback!\n");
+    GNUNET_break (0);
+    return;
+  }
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  being destroyed, why bother\n");
+    return;
+  }
+
+  /* Must have a connection. */
+  if (NULL == t->connection_head)
+  {
+    GNUNET_break (CADET_TUNNEL3_SEARCHING == t->cstate);
+    GMT_debug (t);
+    return;
+  }
+
+  msg = (struct GNUNET_CADET_KX *) cbuf;
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX);
+  msg->header.size = htons (sizeof (struct GNUNET_CADET_KX) + size);
+  c = tunnel_get_connection (t);
+  if (NULL == c)
+  {
+    GNUNET_break (GNUNET_SCHEDULER_NO_TASK != t->destroy_task
+                  || CADET_TUNNEL3_READY != t->cstate);
+    GMT_debug (t);
+    return;
+  }
+  type = ntohs (message->type);
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL:
+    case GNUNET_MESSAGE_TYPE_CADET_KX_PING:
+    case GNUNET_MESSAGE_TYPE_CADET_KX_PONG:
+      memcpy (&msg[1], message, size);
+      break;
+    default:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
+           GM_m2s (type));
+      GNUNET_break (0);
+  }
+
+  fwd = GMC_is_origin (t->connection_head->c, GNUNET_YES);
+  /* TODO save handle and cancel in case of a unneeded retransmission */
+  GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX,
+                             message->type, c, fwd, GNUNET_YES, NULL, NULL);
+}
+
+
+/**
+ * Send the ephemeral key on a tunnel.
+ *
+ * @param t Tunnel on which to send the key.
+ */
+static void
+send_ephemeral (struct CadetTunnel3 *t)
+{
+  LOG (GNUNET_ERROR_TYPE_INFO, "=> EPHM for %s\n", GMT_2s (t));
+
+  kx_msg.sender_status = htonl (t->estate);
+  send_kx (t, &kx_msg.header);
+}
+
+/**
+ * Send a ping message on a tunnel.
+ *
+ * @param t Tunnel on which to send the ping.
+ */
+static void
+send_ping (struct CadetTunnel3 *t)
+{
+  struct GNUNET_CADET_KX_Ping msg;
+
+  LOG (GNUNET_ERROR_TYPE_INFO, "=> PING for %s\n", GMT_2s (t));
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_PING);
+  msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+  msg.target = *GMP_get_id (t->peer);
+  msg.nonce = t->kx_ctx->challenge;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending %u\n", msg.nonce);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s\n", GNUNET_i2s (&msg.target));
+  t_encrypt (t, &msg.target, &msg.target, ping_encryption_size(), msg.iv);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  e sending %u\n", msg.nonce);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  e towards %s\n", GNUNET_i2s (&msg.target));
+
+  send_kx (t, &msg.header);
+}
+
+
+/**
+ * Send a pong message on a tunnel.
+ *
+ * @param t Tunnel on which to send the pong.
+ * @param challenge Value sent in the ping that we have to send back.
+ */
+static void
+send_pong (struct CadetTunnel3 *t, uint32_t challenge)
+{
+  struct GNUNET_CADET_KX_Pong msg;
+
+  LOG (GNUNET_ERROR_TYPE_INFO, "=> PONG for %s\n", GMT_2s (t));
+  msg.header.size = htons (sizeof (msg));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_PONG);
+  msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+  msg.nonce = challenge;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending %u\n", msg.nonce);
+  t_encrypt (t, &msg.nonce, &msg.nonce, sizeof (msg.nonce), msg.iv);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  e sending %u\n", msg.nonce);
+
+  send_kx (t, &msg.header);
+}
+
+
+/**
+ * Initiate a rekey with the remote peer.
+ *
+ * @param cls Closure (tunnel).
+ * @param tc TaskContext.
+ */
+static void
+rekey_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetTunnel3 *t = cls;
+
+  t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-key Tunnel %s\n", GMT_2s (t));
+  if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    return;
+
+  if (NULL == t->kx_ctx)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  new kx ctx\n");
+    t->kx_ctx = GNUNET_new (struct CadetTunnelKXCtx);
+    t->kx_ctx->challenge =
+        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+    t->kx_ctx->d_key_old = t->d_key;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  new challenge for %s: %u\n",
+         GMT_2s (t), t->kx_ctx->challenge);
+  }
+  send_ephemeral (t);
+  switch (t->estate)
+  {
+    case CADET_TUNNEL3_KEY_UNINITIALIZED:
+      t->estate = CADET_TUNNEL3_KEY_SENT;
+      break;
+    case CADET_TUNNEL3_KEY_SENT:
+      break;
+    case CADET_TUNNEL3_KEY_PING:
+    case CADET_TUNNEL3_KEY_OK:
+      send_ping (t);
+      t->estate = CADET_TUNNEL3_KEY_PING;
+      break;
+    default:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected state %u\n", t->estate);
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  next call in %s\n",
+       GNUNET_STRINGS_relative_time_to_string (REKEY_WAIT, GNUNET_YES));
+  t->rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_WAIT, &rekey_tunnel, t);
+}
+
+
+/**
+ * Out ephemeral key has changed, create new session key on all tunnels.
+ *
+ * @param cls Closure (size of the hashmap).
+ * @param key Current public key.
+ * @param value Value in the hash map (tunnel).
+ *
+ * @return #GNUNET_YES, so we should continue to iterate,
+ */
+static int
+rekey_iterator (void *cls,
+                const struct GNUNET_PeerIdentity *key,
+                void *value)
+{
+  struct CadetTunnel3 *t = value;
+  struct GNUNET_TIME_Relative delay;
+  long n = (long) cls;
+  uint32_t r;
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task)
+    return GNUNET_YES;
+
+  if (GNUNET_YES == GMT_is_loopback (t))
+    return GNUNET_YES;
+
+  r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t) n * 
100);
+  delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, r);
+  t->rekey_task = GNUNET_SCHEDULER_add_delayed (delay, &rekey_tunnel, t);
+
+  return GNUNET_YES;
+}
+
+
+/**
+ * Create a new ephemeral key and key message, schedule next rekeying.
+ *
+ * @param cls Closure (unused).
+ * @param tc TaskContext.
+ */
+static void
+rekey (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TIME_Absolute time;
+  long n;
+
+  rekey_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    return;
+
+  GNUNET_free_non_null (my_ephemeral_key);
+  my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
+
+  time = GNUNET_TIME_absolute_get ();
+  kx_msg.creation_time = GNUNET_TIME_absolute_hton (time);
+  time = GNUNET_TIME_absolute_add (time, rekey_period);
+  time = GNUNET_TIME_absolute_add (time, GNUNET_TIME_UNIT_MINUTES);
+  kx_msg.expiration_time = GNUNET_TIME_absolute_hton (time);
+  GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key, &kx_msg.ephemeral_key);
+
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_eddsa_sign (my_private_key,
+                                           &kx_msg.purpose,
+                                           &kx_msg.signature));
+
+  n = (long) GNUNET_CONTAINER_multipeermap_size (tunnels);
+  GNUNET_CONTAINER_multipeermap_iterate (tunnels, &rekey_iterator, (void *) n);
+
+  rekey_task = GNUNET_SCHEDULER_add_delayed (rekey_period, &rekey, NULL);
+}
+
+
+/**
+ * Called only on shutdown, destroy every tunnel.
+ *
+ * @param cls Closure (unused).
+ * @param key Current public key.
+ * @param value Value in the hash map (tunnel).
+ *
+ * @return #GNUNET_YES, so we should continue to iterate,
+ */
+static int
+destroy_iterator (void *cls,
+                const struct GNUNET_PeerIdentity *key,
+                void *value)
+{
+  struct CadetTunnel3 *t = value;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_shutdown destroying tunnel at %p\n", t);
+  GMT_destroy (t);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Notify remote peer that we don't know a channel he is talking about,
+ * probably CHANNEL_DESTROY was missed.
+ *
+ * @param t Tunnel on which to notify.
+ * @param gid ID of the channel.
+ */
+static void
+send_channel_destroy (struct CadetTunnel3 *t, unsigned int gid)
+{
+  struct GNUNET_CADET_ChannelManage msg;
+
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
+  msg.header.size = htons (sizeof (msg));
+  msg.chid = htonl (gid);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "WARNING destroying unknown channel %u on tunnel %s\n",
+       gid, GMT_2s (t));
+  send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL);
+}
+
+
+/**
+ * Demultiplex data per channel and call appropriate channel handler.
+ *
+ * @param t Tunnel on which the data came.
+ * @param msg Data message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+static void
+handle_data (struct CadetTunnel3 *t,
+             const struct GNUNET_CADET_Data *msg,
+             int fwd)
+{
+  struct CadetChannel *ch;
+  size_t size;
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size <
+      sizeof (struct GNUNET_CADET_Data) +
+      sizeof (struct GNUNET_MessageHeader))
+  {
+    GNUNET_break (0);
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n",
+              GM_m2s (ntohs (msg[1].header.type)));
+
+  /* Check channel */
+  ch = GMT_get_channel (t, ntohl (msg->chid));
+  if (NULL == ch)
+  {
+    GNUNET_STATISTICS_update (stats, "# data on unknown channel",
+                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel 0x%X unknown\n",
+         ntohl (msg->chid));
+    send_channel_destroy (t, ntohl (msg->chid));
+    return;
+  }
+
+  GMCH_handle_data (ch, msg, fwd);
+}
+
+
+/**
+ * Demultiplex data ACKs per channel and update appropriate channel buffer 
info.
+ *
+ * @param t Tunnel on which the DATA ACK came.
+ * @param msg DATA ACK message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+static void
+handle_data_ack (struct CadetTunnel3 *t,
+                 const struct GNUNET_CADET_DataACK *msg,
+                 int fwd)
+{
+  struct CadetChannel *ch;
+  size_t size;
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size != sizeof (struct GNUNET_CADET_DataACK))
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Check channel */
+  ch = GMT_get_channel (t, ntohl (msg->chid));
+  if (NULL == ch)
+  {
+    GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
+                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
+         ntohl (msg->chid));
+    return;
+  }
+
+  GMCH_handle_data_ack (ch, msg, fwd);
+}
+
+
+/**
+ * Handle channel create.
+ *
+ * @param t Tunnel on which the data came.
+ * @param msg Data message.
+ */
+static void
+handle_ch_create (struct CadetTunnel3 *t,
+                  const struct GNUNET_CADET_ChannelCreate *msg)
+{
+  struct CadetChannel *ch;
+  size_t size;
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size != sizeof (struct GNUNET_CADET_ChannelCreate))
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Check channel */
+  ch = GMT_get_channel (t, ntohl (msg->chid));
+  if (NULL != ch && ! GMT_is_loopback (t))
+  {
+    /* Probably a retransmission, safe to ignore */
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "   already exists...\n");
+  }
+  ch = GMCH_handle_create (t, msg);
+  if (NULL != ch)
+    GMT_add_channel (t, ch);
+}
+
+
+
+/**
+ * Handle channel NACK: check correctness and call channel handler for NACKs.
+ *
+ * @param t Tunnel on which the NACK came.
+ * @param msg NACK message.
+ */
+static void
+handle_ch_nack (struct CadetTunnel3 *t,
+                const struct GNUNET_CADET_ChannelManage *msg)
+{
+  struct CadetChannel *ch;
+  size_t size;
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Check channel */
+  ch = GMT_get_channel (t, ntohl (msg->chid));
+  if (NULL == ch)
+  {
+    GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel",
+                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
+         ntohl (msg->chid));
+    return;
+  }
+
+  GMCH_handle_nack (ch);
+}
+
+
+/**
+ * Handle a CHANNEL ACK (SYNACK/ACK).
+ *
+ * @param t Tunnel on which the CHANNEL ACK came.
+ * @param msg CHANNEL ACK message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+static void
+handle_ch_ack (struct CadetTunnel3 *t,
+               const struct GNUNET_CADET_ChannelManage *msg,
+               int fwd)
+{
+  struct CadetChannel *ch;
+  size_t size;
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Check channel */
+  ch = GMT_get_channel (t, ntohl (msg->chid));
+  if (NULL == ch)
+  {
+    GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel",
+                              1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
+         ntohl (msg->chid));
+    return;
+  }
+
+  GMCH_handle_ack (ch, msg, fwd);
+}
+
+
+
+/**
+ * Handle a channel destruction message.
+ *
+ * @param t Tunnel on which the message came.
+ * @param msg Channel destroy message.
+ * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+static void
+handle_ch_destroy (struct CadetTunnel3 *t,
+                   const struct GNUNET_CADET_ChannelManage *msg,
+                   int fwd)
+{
+  struct CadetChannel *ch;
+  size_t size;
+
+  /* Check size */
+  size = ntohs (msg->header.size);
+  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  /* Check channel */
+  ch = GMT_get_channel (t, ntohl (msg->chid));
+  if (NULL == ch)
+  {
+    /* Probably a retransmission, safe to ignore */
+    return;
+  }
+
+  GMCH_handle_destroy (ch, msg, fwd);
+}
+
+
+/**
+ * The peer's ephemeral key has changed: update the symmetrical keys.
+ *
+ * @param t Tunnel this message came on.
+ * @param msg Key eXchange message.
+ */
+static void
+handle_ephemeral (struct CadetTunnel3 *t,
+                  const struct GNUNET_CADET_KX_Ephemeral *msg)
+{
+  struct GNUNET_HashCode km;
+  LOG (GNUNET_ERROR_TYPE_INFO, "<=== EPHM for %s\n", GMT_2s (t));
+
+  if (GNUNET_OK != check_ephemeral (t, msg))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  derive_key_material (&km, &msg->ephemeral_key);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  km is %s\n", GNUNET_h2s (&km));
+  derive_symmertic (&t->e_key, &my_full_id, GMP_get_id (t->peer), &km);
+  derive_symmertic (&t->d_key, GMP_get_id (t->peer), &my_full_id, &km);
+  if (CADET_TUNNEL3_KEY_SENT == t->estate)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  our key was sent, send ping\n");
+    send_ping (t);
+    t->estate = CADET_TUNNEL3_KEY_PING;
+  }
+}
+
+
+/**
+ * Peer wants to check our symmetrical keys by sending an encrypted challenge.
+ * Answer with by retransmitting the challenge with the "opposite" key.
+ *
+ * @param t Tunnel this message came on.
+ * @param msg Key eXchange Ping message.
+ */
+static void
+handle_ping (struct CadetTunnel3 *t,
+             const struct GNUNET_CADET_KX_Ping *msg)
+{
+  struct GNUNET_CADET_KX_Ping res;
+
+  if (ntohs (msg->header.size) != sizeof (res))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_INFO, "<=== PING for %s\n", GMT_2s (t));
+  t_decrypt (t, &res.target, &msg->target, ping_encryption_size (), msg->iv);
+  if (0 != memcmp (&my_full_id, &res.target, sizeof (my_full_id)))
+  {
+    // FIXME: move to debug
+    GNUNET_STATISTICS_update (stats, "# malformed PINGs", 1, GNUNET_NO);
+    LOG (GNUNET_ERROR_TYPE_WARNING, "  malformed PING on %s\n", GMT_2s (t));
+    LOG (GNUNET_ERROR_TYPE_WARNING, "  e got %u\n", msg->nonce);
+    LOG (GNUNET_ERROR_TYPE_WARNING, "  e towards %s\n", GNUNET_i2s 
(&msg->target));
+    LOG (GNUNET_ERROR_TYPE_WARNING, "  got %u\n", res.nonce);
+    LOG (GNUNET_ERROR_TYPE_WARNING, "  towards %s\n", GNUNET_i2s 
(&res.target));
+    return;
+  }
+
+  send_pong (t, res.nonce);
+}
+
+
+/**
+ * Peer has answer to our challenge.
+ * If answer is successful, consider the key exchange finished and clean
+ * up all related state.
+ *
+ * @param t Tunnel this message came on.
+ * @param msg Key eXchange Pong message.
+ */
+static void
+handle_pong (struct CadetTunnel3 *t,
+             const struct GNUNET_CADET_KX_Pong *msg)
+{
+  uint32_t challenge;
+
+  LOG (GNUNET_ERROR_TYPE_INFO, "<=== PONG for %s\n", GMT_2s (t));
+  if (GNUNET_SCHEDULER_NO_TASK == t->rekey_task)
+  {
+    GNUNET_STATISTICS_update (stats, "# duplicate PONG messages", 1, 
GNUNET_NO);
+    return;
+  }
+  t_decrypt (t, &challenge, &msg->nonce, sizeof (uint32_t), msg->iv);
+
+  if (challenge != t->kx_ctx->challenge)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong PONG challenge\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "PONG: %u (e: %u). Expected: %u.\n",
+         challenge, msg->nonce, t->kx_ctx->challenge);
+    GNUNET_break_op (0);
+    return;
+  }
+  GNUNET_SCHEDULER_cancel (t->rekey_task);
+  t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_free (t->kx_ctx);
+  t->kx_ctx = NULL;
+  GMT_change_estate (t, CADET_TUNNEL3_KEY_OK);
+}
+
+
+/**
+ * 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? This only is meaningful in loopback 
channels.
+ *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
+ *            #GNUNET_NO if message is BCK on the respective channel (loopback)
+ *            #GNUNET_SYSERR if message on a one-ended channel (remote)
+ */
+static void
+handle_decrypted (struct CadetTunnel3 *t,
+                  const struct GNUNET_MessageHeader *msgh,
+                  int fwd)
+{
+  uint16_t type;
+
+  type = ntohs (msgh->type);
+  LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s on %s\n", GM_m2s (type), GMT_2s (t));
+
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
+      /* Do nothing, connection aleady got updated. */
+      GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_DATA:
+      /* Don't send hop ACK, wait for client to ACK */
+      handle_data (t, (struct GNUNET_CADET_Data *) msgh, fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
+      handle_data_ack (t, (struct GNUNET_CADET_DataACK *) msgh, fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
+      handle_ch_create (t,
+                        (struct GNUNET_CADET_ChannelCreate *) msgh);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
+      handle_ch_nack (t,
+                      (struct GNUNET_CADET_ChannelManage *) msgh);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
+      handle_ch_ack (t,
+                     (struct GNUNET_CADET_ChannelManage *) msgh,
+                     fwd);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
+      handle_ch_destroy (t,
+                         (struct GNUNET_CADET_ChannelManage *) msgh,
+                         fwd);
+      break;
+
+    default:
+      GNUNET_break_op (0);
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "end-to-end message not known (%u)\n",
+           ntohs (msgh->type));
+      GMT_debug (t);
+  }
+}
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Decrypt and demultiplex by message type. Call appropriate handler
+ * for every message.
+ *
+ * @param t Tunnel this message came on.
+ * @param msg Encrypted message.
+ */
+void
+GMT_handle_encrypted (struct CadetTunnel3 *t,
+                      const struct GNUNET_CADET_Encrypted *msg)
+{
+  size_t size = ntohs (msg->header.size);
+  size_t payload_size = size - sizeof (struct GNUNET_CADET_Encrypted);
+  size_t decrypted_size;
+  char cbuf [payload_size];
+  struct GNUNET_MessageHeader *msgh;
+  unsigned int off;
+  struct GNUNET_CADET_Hash hmac;
+
+  decrypted_size = t_decrypt (t, cbuf, &msg[1], payload_size, msg->iv);
+  t_hmac (t, &msg[1], payload_size, msg->iv, GNUNET_NO, &hmac);
+  if (0 != memcmp (&hmac, &msg->hmac, sizeof (hmac)))
+  {
+    /* checksum failed */
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed checksum validation for a message on tunnel `%s'\n",
+                GMT_2s (t));
+    GNUNET_STATISTICS_update (stats, "# wrong HMAC", 1, GNUNET_NO);
+    return;
+  }
+  off = 0;
+  while (off < decrypted_size)
+  {
+    msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
+    handle_decrypted (t, msgh, GNUNET_SYSERR);
+    off += ntohs (msgh->size);
+  }
+}
+
+
+/**
+ * Demultiplex an encapsulated KX message by message type.
+ *
+ * @param t Tunnel on which the message came.
+ * @param message Payload of KX message.
+ */
+void
+GMT_handle_kx (struct CadetTunnel3 *t,
+               const struct GNUNET_MessageHeader *message)
+{
+  uint16_t type;
+
+  type = ntohs (message->type);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message received\n", type);
+  switch (type)
+  {
+    case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL:
+      handle_ephemeral (t, (struct GNUNET_CADET_KX_Ephemeral *) message);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_KX_PING:
+      handle_ping (t, (struct GNUNET_CADET_KX_Ping *) message);
+      break;
+
+    case GNUNET_MESSAGE_TYPE_CADET_KX_PONG:
+      handle_pong (t, (struct GNUNET_CADET_KX_Pong *) message);
+      break;
+
+    default:
+      GNUNET_break_op (0);
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message not known (%u)\n", type);
+  }
+}
+
+
+/**
+ * Initialize the tunnel subsystem.
+ *
+ * @param c Configuration handle.
+ * @param key ECC private key, to derive all other keys and do crypto.
+ */
+void
+GMT_init (const struct GNUNET_CONFIGURATION_Handle *c,
+          const struct GNUNET_CRYPTO_EddsaPrivateKey *key)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DEFAULT_TTL",
+                                             &default_ttl))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+                               "CADET", "DEFAULT_TTL", "USING DEFAULT");
+    default_ttl = 64;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REKEY_PERIOD",
+                                           &rekey_period))
+  {
+    rekey_period = GNUNET_TIME_UNIT_DAYS;
+  }
+
+  my_private_key = key;
+  kx_msg.header.size = htons (sizeof (kx_msg));
+  kx_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL);
+  kx_msg.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CADET_KX);
+  kx_msg.purpose.size = htonl (ephemeral_purpose_size ());
+  kx_msg.origin_identity = my_full_id;
+  rekey_task = GNUNET_SCHEDULER_add_now (&rekey, NULL);
+
+  tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
+}
+
+
+/**
+ * Shut down the tunnel subsystem.
+ */
+void
+GMT_shutdown (void)
+{
+  if (GNUNET_SCHEDULER_NO_TASK != rekey_task)
+  {
+    GNUNET_SCHEDULER_cancel (rekey_task);
+    rekey_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL);
+  GNUNET_CONTAINER_multipeermap_destroy (tunnels);
+}
+
+
+/**
+ * Create a tunnel.
+ *
+ * @param destination Peer this tunnel is towards.
+ */
+struct CadetTunnel3 *
+GMT_new (struct CadetPeer *destination)
+{
+  struct CadetTunnel3 *t;
+
+  t = GNUNET_new (struct CadetTunnel3);
+  t->next_chid = 0;
+  t->peer = destination;
+
+  if (GNUNET_OK !=
+      GNUNET_CONTAINER_multipeermap_put (tunnels, GMP_get_id (destination), t,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+  {
+    GNUNET_break (0);
+    GNUNET_free (t);
+    return NULL;
+  }
+  return t;
+}
+
+
+/**
+ * Change the tunnel's connection state.
+ *
+ * @param t Tunnel whose connection state to change.
+ * @param cstate New connection state.
+ */
+void
+GMT_change_cstate (struct CadetTunnel3* t, enum CadetTunnel3CState cstate)
+{
+  if (NULL == t)
+    return;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n",
+       GMP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate));
+  if (myid != GMP_get_short_id (t->peer) &&
+      CADET_TUNNEL3_READY != t->cstate &&
+      CADET_TUNNEL3_READY == cstate)
+  {
+    t->cstate = cstate;
+    if (CADET_TUNNEL3_KEY_OK == t->estate)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate triggered send queued data\n");
+      send_queued_data (t);
+    }
+    else if (CADET_TUNNEL3_KEY_UNINITIALIZED == t->estate)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate triggered rekey\n");
+      rekey_tunnel (t, NULL);
+    }
+  }
+  t->cstate = cstate;
+
+  if (CADET_TUNNEL3_READY == cstate
+      && CONNECTIONS_PER_TUNNEL <= GMT_count_connections (t))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate triggered stop dht\n");
+    GMP_stop_search (t->peer);
+  }
+}
+
+/**
+ * Change the tunnel encryption state.
+ *
+ * @param t Tunnel whose encryption state to change.
+ * @param state New encryption state.
+ */
+void
+GMT_change_estate (struct CadetTunnel3* t, enum CadetTunnel3EState state)
+{
+  if (NULL == t)
+    return;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Tunnel %s estate was %s\n",
+       GMP_2s (t->peer), estate2s (t->estate));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Tunnel %s estate is now %s\n",
+       GMP_2s (t->peer), estate2s (state));
+  if (myid != GMP_get_short_id (t->peer) &&
+      CADET_TUNNEL3_KEY_OK != t->estate && CADET_TUNNEL3_KEY_OK == state)
+  {
+    t->estate = state;
+    send_queued_data (t);
+    return;
+  }
+  t->estate = state;
+}
+
+
+/**
+ * @brief Check if tunnel has too many connections, and remove one if 
necessary.
+ *
+ * Currently this means the newest connection, unless it is a direct one.
+ * Implemented as a task to avoid freeing a connection that is in the middle
+ * of being created/processed.
+ *
+ * @param cls Closure (Tunnel to check).
+ * @param tc Task context.
+ */
+static void
+trim_connections (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetTunnel3 *t = cls;
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  if (GMT_count_connections (t) > 2 * CONNECTIONS_PER_TUNNEL)
+  {
+    struct CadetTConnection *iter;
+    struct CadetTConnection *c;
+
+    for (c = iter = t->connection_head; NULL != iter; iter = iter->next)
+    {
+      if ((NULL == c || iter->created.abs_value_us > c->created.abs_value_us)
+          && GNUNET_NO == GMC_is_direct (iter->c))
+      {
+        c = iter;
+      }
+    }
+    if (NULL != c)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Too many connections on tunnel %s\n",
+           GMT_2s (t));
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying connection %s\n",
+           GMC_2s (c->c));
+      GMC_destroy (c->c);
+    }
+    else
+    {
+      GNUNET_break (0);
+    }
+  }
+}
+
+
+/**
+ * Add a connection to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param c Connection.
+ */
+void
+GMT_add_connection (struct CadetTunnel3 *t, struct CadetConnection *c)
+{
+  struct CadetTConnection *aux;
+
+  GNUNET_assert (NULL != c);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "add connection %s\n", GMC_2s (c));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " to tunnel %s\n", GMT_2s (t));
+  for (aux = t->connection_head; aux != NULL; aux = aux->next)
+    if (aux->c == c)
+      return;
+
+  aux = GNUNET_new (struct CadetTConnection);
+  aux->c = c;
+  aux->created = GNUNET_TIME_absolute_get ();
+
+  GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux);
+
+  GNUNET_SCHEDULER_add_now (&trim_connections, t);
+}
+
+
+/**
+ * Mark a path as no longer valid for this tunnel: has been tried and failed.
+ *
+ * @param t Tunnel to update.
+ * @param path Invalid path to remove. Is destroyed after removal.
+ */
+void
+GMT_remove_path (struct CadetTunnel3 *t, struct CadetPeerPath *path)
+{
+  GMP_remove_path (t->peer, path);
+}
+
+
+/**
+ * Remove a connection from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param c Connection.
+ */
+void
+GMT_remove_connection (struct CadetTunnel3 *t,
+                       struct CadetConnection *c)
+{
+  struct CadetTConnection *aux;
+  struct CadetTConnection *next;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n",
+       GMC_2s (c), GMT_2s (t));
+  for (aux = t->connection_head; aux != NULL; aux = next)
+  {
+    next = aux->next;
+    if (aux->c == c)
+    {
+      GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, 
aux);
+      GNUNET_free (aux);
+    }
+  }
+
+  /* Start new connections if needed */
+  if (CONNECTIONS_PER_TUNNEL < GMT_count_connections (t)
+      && GNUNET_SCHEDULER_NO_TASK == t->destroy_task
+      && CADET_TUNNEL3_SHUTDOWN != t->cstate
+      && GNUNET_NO == shutting_down)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  no more connections, getting new ones\n");
+    t->cstate = CADET_TUNNEL3_SEARCHING;
+    GMP_connect (t->peer);
+    return;
+  }
+
+  /* If not marked as ready, no change is needed */
+  if (CADET_TUNNEL3_READY != t->cstate)
+    return;
+
+  /* Check if any connection is ready to maintaing cstate */
+  for (aux = t->connection_head; aux != NULL; aux = aux->next)
+    if (CADET_CONNECTION_READY == GMC_get_state (aux->c))
+      return;
+
+  t->cstate = CADET_TUNNEL3_WAITING;
+}
+
+
+/**
+ * Add a channel to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel.
+ */
+void
+GMT_add_channel (struct CadetTunnel3 *t, struct CadetChannel *ch)
+{
+  struct CadetTChannel *aux;
+
+  GNUNET_assert (NULL != ch);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t);
+
+  for (aux = t->channel_head; aux != NULL; aux = aux->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  already there %p\n", aux->ch);
+    if (aux->ch == ch)
+      return;
+  }
+
+  aux = GNUNET_new (struct CadetTChannel);
+  aux->ch = ch;
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " adding %p to %p\n", aux, t->channel_head);
+  GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, t->channel_tail, aux);
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
+  {
+    GNUNET_SCHEDULER_cancel (t->destroy_task);
+    t->destroy_task = GNUNET_SCHEDULER_NO_TASK;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n");
+  }
+}
+
+
+/**
+ * Remove a channel from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel.
+ */
+void
+GMT_remove_channel (struct CadetTunnel3 *t, struct CadetChannel *ch)
+{
+  struct CadetTChannel *aux;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t);
+  for (aux = t->channel_head; aux != NULL; aux = aux->next)
+  {
+    if (aux->ch == ch)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GMCH_2s (ch));
+      GNUNET_CONTAINER_DLL_remove (t->channel_head, t->channel_tail, aux);
+      GNUNET_free (aux);
+      return;
+    }
+  }
+}
+
+
+/**
+ * Search for a channel by global ID.
+ *
+ * @param t Tunnel containing the channel.
+ * @param chid Public channel number.
+ *
+ * @return channel handler, NULL if doesn't exist
+ */
+struct CadetChannel *
+GMT_get_channel (struct CadetTunnel3 *t, CADET_ChannelNumber chid)
+{
+  struct CadetTChannel *iter;
+
+  if (NULL == t)
+    return NULL;
+
+  for (iter = t->channel_head; NULL != iter; iter = iter->next)
+  {
+    if (GMCH_get_id (iter->ch) == chid)
+      break;
+  }
+
+  return NULL == iter ? NULL : iter->ch;
+}
+
+
+/**
+ * @brief Destroy a tunnel and free all resources.
+ *
+ * Should only be called a while after the tunnel has been marked as destroyed,
+ * in case there is a new channel added to the same peer shortly after marking
+ * the tunnel. This way we avoid a new public key handshake.
+ *
+ * @param cls Closure (tunnel to destroy).
+ * @param tc Task context.
+ */
+static void
+delayed_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct CadetTunnel3 *t = cls;
+  struct CadetTConnection *iter;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "delayed destroying tunnel %p\n", t);
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Not destroying tunnel, due to shutdown. "
+         "Tunnel at %p should have been freed by GMT_shutdown\n", t);
+    return;
+  }
+  t->destroy_task = GNUNET_SCHEDULER_NO_TASK;
+  t->cstate = CADET_TUNNEL3_SHUTDOWN;
+
+  for (iter = t->connection_head; NULL != iter; iter = iter->next)
+  {
+    GMC_send_destroy (iter->c);
+  }
+  GMT_destroy (t);
+}
+
+
+/**
+ * Tunnel is empty: destroy it.
+ *
+ * Notifies all connections about the destruction.
+ *
+ * @param t Tunnel to destroy.
+ */
+void
+GMT_destroy_empty (struct CadetTunnel3 *t)
+{
+  if (GNUNET_YES == shutting_down)
+    return; /* Will be destroyed immediately anyway */
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Tunnel %s is already scheduled for destruction\n",
+         GMT_2s (t));
+    GNUNET_break (0);
+    /* should never happen, tunnel can only become empty once, and the
+     * task identifier should be NO_TASK (cleaned when the tunnel was created
+     * or became un-empty)
+     */
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: destroying scheduled\n",
+       GMT_2s (t));
+
+  t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
+                                                  &delayed_destroy, t);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled destroy of %p as %llX\n",
+       t, t->destroy_task);
+}
+
+
+/**
+ * Destroy tunnel if empty (no more channels).
+ *
+ * @param t Tunnel to destroy if empty.
+ */
+void
+GMT_destroy_if_empty (struct CadetTunnel3 *t)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s destroy if empty\n", GMT_2s (t));
+  if (1 < GMT_count_channels (t))
+    return;
+
+  GMT_destroy_empty (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.
+ */
+void
+GMT_destroy (struct CadetTunnel3 *t)
+{
+  struct CadetTConnection *iter_c;
+  struct CadetTConnection *next_c;
+  struct CadetTChannel *iter_ch;
+  struct CadetTChannel *next_ch;
+
+  if (NULL == t)
+    return;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n", GMP_2s (t->peer));
+
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multipeermap_remove (tunnels,
+                                                      GMP_get_id (t->peer), 
t));
+
+  for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c)
+  {
+    next_c = iter_c->next;
+    GMC_destroy (iter_c->c);
+  }
+  for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch)
+  {
+    next_ch = iter_ch->next;
+    GMCH_destroy (iter_ch->ch);
+    /* Should only happen on shutdown, but it's ok. */
+  }
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "cancelling %llX\n", t->destroy_task);
+    GNUNET_SCHEDULER_cancel (t->destroy_task);
+    t->destroy_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
+  GMP_set_tunnel (t->peer, NULL);
+
+  if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task)
+  {
+    GNUNET_SCHEDULER_cancel (t->rekey_task);
+    t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
+    if (NULL != t->kx_ctx)
+      GNUNET_free (t->kx_ctx);
+    else
+      GNUNET_break (0);
+  }
+
+  GNUNET_free (t);
+}
+
+
+/**
+ * @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.
+ */
+struct CadetConnection *
+GMT_use_path (struct CadetTunnel3 *t, struct CadetPeerPath *p)
+{
+  struct CadetConnection *c;
+  struct GNUNET_CADET_Hash cid;
+  unsigned int own_pos;
+
+  if (NULL == t || NULL == p)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  if (CADET_TUNNEL3_SHUTDOWN == t->cstate)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  for (own_pos = 0; own_pos < p->length; own_pos++)
+  {
+    if (p->peers[own_pos] == myid)
+      break;
+  }
+  if (own_pos >= p->length)
+  {
+    GNUNET_break_op (0);
+    return NULL;
+  }
+
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid));
+  c = GMC_new (&cid, t, p, own_pos);
+  if (NULL == c)
+  {
+    /* Path was flawed */
+    return NULL;
+  }
+  GMT_add_connection (t, c);
+  return c;
+}
+
+
+/**
+ * Count established (ready) connections of a tunnel.
+ *
+ * @param t Tunnel on which to count.
+ *
+ * @return Number of connections.
+ */
+unsigned int
+GMT_count_connections (struct CadetTunnel3 *t)
+{
+  struct CadetTConnection *iter;
+  unsigned int count;
+
+  if (NULL == t)
+    return 0;
+
+  for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
+    if (CADET_CONNECTION_DESTROYED != GMC_get_state (iter->c))
+      count++;
+
+  return count;
+}
+
+/**
+ * Count channels of a tunnel.
+ *
+ * @param t Tunnel on which to count.
+ *
+ * @return Number of channels.
+ */
+unsigned int
+GMT_count_channels (struct CadetTunnel3 *t)
+{
+  struct CadetTChannel *iter;
+  unsigned int count;
+
+  for (count = 0, iter = t->channel_head;
+       NULL != iter;
+       iter = iter->next, count++) /* skip */;
+
+  return count;
+}
+
+
+/**
+ * Get the connectivity state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's connectivity state.
+ */
+enum CadetTunnel3CState
+GMT_get_cstate (struct CadetTunnel3 *t)
+{
+  if (NULL == t)
+  {
+    GNUNET_assert (0);
+    return (enum CadetTunnel3CState) -1;
+  }
+  return t->cstate;
+}
+
+
+/**
+ * Get the encryption state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's encryption state.
+ */
+enum CadetTunnel3EState
+GMT_get_estate (struct CadetTunnel3 *t)
+{
+  if (NULL == t)
+  {
+    GNUNET_assert (0);
+    return (enum CadetTunnel3EState) -1;
+  }
+  return t->estate;
+}
+
+/**
+ * Get the maximum buffer space for a tunnel towards a local client.
+ *
+ * @param t Tunnel.
+ *
+ * @return Biggest buffer space offered by any channel in the tunnel.
+ */
+unsigned int
+GMT_get_channels_buffer (struct CadetTunnel3 *t)
+{
+  struct CadetTChannel *iter;
+  unsigned int buffer;
+  unsigned int ch_buf;
+
+  if (NULL == t->channel_head)
+  {
+    /* Probably getting buffer for a channel create/handshake. */
+    return 64;
+  }
+
+  buffer = 0;
+  for (iter = t->channel_head; NULL != iter; iter = iter->next)
+  {
+    ch_buf = get_channel_buffer (iter);
+    if (ch_buf > buffer)
+      buffer = ch_buf;
+  }
+  return buffer;
+}
+
+
+/**
+ * Get the total buffer space for a tunnel for P2P traffic.
+ *
+ * @param t Tunnel.
+ *
+ * @return Buffer space offered by all connections in the tunnel.
+ */
+unsigned int
+GMT_get_connections_buffer (struct CadetTunnel3 *t)
+{
+  struct CadetTConnection *iter;
+  unsigned int buffer;
+
+  buffer = 0;
+  for (iter = t->connection_head; NULL != iter; iter = iter->next)
+  {
+    if (GMC_get_state (iter->c) != CADET_CONNECTION_READY)
+    {
+      continue;
+    }
+    buffer += get_connection_buffer (iter);
+  }
+
+  return buffer;
+}
+
+
+/**
+ * Get the tunnel's destination.
+ *
+ * @param t Tunnel.
+ *
+ * @return ID of the destination peer.
+ */
+const struct GNUNET_PeerIdentity *
+GMT_get_destination (struct CadetTunnel3 *t)
+{
+  return GMP_get_id (t->peer);
+}
+
+
+/**
+ * Get the tunnel's next free global channel ID.
+ *
+ * @param t Tunnel.
+ *
+ * @return GID of a channel free to use.
+ */
+CADET_ChannelNumber
+GMT_get_next_chid (struct CadetTunnel3 *t)
+{
+  CADET_ChannelNumber chid;
+  CADET_ChannelNumber mask;
+  int result;
+
+  /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
+   * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0
+   * If peer's ID is bigger, start at 0x4... bit 30 = 1
+   */
+  result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GMP_get_id (t->peer));
+  if (0 > result)
+    mask = 0x40000000;
+  else
+    mask = 0x0;
+  t->next_chid |= mask;
+
+  while (NULL != GMT_get_channel (t, t->next_chid))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid);
+    t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+    t->next_chid |= mask;
+  }
+  chid = t->next_chid;
+  t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
+  t->next_chid |= mask;
+
+  return chid;
+}
+
+
+/**
+ * Send ACK on one or more channels due to buffer in connections.
+ *
+ * @param t Channel which has some free buffer space.
+ */
+void
+GMT_unchoke_channels (struct CadetTunnel3 *t)
+{
+  struct CadetTChannel *iter;
+  unsigned int buffer;
+  unsigned int channels = GMT_count_channels (t);
+  unsigned int choked_n;
+  struct CadetChannel *choked[channels];
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head);
+  if (NULL != t->channel_head)
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch);
+
+  /* Get buffer space */
+  buffer = GMT_get_connections_buffer (t);
+  if (0 == buffer)
+  {
+    return;
+  }
+
+  /* Count and remember choked channels */
+  choked_n = 0;
+  for (iter = t->channel_head; NULL != iter; iter = iter->next)
+  {
+    if (GNUNET_NO == get_channel_allowed (iter))
+    {
+      choked[choked_n++] = iter->ch;
+    }
+  }
+
+  /* Unchoke random channels */
+  while (0 < buffer && 0 < choked_n)
+  {
+    unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                               choked_n);
+    GMCH_allow_client (choked[r], GMCH_is_origin (choked[r], GNUNET_YES));
+    choked_n--;
+    buffer--;
+    choked[r] = choked[choked_n];
+  }
+}
+
+
+/**
+ * Send ACK on one or more connections due to buffer space to the client.
+ *
+ * Iterates all connections of the tunnel and sends ACKs appropriately.
+ *
+ * @param t Tunnel.
+ */
+void
+GMT_send_connection_acks (struct CadetTunnel3 *t)
+{
+  struct CadetTConnection *iter;
+  uint32_t allowed;
+  uint32_t to_allow;
+  uint32_t allow_per_connection;
+  unsigned int cs;
+  unsigned int buffer;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n",
+       GMT_2s (t));
+
+  if (NULL == t)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  buffer = GMT_get_channels_buffer (t);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer %u\n", buffer);
+
+  /* Count connections, how many messages are already allowed */
+  cs = GMT_count_connections (t);
+  for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
+  {
+    allowed += get_connection_allowed (iter);
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  allowed %u\n", allowed);
+
+  /* Make sure there is no overflow */
+  if (allowed > buffer)
+  {
+    return;
+  }
+
+  /* Authorize connections to send more data */
+  to_allow = buffer; /* - allowed; */
+
+  for (iter = t->connection_head;
+       NULL != iter && to_allow > 0;
+       iter = iter->next)
+  {
+    allow_per_connection = to_allow/cs;
+    to_allow -= allow_per_connection;
+    cs--;
+    if (get_connection_allowed (iter) > 64 / 3)
+    {
+      continue;
+    }
+    GMC_allow (iter->c, allow_per_connection,
+               GMC_is_origin (iter->c, GNUNET_NO));
+  }
+
+  GNUNET_break (to_allow == 0);
+}
+
+
+/**
+ * Cancel a previously sent message while it's in the queue.
+ *
+ * ONLY can be called before the continuation given to the send function
+ * is called. Once the continuation is called, the message is no longer in the
+ * queue.
+ *
+ * @param q Handle to the queue.
+ */
+void
+GMT_cancel (struct CadetTunnel3Queue *q)
+{
+  if (NULL != q->cq)
+  {
+    GMC_cancel (q->cq);
+    /* tun_message_sent() will be called and free q */
+  }
+  else if (NULL != q->tqd)
+  {
+    unqueue_data (q->tqd);
+    q->tqd = NULL;
+    if (NULL != q->cont)
+      q->cont (q->cont_cls, NULL, q, 0, 0);
+    GNUNET_free (q);
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+}
+
+
+/**
+ * Sends an already built message on a tunnel, encrypting it and
+ * choosing the best connection if not provided.
+ *
+ * @param message Message to send. Function modifies it.
+ * @param t Tunnel on which this message is transmitted.
+ * @param c Connection to use (autoselect if NULL).
+ * @param force Force the tunnel to take the message (buffer overfill).
+ * @param cont Continuation to call once message is really sent.
+ * @param cont_cls Closure for @c cont.
+ *
+ * @return Handle to cancel message. NULL if @c cont is NULL.
+ */
+struct CadetTunnel3Queue *
+GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                           struct CadetTunnel3 *t, struct CadetConnection *c,
+                           int force, GMT_sent cont, void *cont_cls)
+{
+  return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL);
+}
+
+
+/**
+ * Is the tunnel directed towards the local peer?
+ *
+ * @param t Tunnel.
+ *
+ * @return #GNUNET_YES if it is loopback.
+ */
+int
+GMT_is_loopback (const struct CadetTunnel3 *t)
+{
+  return (myid == GMP_get_short_id (t->peer));
+}
+
+
+/**
+ * Is the tunnel this path already?
+ *
+ * @param t Tunnel.
+ * @param p Path.
+ *
+ * @return #GNUNET_YES a connection uses this path.
+ */
+int
+GMT_is_path_used (const struct CadetTunnel3 *t, const struct CadetPeerPath *p)
+{
+  struct CadetTConnection *iter;
+
+  for (iter = t->connection_head; NULL != iter; iter = iter->next)
+    if (GMC_get_path (iter->c) == p)
+      return GNUNET_YES;
+
+  return GNUNET_NO;
+}
+
+
+/**
+ * Get a cost of a path for a tunnel considering existing connections.
+ *
+ * @param t Tunnel.
+ * @param path Candidate path.
+ *
+ * @return Cost of the path (path length + number of overlapping nodes)
+ */
+unsigned int
+GMT_get_path_cost (const struct CadetTunnel3 *t,
+                   const struct CadetPeerPath *path)
+{
+  struct CadetTConnection *iter;
+  const struct CadetPeerPath *aux;
+  unsigned int overlap;
+  unsigned int i;
+  unsigned int j;
+
+  if (NULL == path)
+    return 0;
+
+  overlap = 0;
+  GNUNET_assert (NULL != t);
+
+  for (i = 0; i < path->length; i++)
+  {
+    for (iter = t->connection_head; NULL != iter; iter = iter->next)
+    {
+      aux = GMC_get_path (iter->c);
+      if (NULL == aux)
+        continue;
+
+      for (j = 0; j < aux->length; j++)
+      {
+        if (path->peers[i] == aux->peers[j])
+        {
+          overlap++;
+          break;
+        }
+      }
+    }
+  }
+  return path->length + overlap;
+}
+
+
+/**
+ * Get the static string for the peer this tunnel is directed.
+ *
+ * @param t Tunnel.
+ *
+ * @return Static string the destination peer's ID.
+ */
+const char *
+GMT_2s (const struct CadetTunnel3 *t)
+{
+  if (NULL == t)
+    return "(NULL)";
+
+  return GMP_2s (t->peer);
+}
+
+
+/******************************************************************************/
+/*****************************    INFO/DEBUG    
*******************************/
+/******************************************************************************/
+
+
+/**
+ * Log all possible info about the tunnel state to stderr.
+ *
+ * @param t Tunnel to debug.
+ */
+void
+GMT_debug (const struct CadetTunnel3 *t)
+{
+  struct CadetTChannel *iterch;
+  struct CadetTConnection *iterc;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT DEBUG TUNNEL TOWARDS %s\n", GMT_2s (t));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  cstate %s, estate %s\n",
+       cstate2s (t->cstate), estate2s (t->estate));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  kx_ctx %p, rekey_task %u\n",
+       t->kx_ctx, t->rekey_task);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  tq_head %p, tq_tail %p\n",
+       t->tq_head, t->tq_tail);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  destroy %u\n", t->destroy_task);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  channels:\n");
+  for (iterch = t->channel_head; NULL != iterch; iterch = iterch->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  - %s\n", GMCH_2s (iterch->ch));
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  connections:\n");
+  for (iterc = t->connection_head; NULL != iterc; iterc = iterc->next)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  - %s [%u] buf: %u/%u (qn %u/%u)\n",
+         GMC_2s (iterc->c), GMC_get_state (iterc->c),
+         GMC_get_buffer (iterc->c, GNUNET_YES),
+         GMC_get_buffer (iterc->c, GNUNET_NO),
+         GMC_get_qn (iterc->c, GNUNET_YES),
+         GMC_get_qn (iterc->c, GNUNET_NO));
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT DEBUG TUNNEL END\n");
+}
+
+
+/**
+ * Iterate all tunnels.
+ *
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
+{
+  GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls);
+}
+
+
+/**
+ * Count all tunnels.
+ *
+ * @return Number of tunnels to remote peers kept by this peer.
+ */
+unsigned int
+GMT_count_all (void)
+{
+  return GNUNET_CONTAINER_multipeermap_size (tunnels);
+}
+
+
+/**
+ * Iterate all connections of a tunnel.
+ *
+ * @param t Tunnel whose connections to iterate.
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMT_iterate_connections (struct CadetTunnel3 *t, GMT_conn_iter iter, void *cls)
+{
+  struct CadetTConnection *ct;
+
+  for (ct = t->connection_head; NULL != ct; ct = ct->next)
+    iter (cls, ct->c);
+}
+
+
+/**
+ * Iterate all channels of a tunnel.
+ *
+ * @param t Tunnel whose channels to iterate.
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMT_iterate_channels (struct CadetTunnel3 *t, GMT_chan_iter iter, void *cls)
+{
+  struct CadetTChannel *cht;
+
+  for (cht = t->channel_head; NULL != cht; cht = cht->next)
+    iter (cls, cht->ch);
+}

Copied: gnunet/src/cadet/gnunet-service-cadet_tunnel.h (from rev 33185, 
gnunet/src/mesh/gnunet-service-cadet_tunnel.h)
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_tunnel.h                              
(rev 0)
+++ gnunet/src/cadet/gnunet-service-cadet_tunnel.h      2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -0,0 +1,531 @@
+/*
+     This file is part of GNUnet.
+     (C) 2013 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/gnunet-service-cadet_tunnel.h
+ * @brief cadet service; dealing with tunnels and crypto
+ * @author Bartlomiej Polot
+ *
+ * All functions in this file should use the prefix GMT (Gnunet Cadet Tunnel)
+ */
+
+#ifndef GNUNET_SERVICE_CADET_TUNNEL_H
+#define GNUNET_SERVICE_CADET_TUNNEL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+/**
+ * All the connectivity states a tunnel can be in.
+ */
+enum CadetTunnel3CState
+{
+    /**
+     * Uninitialized status, should never appear in operation.
+     */
+  CADET_TUNNEL3_NEW,
+
+    /**
+     * Path to the peer not known yet.
+     */
+  CADET_TUNNEL3_SEARCHING,
+
+    /**
+     * Request sent, not yet answered.
+     */
+  CADET_TUNNEL3_WAITING,
+
+    /**
+     * Peer connected and ready to accept data.
+     */
+  CADET_TUNNEL3_READY,
+
+  /**
+   * Tunnel being shut down, don't try to keep it alive.
+   */
+  CADET_TUNNEL3_SHUTDOWN
+};
+
+
+/**
+ * All the encryption states a tunnel can be in.
+ */
+enum CadetTunnel3EState
+{
+  /**
+   * Uninitialized status, should never appear in operation.
+   */
+  CADET_TUNNEL3_KEY_UNINITIALIZED,
+
+  /**
+   * Ephemeral key sent, waiting for peer's key.
+   */
+  CADET_TUNNEL3_KEY_SENT,
+
+  /**
+   * New ephemeral key and ping sent, waiting for pong.
+   * This means that we DO have the peer's ephemeral key, otherwise the
+   * state would be KEY_SENT.
+   */
+  CADET_TUNNEL3_KEY_PING,
+
+  /**
+   * Handshake completed: session key available.
+   */
+  CADET_TUNNEL3_KEY_OK,
+};
+
+/**
+ * Struct containing all information regarding a given peer
+ */
+struct CadetTunnel3;
+
+
+#include "gnunet-service-cadet_channel.h"
+#include "gnunet-service-cadet_connection.h"
+#include "gnunet-service-cadet_peer.h"
+
+/**
+ * Handle for messages queued but not yet sent.
+ */
+struct CadetTunnel3Queue;
+
+/**
+ * Callback called when a queued message is sent.
+ *
+ * @param cls Closure.
+ * @param t Tunnel this message was on.
+ * @param type Type of message sent.
+ * @param size Size of the message.
+ */
+typedef void (*GMT_sent) (void *cls,
+                          struct CadetTunnel3 *t,
+                          struct CadetTunnel3Queue *q,
+                          uint16_t type, size_t size);
+
+typedef void (*GMT_conn_iter) (void *cls, struct CadetConnection *c);
+typedef void (*GMT_chan_iter) (void *cls, struct CadetChannel *ch);
+
+
+/******************************************************************************/
+/********************************    API    
***********************************/
+/******************************************************************************/
+
+/**
+ * Initialize tunnel subsystem.
+ *
+ * @param c Configuration handle.
+ * @param key ECC private key, to derive all other keys and do crypto.
+ */
+void
+GMT_init (const struct GNUNET_CONFIGURATION_Handle *c,
+          const struct GNUNET_CRYPTO_EddsaPrivateKey *key);
+
+/**
+ * Shut down the tunnel subsystem.
+ */
+void
+GMT_shutdown (void);
+
+/**
+ * Create a tunnel.
+ *
+ * @param destination Peer this tunnel is towards.
+ */
+struct CadetTunnel3 *
+GMT_new (struct CadetPeer *destination);
+
+/**
+ * Tunnel is empty: destroy it.
+ *
+ * Notifies all connections about the destruction.
+ *
+ * @param t Tunnel to destroy.
+ */
+void
+GMT_destroy_empty (struct CadetTunnel3 *t);
+
+/**
+ * Destroy tunnel if empty (no more channels).
+ *
+ * @param t Tunnel to destroy if empty.
+ */
+void
+GMT_destroy_if_empty (struct CadetTunnel3 *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.
+ */
+void
+GMT_destroy (struct CadetTunnel3 *t);
+
+
+/**
+ * Change the tunnel's connection state.
+ *
+ * @param t Tunnel whose connection state to change.
+ * @param cstate New connection state.
+ */
+void
+GMT_change_cstate (struct CadetTunnel3* t, enum CadetTunnel3CState cstate);
+
+
+/**
+ * Change the tunnel encryption state.
+ *
+ * @param t Tunnel whose encryption state to change.
+ * @param state New encryption state.
+ */
+void
+GMT_change_estate (struct CadetTunnel3* t, enum CadetTunnel3EState state);
+
+/**
+ * Add a connection to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param c Connection.
+ */
+void
+GMT_add_connection (struct CadetTunnel3 *t, struct CadetConnection *c);
+
+/**
+ * Mark a path as no longer valid for this tunnel: has been tried and failed.
+ *
+ * @param t Tunnel to update.
+ * @param path Invalid path to remove. Is destroyed after removal.
+ */
+void
+GMT_remove_path (struct CadetTunnel3 *t, struct CadetPeerPath *path);
+
+/**
+ * Remove a connection from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param c Connection.
+ */
+void
+GMT_remove_connection (struct CadetTunnel3 *t, struct CadetConnection *c);
+
+/**
+ * Add a channel to a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel.
+ */
+void
+GMT_add_channel (struct CadetTunnel3 *t, struct CadetChannel *ch);
+
+/**
+ * Remove a channel from a tunnel.
+ *
+ * @param t Tunnel.
+ * @param ch Channel.
+ */
+void
+GMT_remove_channel (struct CadetTunnel3 *t, struct CadetChannel *ch);
+
+/**
+ * Search for a channel by global ID.
+ *
+ * @param t Tunnel containing the channel.
+ * @param chid Public channel number.
+ *
+ * @return channel handler, NULL if doesn't exist
+ */
+struct CadetChannel *
+GMT_get_channel (struct CadetTunnel3 *t, CADET_ChannelNumber chid);
+
+/**
+ * Decrypt and demultiplex by message type. Call appropriate handler
+ * for a message
+ * towards a channel of a local tunnel.
+ *
+ * @param t Tunnel this message came on.
+ * @param msg Message header.
+ */
+void
+GMT_handle_encrypted (struct CadetTunnel3 *t,
+                      const struct GNUNET_CADET_Encrypted *msg);
+
+/**
+ * Demultiplex an encapsulated KX message by message type.
+ *
+ * @param t Tunnel on which the message came.
+ * @param message KX message itself.
+ */
+void
+GMT_handle_kx (struct CadetTunnel3 *t,
+               const struct GNUNET_MessageHeader *message);
+
+/**
+ * @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.
+ */
+struct CadetConnection *
+GMT_use_path (struct CadetTunnel3 *t, struct CadetPeerPath *p);
+
+/**
+ * Count established (ready) connections of a tunnel.
+ *
+ * @param t Tunnel on which to count.
+ *
+ * @return Number of connections.
+ */
+unsigned int
+GMT_count_connections (struct CadetTunnel3 *t);
+
+/**
+ * Count channels of a tunnel.
+ *
+ * @param t Tunnel on which to count.
+ *
+ * @return Number of channels.
+ */
+unsigned int
+GMT_count_channels (struct CadetTunnel3 *t);
+
+/**
+ * Get the connectivity state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's connectivity state.
+ */
+enum CadetTunnel3CState
+GMT_get_cstate (struct CadetTunnel3 *t);
+
+/**
+ * Get the encryption state of a tunnel.
+ *
+ * @param t Tunnel.
+ *
+ * @return Tunnel's encryption state.
+ */
+enum CadetTunnel3EState
+GMT_get_estate (struct CadetTunnel3 *t);
+
+/**
+ * Get the maximum buffer space for a tunnel towards a local client.
+ *
+ * @param t Tunnel.
+ *
+ * @return Biggest buffer space offered by any channel in the tunnel.
+ */
+unsigned int
+GMT_get_channels_buffer (struct CadetTunnel3 *t);
+
+/**
+ * Get the total buffer space for a tunnel for P2P traffic.
+ *
+ * @param t Tunnel.
+ *
+ * @return Buffer space offered by all connections in the tunnel.
+ */
+unsigned int
+GMT_get_connections_buffer (struct CadetTunnel3 *t);
+
+/**
+ * Get the tunnel's destination.
+ *
+ * @param t Tunnel.
+ *
+ * @return ID of the destination peer.
+ */
+const struct GNUNET_PeerIdentity *
+GMT_get_destination (struct CadetTunnel3 *t);
+
+/**
+ * Get the tunnel's next free Channel ID.
+ *
+ * @param t Tunnel.
+ *
+ * @return ID of a channel free to use.
+ */
+CADET_ChannelNumber
+GMT_get_next_chid (struct CadetTunnel3 *t);
+
+/**
+ * Send ACK on one or more channels due to buffer in connections.
+ *
+ * @param t Channel which has some free buffer space.
+ */
+void
+GMT_unchoke_channels (struct CadetTunnel3 *t);
+
+/**
+ * Send ACK on one or more connections due to buffer space to the client.
+ *
+ * Iterates all connections of the tunnel and sends ACKs appropriately.
+ *
+ * @param t Tunnel which has some free buffer space.
+ */
+void
+GMT_send_connection_acks (struct CadetTunnel3 *t);
+
+/**
+ * Cancel a previously sent message while it's in the queue.
+ *
+ * ONLY can be called before the continuation given to the send function
+ * is called. Once the continuation is called, the message is no longer in the
+ * queue.
+ *
+ * @param q Handle to the queue.
+ */
+void
+GMT_cancel (struct CadetTunnel3Queue *q);
+
+/**
+ * Sends an already built message on a tunnel, encrypting it and
+ * choosing the best connection.
+ *
+ * @param message Message to send. Function modifies it.
+ * @param t Tunnel on which this message is transmitted.
+ * @param c Connection to use (autoselect if NULL).
+ * @param force Force the tunnel to take the message (buffer overfill).
+ * @param cont Continuation to call once message is really sent.
+ * @param cont_cls Closure for @c cont.
+ *
+ * @return Handle to cancel message. NULL if @c cont is NULL.
+ */
+struct CadetTunnel3Queue *
+GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
+                           struct CadetTunnel3 *t, struct CadetConnection *c,
+                           int force, GMT_sent cont, void *cont_cls);
+
+/**
+ * Is the tunnel directed towards the local peer?
+ *
+ * @param t Tunnel.
+ *
+ * @return #GNUNET_YES if it is loopback.
+ */
+int
+GMT_is_loopback (const struct CadetTunnel3 *t);
+
+/**
+ * Is the tunnel using this path already?
+ *
+ * @param t Tunnel.
+ * @param p Path.
+ *
+ * @return #GNUNET_YES a connection uses this path.
+ */
+int
+GMT_is_path_used (const struct CadetTunnel3 *t, const struct CadetPeerPath *p);
+
+/**
+ * Get a cost of a path for a tunnel considering existing connections.
+ *
+ * @param t Tunnel.
+ * @param path Candidate path.
+ *
+ * @return Cost of the path (path length + number of overlapping nodes)
+ */
+unsigned int
+GMT_get_path_cost (const struct CadetTunnel3 *t,
+                   const struct CadetPeerPath *path);
+
+/**
+ * Get the static string for the peer this tunnel is directed.
+ *
+ * @param t Tunnel.
+ *
+ * @return Static string the destination peer's ID.
+ */
+const char *
+GMT_2s (const struct CadetTunnel3 *t);
+
+/**
+ * Log all possible info about the tunnel state.
+ *
+ * @param t Tunnel to debug.
+ */
+void
+GMT_debug (const struct CadetTunnel3 *t);
+
+/**
+ * Iterate all tunnels.
+ *
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
+
+/**
+ * Count all tunnels.
+ *
+ * @return Number of tunnels to remote peers kept by this peer.
+ */
+unsigned int
+GMT_count_all (void);
+
+/**
+ * Iterate all connections of a tunnel.
+ *
+ * @param t Tunnel whose connections to iterate.
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMT_iterate_connections (struct CadetTunnel3 *t, GMT_conn_iter iter, void 
*cls);
+
+/**
+ * Iterate all channels of a tunnel.
+ *
+ * @param t Tunnel whose channels to iterate.
+ * @param iter Iterator.
+ * @param cls Closure for @c iter.
+ */
+void
+GMT_iterate_channels (struct CadetTunnel3 *t, GMT_chan_iter iter, void *cls);
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_CADET_SERVICE_TUNNEL_H */
+#endif
+/* end of gnunet-cadet-service_tunnel.h */

Copied: gnunet/src/cadet/loopcheck.sh (from rev 33185, 
gnunet/src/mesh/loopcheck.sh)
===================================================================
--- gnunet/src/cadet/loopcheck.sh                               (rev 0)
+++ gnunet/src/cadet/loopcheck.sh       2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+while true; do
+    date;
+    taskset 1 make check || break;
+    grep -B 10 Assert *log && break
+    ls core* &> /dev/null && break
+done

Copied: gnunet/src/cadet/mesh.conf.in (from rev 33185, 
gnunet/src/mesh/mesh.conf.in)
===================================================================
--- gnunet/src/cadet/mesh.conf.in                               (rev 0)
+++ gnunet/src/cadet/mesh.conf.in       2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,21 @@
+[mesh]
+AUTOSTART = @AUTOSTART@
address@hidden@PORT = 2096
+HOSTNAME = localhost
+BINARY = gnunet-service-mesh
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-mesh.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+REFRESH_CONNECTION_TIME = 5 min
+ID_ANNOUNCE_TIME = 1 h
+APP_ANNOUNCE_TIME = 1 h
+CONNECT_TIMEOUT = 30 s
+DEFAULT_TTL = 64
+DHT_REPLICATION_LEVEL = 3
+MAX_TUNNELS = 1000
+# MAX_TUNNELS deprecated
+MAX_CONNECTIONS = 1000
+MAX_MSGS_QUEUE = 10000
+MAX_PEERS = 1000

Copied: gnunet/src/cadet/profiler.conf (from rev 33185, 
gnunet/src/mesh/profiler.conf)
===================================================================
--- gnunet/src/cadet/profiler.conf                              (rev 0)
+++ gnunet/src/cadet/profiler.conf      2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,19 @@
address@hidden@ test_mesh.conf
+
+[testbed]
+OVERLAY_TOPOLOGY = RANDOM
+OVERLAY_RANDOM_LINKS = %LINKS%
+MAX_PARALLEL_SERVICE_CONNECTIONS=4000
+SETUP_TIMEOUT = 60 m
+
+[transport]
+#MANIPULATE_DELAY_IN = 50 ms
+MANIPULATE_DELAY_OUT = 10 ms
+
+[mesh]
+REFRESH_CONNECTION_TIME = 1 h
+DISABLE_TRY_CONNECT = YES
+ID_ANNOUNCE_TIME = 240 s
+
+[dht]
+FORCE_NSE = %NSE%

Copied: gnunet/src/cadet/run_profiler.sh (from rev 33185, 
gnunet/src/mesh/run_profiler.sh)
===================================================================
--- gnunet/src/cadet/run_profiler.sh                            (rev 0)
+++ gnunet/src/cadet/run_profiler.sh    2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+if [ "$#" -lt "3" ]; then
+    echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS";
+    echo "example: $0 30s 16 1";
+    exit 1;
+fi
+
+ROUNDTIME=$1
+PEERS=$2
+PINGS=$3
+
+if [ $PEERS -eq 1 ]; then
+    echo "cannot run 1 peer";
+    exit 1;
+fi
+
+LINKS=`echo "l($PEERS)/l(2) * $PEERS" | bc -l`
+LINKS=`printf "%.0f" $LINKS`
+NSE=`echo "l($PEERS)/l(2)" | bc -l`
+echo "using $PEERS peers, $LINKS links";
+    
+sed -e "s/%LINKS%/$LINKS/;s/%NSE%/$NSE/" profiler.conf > .profiler.conf
+
+./gnunet-mesh-profiler $ROUNDTIME $PEERS $PINGS $4 |& tee log | grep -v DEBUG

Copied: gnunet/src/cadet/small.dat (from rev 33185, gnunet/src/mesh/small.dat)
===================================================================
--- gnunet/src/cadet/small.dat                          (rev 0)
+++ gnunet/src/cadet/small.dat  2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,21 @@
+16
+1:2
+1:9
+2:3
+3:4
+3:11
+4:5
+5:6
+5:13
+6:7
+7:8
+7:15
+8:9
+9:10
+10:11
+11:12
+12:13
+13:14
+14:15
+15:16
+16:1

Copied: gnunet/src/cadet/test_cadet.c (from rev 33185, 
gnunet/src/mesh/test_cadet.c)
===================================================================
--- gnunet/src/cadet/test_cadet.c                               (rev 0)
+++ gnunet/src/cadet/test_cadet.c       2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,953 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file cadet/test_cadet.c
+ *
+ * @brief Test for the cadet service: retransmission of traffic.
+ */
+#include <stdio.h>
+#include "platform.h"
+#include "cadet_test_lib.h"
+#include "gnunet_cadet_service.h"
+#include "gnunet_statistics_service.h"
+#include <gauger.h>
+
+
+/**
+ * How namy messages to send
+ */
+#define TOTAL_PACKETS 100
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * Time to wait for stuff that should be rather fast
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
+
+/**
+ * DIFFERENT TESTS TO RUN
+ */
+#define SETUP 0
+#define FORWARD 1
+#define KEEPALIVE 2
+#define SPEED 3
+#define SPEED_ACK 4
+#define SPEED_REL 8
+#define P2P_SIGNAL 10
+
+/**
+ * Which test are we running?
+ */
+static int test;
+
+/**
+ * String with test name
+ */
+char *test_name;
+
+/**
+ * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
+ */
+static int test_backwards = GNUNET_NO;
+
+/**
+ * How many events have happened
+ */
+static int ok;
+
+/**
+ * Number of events expected to conclude the test successfully.
+ */
+int ok_goal;
+
+/**
+ * Size of each test packet
+ */
+size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
+
+/**
+ * Operation to get peer ids.
+ */
+struct GNUNET_TESTBED_Operation *t_op[2];
+
+/**
+ * Peer ids.
+ */
+struct GNUNET_PeerIdentity *p_id[2];
+
+/**
+ * Peer ids counter.
+ */
+unsigned int p_ids;
+
+/**
+ * Is the setup initialized?
+ */
+static int initialized;
+
+/**
+ * Number of payload packes sent
+ */
+static int data_sent;
+
+/**
+ * Number of payload packets received
+ */
+static int data_received;
+
+/**
+ * Number of payload packed explicitly (app level) acknowledged
+ */
+static int data_ack;
+
+/**
+ * Total number of currently running peers.
+ */
+static unsigned long long peers_running;
+
+/**
+ * Test context (to shut down).
+ */
+struct GNUNET_CADET_TEST_Context *test_ctx;
+
+/**
+ * Task called to disconnect peers.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+/**
+ * Task To perform tests
+ */
+static GNUNET_SCHEDULER_TaskIdentifier test_task;
+
+/**
+ * Task called to shutdown test.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
+
+/**
+ * Cadet handle for the root peer
+ */
+static struct GNUNET_CADET_Handle *h1;
+
+/**
+ * Cadet handle for the first leaf peer
+ */
+static struct GNUNET_CADET_Handle *h2;
+
+/**
+ * Channel handle for the root peer
+ */
+static struct GNUNET_CADET_Channel *ch;
+
+/**
+ * Channel handle for the dest peer
+ */
+static struct GNUNET_CADET_Channel *incoming_ch;
+
+/**
+ * Time we started the data transmission (after channel has been established
+ * and initilized).
+ */
+static struct GNUNET_TIME_Absolute start_time;
+
+/**
+ * Peers handle.
+ */
+static struct GNUNET_TESTBED_Peer **testbed_peers;
+
+/**
+ * Statistics operation handle.
+ */
+static struct GNUNET_TESTBED_Operation *stats_op;
+
+/**
+ * Keepalives sent.
+ */
+static unsigned int ka_sent;
+
+/**
+ * Keepalives received.
+ */
+static unsigned int ka_received;
+
+
+/**
+ * Show the results of the test (banwidth acheived) and log them to GAUGER
+ */
+static void
+show_end_data (void)
+{
+  static struct GNUNET_TIME_Absolute end_time;
+  static struct GNUNET_TIME_Relative total_time;
+
+  end_time = GNUNET_TIME_absolute_get();
+  total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
+  FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
+  FPRINTF (stderr, "Test time %s\n",
+          GNUNET_STRINGS_relative_time_to_string (total_time,
+                                                  GNUNET_YES));
+  FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
+          4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 
4bytes * ms
+  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
+          TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // 
packets * ms
+  GAUGER ("CADET", test_name,
+          TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000),
+          "packets/s");
+}
+
+
+/**
+ * Shut down peergroup, clean up.
+ *
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
+  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
+}
+
+
+/**
+ * Disconnect from cadet services af all peers, call shutdown.
+ *
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+disconnect_cadet_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
+{
+  long line = (long) cls;
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "disconnecting cadet service of peers, called from line %ld\n",
+              line);
+  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  for (i = 0; i < 2; i++)
+  {
+    GNUNET_TESTBED_operation_done (t_op[i]);
+  }
+  if (NULL != ch)
+  {
+    GNUNET_CADET_channel_destroy (ch);
+    ch = NULL;
+  }
+  if (NULL != incoming_ch)
+  {
+    GNUNET_CADET_channel_destroy (incoming_ch);
+    incoming_ch = NULL;
+  }
+  GNUNET_CADET_TEST_cleanup (test_ctx);
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_handle);
+  }
+  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+
+/**
+ * Abort test: schedule disconnect and shutdown immediately
+ *
+ * @param line Line in the code the abort is requested from (__LINE__).
+ */
+static void
+abort_test (long line)
+{
+  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                                (void *) line);
+  }
+}
+
+/**
+ * Transmit ready callback.
+ *
+ * @param cls Closure (message type).
+ * @param size Size of the tranmist buffer.
+ * @param buf Pointer to the beginning of the buffer.
+ *
+ * @return Number of bytes written to buf.
+ */
+static size_t
+tmt_rdy (void *cls, size_t size, void *buf);
+
+
+/**
+ * Task to schedule a new data transmission.
+ *
+ * @param cls Closure (peer #).
+ * @param tc Task Context.
+ */
+static void
+data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_CADET_TransmitHandle *th;
+  struct GNUNET_CADET_Channel *channel;
+
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
+  if (GNUNET_YES == test_backwards)
+  {
+    channel = incoming_ch;
+  }
+  else
+  {
+    channel = ch;
+  }
+  th = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
+                                          GNUNET_TIME_UNIT_FOREVER_REL,
+                                          size_payload, &tmt_rdy, (void *) 1L);
+  if (NULL == th)
+  {
+    unsigned long i = (unsigned long) cls;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
+    if (0 == i)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
+                                    &data_task, (void *)1UL);
+    }
+    else
+    {
+      i++;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
+                                      GNUNET_TIME_UNIT_MILLISECONDS,
+                                      i),
+                                    &data_task, (void *)i);
+    }
+  }
+}
+
+
+/**
+ * Transmit ready callback
+ *
+ * @param cls Closure (message type).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+size_t
+tmt_rdy (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *msg = buf;
+  uint32_t *data;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "tmt_rdy called, filling buffer\n");
+  if (size < size_payload || NULL == buf)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "size %u, buf %p, data_sent %u, data_received %u\n",
+                size, buf, data_sent, data_received);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal);
+    GNUNET_break (ok >= ok_goal - 2);
+
+    return 0;
+  }
+  msg->size = htons (size);
+  msg->type = htons ((long) cls);
+  data = (uint32_t *) &msg[1];
+  *data = htonl (data_sent);
+  if (GNUNET_NO == initialized)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "sending initializer\n");
+  }
+  else if (SPEED == test)
+  {
+    data_sent++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Sent packet %d\n", data_sent);
+    if (data_sent < TOTAL_PACKETS)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " Scheduling packet %d\n", data_sent + 1);
+      GNUNET_SCHEDULER_add_now (&data_task, NULL);
+    }
+  }
+
+  return size_payload;
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
+               void **channel_ctx,
+               const struct GNUNET_MessageHeader *message)
+{
+  long client = (long) cls;
+  long expected_target_client;
+  uint32_t *data;
+
+  ok++;
+
+  GNUNET_CADET_receive_done (channel);
+
+  if ((ok % 20) == 0)
+  {
+    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    {
+      GNUNET_SCHEDULER_cancel (disconnect_task);
+      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                      &disconnect_cadet_peers,
+                                                      (void *) __LINE__);
+    }
+  }
+
+  switch (client)
+  {
+  case 0L:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
+    break;
+  case 4L:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Leaf client %li got a message.\n",
+                client);
+    break;
+  default:
+    GNUNET_assert (0);
+    break;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
+  data = (uint32_t *) &message[1];
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
+  if (SPEED == test && GNUNET_YES == test_backwards)
+  {
+    expected_target_client = 0L;
+  }
+  else
+  {
+    expected_target_client = 4L;
+  }
+
+  if (GNUNET_NO == initialized)
+  {
+    initialized = GNUNET_YES;
+    start_time = GNUNET_TIME_absolute_get ();
+    if (SPEED == test)
+    {
+      GNUNET_assert (4L == client);
+      GNUNET_SCHEDULER_add_now (&data_task, NULL);
+      return GNUNET_OK;
+    }
+  }
+
+  if (client == expected_target_client) // Normally 4
+  {
+    data_received++;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
+    if (SPEED != test || (ok_goal - 2) == ok)
+    {
+      GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         size_payload, &tmt_rdy, (void *) 1L);
+      return GNUNET_OK;
+    }
+    else
+    {
+      if (data_received < TOTAL_PACKETS)
+        return GNUNET_OK;
+    }
+  }
+  else // Normally 0
+  {
+    if (test == SPEED_ACK || test == SPEED)
+    {
+      data_ack++;
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", data_ack);
+      GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         size_payload, &tmt_rdy, (void *) 1L);
+      if (data_ack < TOTAL_PACKETS && SPEED != test)
+        return GNUNET_OK;
+      if (ok == 2 && SPEED == test)
+        return GNUNET_OK;
+      show_end_data();
+    }
+    if (test == P2P_SIGNAL)
+    {
+      GNUNET_CADET_channel_destroy (incoming_ch);
+      incoming_ch = NULL;
+    }
+    else
+    {
+      GNUNET_CADET_channel_destroy (ch);
+      ch = NULL;
+    }
+  }
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                    &disconnect_cadet_peers,
+                                                    (void *) __LINE__);
+  }
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Stats callback. Finish the stats testbed operation and when all stats have
+ * been iterated, shutdown the test.
+ *
+ * @param cls closure
+ * @param op the operation that has been finished
+ * @param emsg error message in case the operation has failed; will be NULL if
+ *          operation has executed successfully.
+ */
+static void
+stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stats_cont for peer %u\n", cls);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " sent: %u, received: %u\n",
+              ka_sent, ka_received);
+  if (ka_sent < 2 || ka_sent > ka_received + 1)
+    ok--;
+  GNUNET_TESTBED_operation_done (stats_op);
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                              (void *) __LINE__);
+
+}
+
+
+/**
+ * Process statistic values.
+ *
+ * @param cls closure
+ * @param peer the peer the statistic belong to
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
+ * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
+ */
+static int
+stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
+                const char *subsystem, const char *name,
+                uint64_t value, int is_persistent)
+{
+  static const char *s_sent = "# keepalives sent";
+  static const char *s_recv = "# keepalives received";
+  uint32_t i;
+
+  i = GNUNET_TESTBED_get_index (peer);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %u - %s [%s]: %llu\n",
+              i, subsystem, name, value);
+  if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i)
+    ka_sent = value;
+
+  if (0 == strncmp(s_recv, name, strlen (s_recv)) && 4 == i)
+    ka_received = value;
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Task check that keepalives were sent and received.
+ *
+ * @param cls Closure (NULL).
+ * @param tc Task Context.
+ */
+static void
+check_keepalives (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "check keepalives\n");
+  GNUNET_CADET_channel_destroy (ch);
+  stats_op = GNUNET_TESTBED_get_statistics (5, testbed_peers,
+                                            "cadet", NULL,
+                                            stats_iterator, stats_cont, NULL);
+}
+
+
+/**
+ * Handlers, for diverse services
+ */
+static struct GNUNET_CADET_MessageHandler handlers[] = {
+  {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * Method called whenever another peer has added us to a channel
+ * the other peer initiated.
+ *
+ * @param cls Closure.
+ * @param channel New handle to the channel.
+ * @param initiator Peer that started the channel.
+ * @param port Port this channel is connected to.
+ * @param options channel option flags
+ * @return Initial channel context for the channel
+ *         (can be NULL -- that's not an error).
+ */
+static void *
+incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel,
+                 const struct GNUNET_PeerIdentity *initiator,
+                 uint32_t port, enum GNUNET_CADET_ChannelOption options)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming channel from %s to peer %d\n",
+              GNUNET_i2s (initiator), (long) cls);
+  ok++;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+  if ((long) cls == 4L)
+    incoming_ch = channel;
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Incoming channel for unknown client %lu\n", (long) cls);
+    GNUNET_break(0);
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    if (KEEPALIVE == test)
+    {
+      struct GNUNET_TIME_Relative delay;
+      delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS , 5);
+      disconnect_task =
+        GNUNET_SCHEDULER_add_delayed (delay, &check_keepalives, NULL);
+    }
+    else
+      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                      &disconnect_cadet_peers,
+                                                      (void *) __LINE__);
+  }
+
+  return NULL;
+}
+
+/**
+ * Function called whenever an inbound channel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect)
+ * @param channel connection to the other end (henceforth invalid)
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ */
+static void
+channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel,
+                 void *channel_ctx)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming channel disconnected at peer %ld\n", i);
+  if (4L == i)
+  {
+    ok++;
+    GNUNET_break (channel == incoming_ch);
+    incoming_ch = NULL;
+  }
+  else if (0L == i)
+  {
+    if (P2P_SIGNAL == test)
+    {
+      ok ++;
+    }
+    GNUNET_break (channel == ch);
+    ch = NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Unknown peer! %d\n", i);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                                (void *) __LINE__);
+  }
+
+  return;
+}
+
+
+/**
+ * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
+ *
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ *
+ * @param cls Closure (unsued).
+ * @param tc Task Context.
+ */
+static void
+do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  enum GNUNET_CADET_ChannelOption flags;
+
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
+
+  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  }
+
+  flags = GNUNET_CADET_OPTION_DEFAULT;
+  if (SPEED_REL == test)
+  {
+    test = SPEED;
+    flags |= GNUNET_CADET_OPTION_RELIABLE;
+  }
+  ch = GNUNET_CADET_channel_create (h1, NULL, p_id[1], 1, flags);
+
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_cadet_peers,
+                                                  (void *) __LINE__);
+  if (KEEPALIVE == test)
+    return; /* Don't send any data. */
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending data initializer...\n");
+  data_ack = 0;
+  data_received = 0;
+  data_sent = 0;
+  GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     size_payload, &tmt_rdy, (void *) 1L);
+}
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed;
+ *             NULL if the operation is successfull
+ */
+static void
+pi_cb (void *cls,
+       struct GNUNET_TESTBED_Operation *op,
+       const struct GNUNET_TESTBED_PeerInformation *pinfo,
+       const char *emsg)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
+
+  if (NULL == pinfo || NULL != emsg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
+    abort_test (__LINE__);
+    return;
+  }
+  p_id[i] = pinfo->result.id;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  id: %s\n", GNUNET_i2s (p_id[i]));
+  p_ids++;
+  if (p_ids < 2)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
+  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                            &do_test, NULL);
+}
+
+/**
+ * test main: start test when all peers are connected
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param peers Array of peers.
+ * @param cadetes Handle to each of the CADETs of the peers.
+ */
+static void
+tmain (void *cls,
+       struct GNUNET_CADET_TEST_Context *ctx,
+       unsigned int num_peers,
+       struct GNUNET_TESTBED_Peer **peers,
+       struct GNUNET_CADET_Handle **cadetes)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
+  ok = 0;
+  test_ctx = ctx;
+  peers_running = num_peers;
+  testbed_peers = peers;
+  h1 = cadetes[0];
+  h2 = cadetes[num_peers - 1];
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_cadet_peers,
+                                                  (void *) __LINE__);
+  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                  &shutdown_task, NULL);
+  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb, (void *) 0L);
+  t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb, (void *) 1L);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
+}
+
+
+/**
+ * Main: start test
+ */
+int
+main (int argc, char *argv[])
+{
+  initialized = GNUNET_NO;
+  static uint32_t ports[2];
+  const char *config_file;
+
+  GNUNET_log_setup ("test", "DEBUG", NULL);
+  config_file = "test_cadet.conf";
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
+  if (strstr (argv[0], "_cadet_forward") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
+    test = FORWARD;
+    test_name = "unicast";
+    ok_goal = 4;
+  }
+  else if (strstr (argv[0], "_cadet_signal") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
+    test = P2P_SIGNAL;
+    test_name = "signal";
+    ok_goal = 4;
+  }
+  else if (strstr (argv[0], "_cadet_speed_ack") != NULL)
+  {
+    /* Test is supposed to generate the following callbacks:
+     * 1 incoming channel (@dest)
+     * TOTAL_PACKETS received data packet (@dest)
+     * TOTAL_PACKETS received data packet (@orig)
+     * 1 received channel destroy (@dest)
+     */
+    ok_goal = TOTAL_PACKETS * 2 + 2;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
+    test = SPEED_ACK;
+    test_name = "speed ack";
+  }
+  else if (strstr (argv[0], "_cadet_speed") != NULL)
+  {
+    /* Test is supposed to generate the following callbacks:
+     * 1 incoming channel (@dest)
+     * 1 initial packet (@dest)
+     * TOTAL_PACKETS received data packet (@dest)
+     * 1 received data packet (@orig)
+     * 1 received channel destroy (@dest)
+     */
+    ok_goal = TOTAL_PACKETS + 4;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
+    if (strstr (argv[0], "_reliable") != NULL)
+    {
+      test = SPEED_REL;
+      test_name = "speed reliable";
+      config_file = "test_cadet_drop.conf";
+    }
+    else
+    {
+      test = SPEED;
+      test_name = "speed";
+    }
+  }
+  else if (strstr (argv[0], "_keepalive") != NULL)
+  {
+    test = KEEPALIVE;
+    /* Test is supposed to generate the following callbacks:
+     * 1 incoming channel (@dest)
+     * [wait]
+     * 1 received channel destroy (@dest)
+     */
+    ok_goal = 2;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
+    test = SETUP;
+    ok_goal = 0;
+  }
+
+  if (strstr (argv[0], "backwards") != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
+    test_backwards = GNUNET_YES;
+    GNUNET_asprintf (&test_name, "backwards %s", test_name);
+  }
+
+  p_ids = 0;
+  ports[0] = 1;
+  ports[1] = 0;
+  GNUNET_CADET_TEST_run ("test_cadet_small",
+                        config_file,
+                        5,
+                        &tmain,
+                        NULL, /* tmain cls */
+                        &incoming_channel,
+                        &channel_cleaner,
+                        handlers,
+                        ports);
+
+  if (ok_goal > ok)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "FAILED! (%d/%d)\n", ok, ok_goal);
+    return 1;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
+  return 0;
+}
+
+/* end of test_cadet.c */
+

Copied: gnunet/src/cadet/test_cadet.conf (from rev 33185, 
gnunet/src/mesh/test_cadet.conf)
===================================================================
--- gnunet/src/cadet/test_cadet.conf                            (rev 0)
+++ gnunet/src/cadet/test_cadet.conf    2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,100 @@
+[testbed]
+AUTOSTART = NO
+PORT = 12113
+ACCEPT_FROM = 127.0.0.1;
+HOSTNAME = localhost
+OVERLAY_TOPOLOGY = LINE
+#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
+
+[fs]
+AUTOSTART = NO
+
+[resolver]
+AUTOSTART = NO
+
+[mesh]
+#BINARY = gnunet-service-mesh-enc
+#PREFIX = valgrind --leak-check=full
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+AUTOSTART = NO
+ACCEPT_FROM = 127.0.0.1;
+REFRESH_CONNECTION_TIME = 2 s
+ID_ANNOUNCE_TIME = 5 s
+CONNECT_TIMEOUT = 30 s
+DEFAULT_TTL = 16
+DHT_REPLICATION_LEVEL = 10
+MAX_TUNNELS = 10
+MAX_CONNECTIONS = 10
+MAX_MSGS_QUEUE = 20
+DISABLE_TRY_CONNECT = YES
+
+[dht]
+AUTOSTART = NO
+DISABLE_TRY_CONNECT = YES
+FORCE_NSE = 3
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = heap
+
+[transport]
+PLUGINS = udp
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+NEIGHBOUR_LIMIT = 50
+PORT = 12365
+#MANIPULATE_DELAY_IN = 10 ms
+#MANIPULATE_DELAY_OUT = 10 ms
+
+
+[ats]
+WAN_QUOTA_OUT = 3932160
+WAN_QUOTA_IN = 3932160
+
+[core]
+PORT = 12092
+AUTOSTART = YES
+USE_EPHEMERAL_KEYS = NO
+
+[arm]
+DEFAULTSERVICES = core transport dht mesh statistics
+PORT = 12366
+
+[transport-udp]
+TIMEOUT = 300 s
+PORT = 12368
+
+[gnunetd]
+HOSTKEY = $GNUNET_TEST_HOME/.hostkey
+
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-mesh/
+
+[dns]
+AUTOSTART = NO
+
+[nse]
+AUTOSTART = NO
+
+[vpn]
+AUTOSTART = NO
+
+[nat]
+RETURN_LOCAL_ADDRESSES = YES
+DISABLEV6 = YES
+USE_LOCALADDR = YES
+
+[gns-helper-service-w32]
+AUTOSTART = NO
+
+[consensus]
+AUTOSTART = NO
+
+[gns]
+AUTOSTART = NO
+
+[statistics]
+AUTOSTART = NO
+
+[peerinfo]
+NO_IO = YES

Copied: gnunet/src/cadet/test_cadet_drop.conf (from rev 33185, 
gnunet/src/mesh/test_cadet_drop.conf)
===================================================================
--- gnunet/src/cadet/test_cadet_drop.conf                               (rev 0)
+++ gnunet/src/cadet/test_cadet_drop.conf       2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,4 @@
address@hidden@ test_mesh.conf
+
+[mesh]
+DROP_PERCENT = 1

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

Copied: gnunet/src/cadet/test_cadet_single.c (from rev 33185, 
gnunet/src/mesh/test_cadet_single.c)
===================================================================
--- gnunet/src/cadet/test_cadet_single.c                                (rev 0)
+++ gnunet/src/cadet/test_cadet_single.c        2014-05-07 12:07:16 UTC (rev 
33186)
@@ -0,0 +1,329 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file cadet/test_cadet_single.c
+ * @brief test cadet single: test of cadet channels with just one client
+ * @author Bartlomiej Polot
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_cadet_service.h"
+
+#define REPETITIONS 5
+#define DATA_SIZE 35000
+
+struct GNUNET_TESTING_Peer *me;
+
+static struct GNUNET_CADET_Handle *cadet;
+
+static struct GNUNET_CADET_Channel *ch1;
+
+static struct GNUNET_CADET_Channel *ch2;
+
+static int result;
+
+static GNUNET_SCHEDULER_TaskIdentifier abort_task;
+
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
+
+static unsigned int repetition;
+
+
+/* forward declaration */
+static size_t
+do_send (void *cls, size_t size, void *buf);
+
+
+/**
+ * Shutdown nicely
+ */
+static void
+do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
+  if (GNUNET_SCHEDULER_NO_TASK != abort_task)
+  {
+    GNUNET_SCHEDULER_cancel (abort_task);
+  }
+  if (NULL != ch1)
+  {
+    GNUNET_CADET_channel_destroy (ch1);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n");
+  if (NULL != cadet)
+  {
+    GNUNET_CADET_disconnect (cadet);
+    cadet = NULL;
+  }
+  else
+  {
+    GNUNET_break (0);
+  }
+}
+
+
+/**
+ * Something went wrong and timed out. Kill everything and set error flag
+ */
+static void
+do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n");
+  result = GNUNET_SYSERR;
+  abort_task = GNUNET_SCHEDULER_NO_TASK;
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_task);
+    shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  do_shutdown (cls, tc);
+}
+
+
+static void
+finish (void)
+{
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
+    GNUNET_SCHEDULER_cancel (shutdown_task);
+  shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                                &do_shutdown, NULL);
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ *
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
+               void **channel_ctx,
+               const struct GNUNET_MessageHeader *message)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Data callback! Repetition %u/%u\n",
+              repetition, REPETITIONS);
+  repetition = repetition + 1;
+  if (repetition < REPETITIONS)
+  {
+    struct GNUNET_CADET_Channel *my_channel;
+    if (repetition % 2 == 0)
+      my_channel = ch1;
+    else
+      my_channel = ch2;
+    GNUNET_CADET_notify_transmit_ready (my_channel, GNUNET_NO,
+                                       GNUNET_TIME_UNIT_FOREVER_REL,
+                                       sizeof (struct GNUNET_MessageHeader)
+                                       + DATA_SIZE,
+                                       &do_send, NULL);
+    GNUNET_CADET_receive_done (channel);
+    return GNUNET_OK;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All data OK. Destroying channel.\n");
+  GNUNET_CADET_channel_destroy (ch1);
+  ch1 = NULL;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Method called whenever another peer has added us to a channel
+ * the other peer initiated.
+ *
+ * @param cls closure
+ * @param channel new handle to the channel
+ * @param initiator peer that started the channel
+ * @param port port number
+ * @param options channel option flags
+ * @return initial channel context for the channel
+ *         (can be NULL -- that's not an error)
+ */
+static void *
+inbound_channel (void *cls, struct GNUNET_CADET_Channel *channel,
+                const struct GNUNET_PeerIdentity *initiator,
+                uint32_t port, enum GNUNET_CADET_ChannelOption options)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "received incoming channel on port %u\n",
+              port);
+  ch2 = channel;
+  return NULL;
+}
+
+
+/**
+ * Function called whenever an inbound channel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect)
+ * @param channel connection to the other end (henceforth invalid)
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ */
+static void
+channel_end (void *cls, const struct GNUNET_CADET_Channel *channel,
+             void *channel_ctx)
+{
+  long id = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "incoming channel closed at peer %ld\n",
+              id);
+  if (REPETITIONS == repetition && channel == ch2)
+  {
+    ch2 = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "everything fine! finishing!\n");
+    result = GNUNET_OK;
+    finish ();
+  }
+}
+
+
+/**
+ * Handler array for traffic received on peer1
+ */
+static struct GNUNET_CADET_MessageHandler handlers1[] = {
+  {&data_callback, 1, 0},
+  {NULL, 0, 0}
+};
+
+
+/**
+ * Data send callback: fillbuffer with test packet.
+ *
+ * @param cls Closure (unused).
+ * @param size Buffer size.
+ * @param buf Buffer to fill.
+ *
+ * @return size of test packet.
+ */
+static size_t
+do_send (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_MessageHeader *m = buf;
+
+  if (NULL == buf)
+  {
+    GNUNET_break (0);
+    result = GNUNET_SYSERR;
+    return 0;
+  }
+  m->size = htons (sizeof (struct GNUNET_MessageHeader));
+  m->type = htons (1);
+  memset (&m[1], 0, DATA_SIZE);
+  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader) + DATA_SIZE);
+  return sizeof (struct GNUNET_MessageHeader) + DATA_SIZE;
+}
+
+/**
+ * Connect to other client and send data
+ *
+ * @param cls Closue (unused).
+ * @param tc TaskContext.
+ */
+static void
+do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_PeerIdentity id;
+  size_t size = sizeof (struct GNUNET_MessageHeader) + DATA_SIZE;
+
+  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
+    return;
+
+  GNUNET_TESTING_peer_get_identity (me, &id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n");
+  ch1 = GNUNET_CADET_channel_create (cadet, NULL, &id, 1,
+                                    GNUNET_CADET_OPTION_DEFAULT);
+  GNUNET_CADET_notify_transmit_ready (ch1, GNUNET_NO,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     size, &do_send, NULL);
+}
+
+
+/**
+ * Initialize framework and start test
+ *
+ * @param cls Closure (unused).
+ * @param cfg Configuration handle.
+ * @param peer Testing peer handle.
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_TESTING_Peer *peer)
+{
+  static uint32_t ports[] = {1, 0};
+
+  me = peer;
+  abort_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort,
+                                    NULL);
+  cadet = GNUNET_CADET_connect (cfg,       /* configuration */
+                              (void *) 1L,     /* cls */
+                              &inbound_channel,   /* inbound new hndlr */
+                              &channel_end,      /* inbound end hndlr */
+                              handlers1, /* traffic handlers */
+                              ports);     /* ports offered */
+
+  if (NULL == cadet)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to cadet :(\n");
+    result = GNUNET_SYSERR;
+    return;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO CADET :D\n");
+  }
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_connect, NULL);
+}
+
+
+/**
+ * Main
+ */
+int
+main (int argc, char *argv[])
+{
+  result = GNUNET_NO;
+  if (0 != GNUNET_TESTING_peer_run ("test-cadet-local",
+                                    "test_cadet.conf",
+                                    &run, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
+    return 2;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result);
+  return (result == GNUNET_OK) ? 0 : 1;
+}
+
+/* end of test_cadet_single.c */

Copied: gnunet/src/cadet/valgrind-mesh.supp (from rev 33185, 
gnunet/src/mesh/valgrind-mesh.supp)
===================================================================
--- gnunet/src/cadet/valgrind-mesh.supp                         (rev 0)
+++ gnunet/src/cadet/valgrind-mesh.supp 2014-05-07 12:07:16 UTC (rev 33186)
@@ -0,0 +1,116 @@
+{
+   logsetup_addr
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:get_type
+   fun:GNUNET_log_setup
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   scanf_addr
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:vsscanf
+   fun:sscanf
+   fun:GNUNET_CONFIGURATION_get_value_number
+   fun:GNUNET_SERVICE_get_server_addresses
+   fun:setup_service
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_addr
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_uninit
+   Memcheck:Value8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:mylog
+   fun:GNUNET_log_from_nocheck
+   fun:service_task
+   ...
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_from_cond
+   Memcheck:Cond
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:mylog
+   fun:GNUNET_log_from_nocheck
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_cond
+   Memcheck:Cond
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:mylog
+   fun:GNUNET_log_nocheck
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   inet_ntop_cond
+   Memcheck:Cond
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:inet_ntop
+   fun:GNUNET_a2s
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   create_key_from_file
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:GNUNET_CRYPTO_rsa_key_create_from_file
+   fun:run
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   main_notify_handler
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:main_notify_handler
+   fun:receive_ready
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
\ No newline at end of file

Deleted: gnunet/src/mesh/Makefile.am
===================================================================
--- gnunet/src/mesh/Makefile.am 2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/Makefile.am 2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,194 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-if MINGW
-  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
-endif
-
-if USE_COVERAGE
-  AM_CFLAGS = --coverage -O0
-  XLIB = -lgcov
-endif
-
-pkgcfgdir= $(pkgdatadir)/config.d/
-
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfg_DATA = \
-  cadet.conf
-
-plugindir = $(libdir)/gnunet
-
-AM_CLFAGS = -g
-
-libexec_PROGRAMS = \
- gnunet-service-cadet $(EXP_LIBEXEC)
-
-bin_PROGRAMS = \
- gnunet-cadet
-
-lib_LTLIBRARIES = \
-  libgnunetcadet.la $(EXP_LIB)
-
-libgnunetcadet_la_SOURCES = \
-  cadet_api.c cadet_common.c
-libgnunetcadet_la_LIBADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(XLIB) \
-  $(LTLIBINTL)
-libgnunetcadet_la_LDFLAGS = \
-  $(GN_LIB_LDFLAGS) $(WINFLAGS) \
-  -version-info 5:0:0
-
-gnunet_cadet_SOURCES = \
-  gnunet-cadet.c
-gnunet_cadet_LDADD = \
-  $(top_builddir)/src/cadet/libgnunetcadet.la \
-  $(top_builddir)/src/util/libgnunetutil.la
-gnunet_cadet_DEPENDENCIES = \
-  libgnunetcadet.la
-
-gnunet_service_cadet_SOURCES = \
- gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \
- gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
- gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \
- gnunet-service-cadet_local.c gnunet-service-cadet_local.h \
- gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \
- gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \
- gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \
- cadet_path.c cadet_path.h \
- cadet_common.c \
- gnunet-service-cadet.c
-gnunet_service_cadet_CFLAGS = $(AM_CFLAGS)
-gnunet_service_cadet_LDADD = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/transport/libgnunettransport.la \
-  $(top_builddir)/src/core/libgnunetcore.la \
-  $(top_builddir)/src/dht/libgnunetdht.la \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/hello/libgnunethello.la \
-  $(top_builddir)/src/block/libgnunetblock.la
-gnunet_service_cadet_DEPENDENCIES = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/transport/libgnunettransport.la \
-  $(top_builddir)/src/core/libgnunetcore.la \
-  $(top_builddir)/src/dht/libgnunetdht.la \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/hello/libgnunethello.la \
-  $(top_builddir)/src/block/libgnunetblock.la
-if LINUX
-  gnunet_service_cadet_LDFLAGS = -lrt
-endif
-
-
-if HAVE_TESTING
- noinst_LIBRARIES = libgnunetcadettest.a $(noinst_LIB_EXP)
- noinst_PROGRAMS = gnunet-cadet-profiler
-endif
-
-libgnunetcadettest_a_SOURCES = \
-  cadet_test_lib.c cadet_test_lib.h
-libgnunetcadettest_a_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testbed/libgnunettestbed.la \
- $(top_builddir)/src/cadet/libgnunetcadet.la
-libgnunetcadettest_a_DEPENDENCIES = \
-  libgnunetcadet.la
-
-if HAVE_TESTING
-check_PROGRAMS = \
-  test_cadet_single \
-  test_cadet_local \
-  test_cadet_forward \
-  test_cadet_signal \
-  test_cadet_keepalive \
-  test_cadet_speed \
-  test_cadet_speed_ack \
-  test_cadet_speed_backwards \
-  test_cadet_speed_reliable \
-  test_cadet_speed_reliable_backwards
-endif
-
-ld_cadet_test_lib = \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
-  $(top_builddir)/src/cadet/libgnunetcadettest.a \
-  $(top_builddir)/src/cadet/libgnunetcadet.la \
-  $(top_builddir)/src/testbed/libgnunettestbed.la \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la
-
-dep_cadet_test_lib = \
-  libgnunetcadet.la \
-  libgnunetcadettest.a \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la
-
-
-gnunet_cadet_profiler_SOURCES = \
-  gnunet-cadet-profiler.c
-gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib)
-gnunet_cadet_profiler_DEPENDENCIES = $(dep_cadet_test_lib)
-
-
-test_cadet_single_SOURCES = \
-  test_cadet_single.c
-test_cadet_single_LDADD = $(ld_cadet_test_lib)
-test_cadet_single_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_local_SOURCES = \
-  test_cadet_local.c
-test_cadet_local_LDADD = $(ld_cadet_test_lib)
-test_cadet_local_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_forward_SOURCES = \
-  test_cadet.c
-test_cadet_forward_LDADD = $(ld_cadet_test_lib)
-test_cadet_forward_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_signal_SOURCES = \
-  test_cadet.c
-test_cadet_signal_LDADD = $(ld_cadet_test_lib)
-test_cadet_signal_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_keepalive_SOURCES = \
-  test_cadet.c
-test_cadet_keepalive_LDADD = $(ld_cadet_test_lib)
-test_cadet_keepalive_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_speed_SOURCES = \
-  test_cadet.c
-test_cadet_speed_LDADD = $(ld_cadet_test_lib)
-test_cadet_speed_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_speed_ack_SOURCES = \
-  test_cadet.c
-test_cadet_speed_ack_LDADD = $(ld_cadet_test_lib)
-test_cadet_speed_ack_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_speed_backwards_SOURCES = \
-  test_cadet.c
-test_cadet_speed_backwards_LDADD = $(ld_cadet_test_lib)
-test_cadet_speed_backwards_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_speed_reliable_SOURCES = \
-  test_cadet.c
-test_cadet_speed_reliable_LDADD = $(ld_cadet_test_lib)
-test_cadet_speed_reliable_DEPENDENCIES = $(dep_cadet_test_lib)
-
-test_cadet_speed_reliable_backwards_SOURCES = \
-  test_cadet.c
-test_cadet_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
-test_cadet_speed_reliable_backwards_DEPENDENCIES = $(dep_cadet_test_lib)
-
-
-if ENABLE_TEST_RUN
-AM_TESTS_ENVIRONMENT=export 
GNUNET_PREFIX=$${GNUNET_PREFIX:address@hidden@};export 
PATH=$${GNUNET_PREFIX:address@hidden@}/bin:$$PATH;
-TESTS = \
- $(check_PROGRAMS)
-endif
-
-EXTRA_DIST = \
-  cadet.h cadet_protocol.h \
-  test_cadet.conf \
-  test_cadet_drop.conf
-

Deleted: gnunet/src/mesh/beautify_log.sh
===================================================================
--- gnunet/src/mesh/beautify_log.sh     2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/beautify_log.sh     2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,18 +0,0 @@
-#!/bin/sh
-grep "STARTING SERVICE " log > __tmp_peers
-SED_EXPR=""
-while read -r line; do
-    PEER=`echo $line | sed -e 's/.*\[\(....\)\].*/\1/'`
-    PID=`echo $line | sed -e 's/.*mesh-\([0-9]*\).*/\1/'`
-    echo "$PID => $PEER"
-    SED_EXPR="${SED_EXPR}s/mesh-\([a-z2]*\)-$PID/MESH \1 $PEER/;"
-    SED_EXPR="${SED_EXPR}s/mesh-$PID/MESH XXX $PEER/;"
-done < __tmp_peers
-rm __tmp_peers
-
-SED_EXPR="${SED_EXPR}s/mesh-api-/mesh-api-                                     
       /g"
-sed -e "$SED_EXPR" log > .log
-
-if [[ "`ps aux | grep "kwrite .lo[g]"`" = "" ]]; then
-    kwrite .log --geometry 960x1140-960 &
-fi

Deleted: gnunet/src/mesh/cadet.h
===================================================================
--- gnunet/src/mesh/cadet.h     2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet.h     2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,351 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @author Bartlomiej Polot
- * @file cadet/cadet.h
- */
-
-#ifndef CADET_H_
-#define CADET_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include <stdint.h>
-
-#define CADET_DEBUG              GNUNET_YES
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_peer_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_protocols.h"
-#include <gnunet_cadet_service.h>
-
-/******************************************************************************/
-/**************************       CONSTANTS      
******************************/
-/******************************************************************************/
-
-#define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI        0x80000000
-#define GNUNET_CADET_LOCAL_CHANNEL_ID_SERV       0xB0000000
-
-#define HIGH_PID                                0xFFFF0000
-#define LOW_PID                                 0x0000FFFF
-
-#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID)
-
-/******************************************************************************/
-/**************************        MESSAGES      
******************************/
-/******************************************************************************/
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Message for a client to register to the service
- */
-struct GNUNET_CADET_ClientConnect
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT
-     *
-     * Size: sizeof(struct GNUNET_CADET_ClientConnect) +
-     *       sizeof(CADET_ApplicationType) * applications +
-     *       sizeof(uint16_t) * types
-     */
-  struct GNUNET_MessageHeader header;
-  /* uint32_t                 list_ports[]           */
-};
-
-
-/**
- * Type for channel numbering.
- * - Local channel numbers given by the service (incoming) are >= 0xB0000000
- * - Local channel numbers given by the client (created) are >= 0x80000000
- * - Global channel numbers are < 0x80000000
- */
-typedef uint32_t CADET_ChannelNumber;
-
-
-/**
- * Message for a client to create and destroy channels.
- */
-struct GNUNET_CADET_ChannelMessage
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_[CREATE|DESTROY]
-     *
-     * Size: sizeof(struct GNUNET_CADET_ChannelMessage)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of a channel controlled by this client.
-     */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
-
-    /**
-     * Channel's peer
-     */
-  struct GNUNET_PeerIdentity peer;
-
-    /**
-     * Port of the channel.
-     */
-  uint32_t port GNUNET_PACKED;
-
-    /**
-     * Options.
-     */
-  uint32_t opt GNUNET_PACKED;
-};
-
-
-/**
- * Message for cadet data traffic.
- */
-struct GNUNET_CADET_LocalData
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the channel
-     */
-  uint32_t id GNUNET_PACKED;
-
-    /**
-     * Payload follows
-     */
-};
-
-
-/**
- * Message to allow the client send more data to the service
- * (always service -> client).
- */
-struct GNUNET_CADET_LocalAck
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the channel allowed to send more data.
-     */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
-
-};
-
-
-/**
- * Message to inform the client about channels in the service.
- */
-struct GNUNET_CADET_LocalInfo
-{
-  /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO[_TUNNEL,_PEER]
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the channel allowed to send more data.
-   */
-  CADET_ChannelNumber channel_id GNUNET_PACKED;
-
-  /**
-   * ID of the owner of the channel (can be local peer).
-   */
-//   struct GNUNET_PeerIdentity owner;
-
-  /**
-   * ID of the destination of the channel (can be local peer).
-   */
-  struct GNUNET_PeerIdentity peer;
-};
-
-
-/**
- * Message to inform the client about one of the peers in the service.
- */
-struct GNUNET_CADET_LocalInfoPeer
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER[S]
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Number of paths.
-   */
-  uint16_t paths GNUNET_PACKED;
-
-  /**
-   * Do we have a tunnel toward this peer?
-   */
-  int16_t tunnel GNUNET_PACKED;
-
-  /**
-   * ID of the destination of the tunnel (can be local peer).
-   */
-  struct GNUNET_PeerIdentity destination;
-
-  /* If type == PEER (no 'S'): GNUNET_PeerIdentity paths[]
-   * (each path ends in destination) */
-};
-
-/**
- * Message to inform the client about one of the tunnels in the service.
- */
-struct GNUNET_CADET_LocalInfoTunnel
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL[S]
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Number of channels.
-   */
-  uint32_t channels GNUNET_PACKED;
-
-  /**
-   * ID of the destination of the tunnel (can be local peer).
-   */
-  struct GNUNET_PeerIdentity destination;
-
-  /**
-   * Number of connections.
-   */
-  uint32_t connections GNUNET_PACKED;
-
-  /**
-   * Encryption state.
-   */
-  uint16_t estate GNUNET_PACKED;
-
-  /**
-   * Connection state.
-   */
-  uint16_t cstate GNUNET_PACKED;
-
-  /* If TUNNEL (no 'S'): GNUNET_PeerIdentity connection_ids[connections] */
-  /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */
-};
-
-
-GNUNET_NETWORK_STRUCT_END
-
-
-
-/**
- * @brief Translate a fwd variable into a string representation, for logging.
- *
- * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO)
- *
- * @return String representing FWD or BCK.
- */
-char *
-GM_f2s (int fwd);
-
-
-/**
- * Check if one pid is bigger than other, accounting for overflow.
- *
- * @param bigger Argument that should be bigger.
- * @param smaller Argument that should be smaller.
- *
- * @return True if bigger (arg1) has a higher value than smaller (arg 2).
- */
-int
-GM_is_pid_bigger (uint32_t bigger, uint32_t smaller);
-
-
-/**
- * Get the higher ACK value out of two values, taking in account overflow.
- *
- * @param a First ACK value.
- * @param b Second ACK value.
- *
- * @return Highest ACK value from the two.
- */
-uint32_t
-GM_max_pid (uint32_t a, uint32_t b);
-
-
-/**
- * Get the lower ACK value out of two values, taking in account overflow.
- *
- * @param a First ACK value.
- * @param b Second ACK value.
- *
- * @return Lowest ACK value from the two.
- */
-uint32_t
-GM_min_pid (uint32_t a, uint32_t b);
-
-
-/**
- * Convert a 256 bit CadetHash into a 512 HashCode to use in GNUNET_h2s,
- * multihashmap, and other HashCode-based functions.
- *
- * @param id A 256 bit hash to expand.
- *
- * @return A HashCode containing the original 256 bit hash right-padded with 0.
- */
-const struct GNUNET_HashCode *
-GM_h2hc (const struct GNUNET_CADET_Hash *id);
-
-/**
- * Get a string from a Cadet Hash (256 bits).
- * WARNING: Not reentrant (based on GNUNET_h2s).
- */
-const char *
-GM_h2s (const struct GNUNET_CADET_Hash *id);
-
-/**
- * Convert a message type into a string to help debug
- * Generated with:
- * FIND:        "#define ([^ ]+)[ ]*([0-9]+)"
- * REPLACE:     "    case \2: return "\1"; break;"
- *
- * @param m Message type.
- *
- * @return Human readable string description.
- */
-const char *
-GM_m2s (uint16_t m);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif

Deleted: gnunet/src/mesh/cadet_api.c
===================================================================
--- gnunet/src/mesh/cadet_api.c 2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_api.c 2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,2141 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/cadet_api.c
- * @brief cadet api: client implementation of new cadet service
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_cadet_service.h"
-#include "cadet.h"
-#include "cadet_protocol.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__)
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/**
- * Transmission queue to the service
- */
-struct GNUNET_CADET_TransmitHandle
-{
-
-    /**
-     * Double Linked list
-     */
-  struct GNUNET_CADET_TransmitHandle *next;
-
-    /**
-     * Double Linked list
-     */
-  struct GNUNET_CADET_TransmitHandle *prev;
-
-    /**
-     * Channel this message is sent on / for (may be NULL for control 
messages).
-     */
-  struct GNUNET_CADET_Channel *channel;
-
-    /**
-     * Callback to obtain the message to transmit, or NULL if we
-     * got the message in 'data'.  Notice that messages built
-     * by 'notify' need to be encapsulated with information about
-     * the 'target'.
-     */
-  GNUNET_CONNECTION_TransmitReadyNotify notify;
-
-    /**
-     * Closure for 'notify'
-     */
-  void *notify_cls;
-
-    /**
-     * How long is this message valid.  Once the timeout has been
-     * reached, the message must no longer be sent.  If this
-     * is a message with a 'notify' callback set, the 'notify'
-     * function should be called with 'buf' NULL and size 0.
-     */
-  struct GNUNET_TIME_Absolute timeout;
-
-    /**
-     * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-    /**
-     * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
-     */
-  size_t size;
-};
-
-union CadetInfoCB {
-
-  /**
-   * Channel callback.
-   */
-  GNUNET_CADET_ChannelCB channel_cb;
-
-  /**
-   * Monitor callback
-   */
-  GNUNET_CADET_PeersCB peers_cb;
-
-  /**
-   * Monitor callback
-   */
-  GNUNET_CADET_PeerCB peer_cb;
-
-  /**
-   * Monitor callback
-   */
-  GNUNET_CADET_TunnelsCB tunnels_cb;
-
-  /**
-   * Tunnel callback.
-   */
-  GNUNET_CADET_TunnelCB tunnel_cb;
-};
-
-
-/**
- * Opaque handle to the service.
- */
-struct GNUNET_CADET_Handle
-{
-
-    /**
-     * Handle to the server connection, to send messages later
-     */
-  struct GNUNET_CLIENT_Connection *client;
-
-    /**
-     * Set of handlers used for processing incoming messages in the channels
-     */
-  const struct GNUNET_CADET_MessageHandler *message_handlers;
-
-  /**
-   * Number of handlers in the handlers array.
-   */
-  unsigned int n_handlers;
-
-  /**
-   * Ports open.
-   */
-  const uint32_t *ports;
-
-  /**
-   * Number of ports.
-   */
-  unsigned int n_ports;
-
-    /**
-     * Double linked list of the channels this client is connected to, head.
-     */
-  struct GNUNET_CADET_Channel *channels_head;
-
-    /**
-     * Double linked list of the channels this client is connected to, tail.
-     */
-  struct GNUNET_CADET_Channel *channels_tail;
-
-    /**
-     * Callback for inbound channel creation
-     */
-  GNUNET_CADET_InboundChannelNotificationHandler *new_channel;
-
-    /**
-     * Callback for inbound channel disconnection
-     */
-  GNUNET_CADET_ChannelEndHandler *cleaner;
-
-    /**
-     * Handle to cancel pending transmissions in case of disconnection
-     */
-  struct GNUNET_CLIENT_TransmitHandle *th;
-
-    /**
-     * Closure for all the handlers given by the client
-     */
-  void *cls;
-
-    /**
-     * Messages to send to the service, head.
-     */
-  struct GNUNET_CADET_TransmitHandle *th_head;
-
-    /**
-     * Messages to send to the service, tail.
-     */
-  struct GNUNET_CADET_TransmitHandle *th_tail;
-
-    /**
-     * chid of the next channel to create (to avoid reusing IDs often)
-     */
-  CADET_ChannelNumber next_chid;
-
-    /**
-     * Have we started the task to receive messages from the service
-     * yet? We do this after we send the 'CADET_LOCAL_CONNECT' message.
-     */
-  int in_receive;
-
-  /**
-   * Configuration given by the client, in case of reconnection
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Time to the next reconnect in case one reconnect fails
-   */
-  struct GNUNET_TIME_Relative reconnect_time;
-
-  /**
-   * Task for trying to reconnect.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
-
-  /**
-   * Callback for an info task (only one active at a time).
-   */
-  union CadetInfoCB info_cb;
-
-  /**
-   * Info callback closure for @c info_cb.
-   */
-  void *info_cls;
-};
-
-
-/**
- * Description of a peer
- */
-struct GNUNET_CADET_Peer
-{
-    /**
-     * ID of the peer in short form
-     */
-  GNUNET_PEER_Id id;
-
-  /**
-   * Channel this peer belongs to
-   */
-  struct GNUNET_CADET_Channel *t;
-};
-
-
-/**
- * Opaque handle to a channel.
- */
-struct GNUNET_CADET_Channel
-{
-
-    /**
-     * DLL next
-     */
-  struct GNUNET_CADET_Channel *next;
-
-    /**
-     * DLL prev
-     */
-  struct GNUNET_CADET_Channel *prev;
-
-    /**
-     * Handle to the cadet this channel belongs to
-     */
-  struct GNUNET_CADET_Handle *cadet;
-
-    /**
-     * Local ID of the channel
-     */
-  CADET_ChannelNumber chid;
-
-    /**
-     * Port number.
-     */
-  uint32_t port;
-
-    /**
-     * Other end of the channel.
-     */
-  GNUNET_PEER_Id peer;
-
-  /**
-   * Any data the caller wants to put in here
-   */
-  void *ctx;
-
-    /**
-     * Size of packet queued in this channel
-     */
-  unsigned int packet_size;
-
-    /**
-     * Channel options: reliability, etc.
-     */
-  enum GNUNET_CADET_ChannelOption options;
-
-    /**
-     * Are we allowed to send to the service?
-     */
-  int allow_send;
-
-};
-
-
-/**
- * Implementation state for cadet's message queue.
- */
-struct CadetMQState
-{
-  /**
-   * The current transmit handle, or NULL
-   * if no transmit is active.
-   */
-  struct GNUNET_CADET_TransmitHandle *th;
-
-  /**
-   * Channel to send the data over.
-   */
-  struct GNUNET_CADET_Channel *channel;
-};
-
-
-/******************************************************************************/
-/***********************         DECLARATIONS         
*************************/
-/******************************************************************************/
-
-/**
- * Function called to send a message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, the cadet handle
- * @param size number of bytes available in buf
- * @param buf where the callee should write the connect message
- * @return number of bytes written to buf
- */
-static size_t
-send_callback (void *cls, size_t size, void *buf);
-
-
-/******************************************************************************/
-/***********************     AUXILIARY FUNCTIONS      
*************************/
-/******************************************************************************/
-
-/**
- * Check if transmission is a payload packet.
- *
- * @param th Transmission handle.
- *
- * @return GNUNET_YES if it is a payload packet,
- *         GNUNET_NO if it is a cadet management packet.
- */
-static int
-th_is_payload (struct GNUNET_CADET_TransmitHandle *th)
-{
-  return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Check whether there is any message ready in the queue and find the size.
- *
- * @param h Cadet handle.
- *
- * @return The size of the first ready message in the queue,
- *         0 if there is none.
- */
-static size_t
-message_ready_size (struct GNUNET_CADET_Handle *h)
-{
-  struct GNUNET_CADET_TransmitHandle *th;
-  struct GNUNET_CADET_Channel *ch;
-
-  for (th = h->th_head; NULL != th; th = th->next)
-  {
-    ch = th->channel;
-    if (GNUNET_NO == th_is_payload (th))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message internal\n");
-      return th->size;
-    }
-    if (GNUNET_YES == ch->allow_send)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message payload ok\n");
-      return th->size;
-    }
-  }
-  return 0;
-}
-
-
-/**
- * Get the channel handler for the channel specified by id from the given 
handle
- * @param h Cadet handle
- * @param chid ID of the wanted channel
- * @return handle to the required channel or NULL if not found
- */
-static struct GNUNET_CADET_Channel *
-retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
-{
-  struct GNUNET_CADET_Channel *ch;
-
-  ch = h->channels_head;
-  while (ch != NULL)
-  {
-    if (ch->chid == chid)
-      return ch;
-    ch = ch->next;
-  }
-  return NULL;
-}
-
-
-/**
- * Create a new channel and insert it in the channel list of the cadet handle
- *
- * @param h Cadet handle
- * @param chid Desired chid of the channel, 0 to assign one automatically.
- *
- * @return Handle to the created channel.
- */
-static struct GNUNET_CADET_Channel *
-create_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid)
-{
-  struct GNUNET_CADET_Channel *ch;
-
-  ch = GNUNET_new (struct GNUNET_CADET_Channel);
-  GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch);
-  ch->cadet = h;
-  if (0 == chid)
-  {
-    ch->chid = h->next_chid;
-    while (NULL != retrieve_channel (h, h->next_chid))
-    {
-      h->next_chid++;
-      h->next_chid &= ~GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-      h->next_chid |= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-    }
-  }
-  else
-  {
-    ch->chid = chid;
-  }
-  ch->allow_send = GNUNET_NO;
-  return ch;
-}
-
-
-/**
- * Destroy the specified channel.
- * - Destroys all peers, calling the disconnect callback on each if needed
- * - Cancels all outgoing traffic for that channel, calling respective notifys
- * - Calls cleaner if channel was inbound
- * - Frees all memory used
- *
- * @param ch Pointer to the channel.
- * @param call_cleaner Whether to call the cleaner handler.
- *
- * @return Handle to the required channel or NULL if not found.
- */
-static void
-destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner)
-{
-  struct GNUNET_CADET_Handle *h;
-  struct GNUNET_CADET_TransmitHandle *th;
-  struct GNUNET_CADET_TransmitHandle *next;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " destroy_channel %X\n", ch->chid);
-
-  if (NULL == ch)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  h = ch->cadet;
-
-  GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch);
-
-  /* signal channel destruction */
-  if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) 
)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cleaner\n");
-    h->cleaner (h->cls, ch, ch->ctx);
-  }
-
-  /* check that clients did not leave messages behind in the queue */
-  for (th = h->th_head; NULL != th; th = next)
-  {
-    next = th->next;
-    if (th->channel != ch)
-      continue;
-    /* Clients should have aborted their requests already.
-     * Management traffic should be ok, as clients can't cancel that.
-     * If the service crashed and we are reconnecting, it's ok.
-     */
-    GNUNET_break (GNUNET_NO == th_is_payload (th)
-                  || GNUNET_NO == h->in_receive);
-    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-
-    /* clean up request */
-    if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
-      GNUNET_SCHEDULER_cancel (th->timeout_task);
-    GNUNET_free (th);
-  }
-
-  /* if there are no more pending requests with cadet service, cancel active 
request */
-  /* Note: this should be unnecessary... */
-  if ((0 == message_ready_size (h)) && (NULL != h->th))
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
-    h->th = NULL;
-  }
-
-  if (0 != ch->peer)
-    GNUNET_PEER_change_rc (ch->peer, -1);
-  GNUNET_free (ch);
-  return;
-}
-
-
-/**
- * Notify client that the transmission has timed out
- *
- * @param cls closure
- * @param tc task context
- */
-static void
-timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CADET_TransmitHandle *th = cls;
-  struct GNUNET_CADET_Handle *cadet;
-
-  cadet = th->channel->cadet;
-  GNUNET_CONTAINER_DLL_remove (cadet->th_head, cadet->th_tail, th);
-  th->channel->packet_size = 0;
-  if (GNUNET_YES == th_is_payload (th))
-    th->notify (th->notify_cls, 0, NULL);
-  GNUNET_free (th);
-  if ((0 == message_ready_size (cadet)) && (NULL != cadet->th))
-  {
-    /* nothing ready to transmit, no point in asking for transmission */
-    GNUNET_CLIENT_notify_transmit_ready_cancel (cadet->th);
-    cadet->th = NULL;
-  }
-}
-
-
-/**
- * Add a transmit handle to the transmission queue and set the
- * timeout if needed.
- *
- * @param h cadet handle with the queue head and tail
- * @param th handle to the packet to be transmitted
- */
-static void
-add_to_queue (struct GNUNET_CADET_Handle *h,
-              struct GNUNET_CADET_TransmitHandle *th)
-{
-  GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
-  if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == th->timeout.abs_value_us)
-    return;
-  th->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                    (th->timeout), &timeout_transmission, th);
-}
-
-
-/**
- * Auxiliary function to send an already constructed packet to the service.
- * Takes care of creating a new queue element, copying the message and
- * calling the tmt_rdy function if necessary.
- *
- * @param h cadet handle
- * @param msg message to transmit
- * @param channel channel this send is related to (NULL if N/A)
- */
-static void
-send_packet (struct GNUNET_CADET_Handle *h,
-             const struct GNUNET_MessageHeader *msg,
-             struct GNUNET_CADET_Channel *channel);
-
-
-/**
- * Send an ack on the channel to confirm the processing of a message.
- *
- * @param ch Channel on which to send the ACK.
- */
-static void
-send_ack (struct GNUNET_CADET_Channel *ch)
-{
-  struct GNUNET_CADET_LocalAck msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid);
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
-  msg.header.size = htons (sizeof (msg));
-  msg.channel_id = htonl (ch->chid);
-
-  send_packet (ch->cadet, &msg.header, ch);
-  return;
-}
-
-
-
-/**
- * Reconnect callback: tries to reconnect again after a failer previous
- * reconnecttion
- * @param cls closure (cadet handle)
- * @param tc task context
- */
-static void
-reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Send a connect packet to the service with the applications and types
- * requested by the user.
- *
- * @param h The cadet handle.
- *
- */
-static void
-send_connect (struct GNUNET_CADET_Handle *h)
-{
-  size_t size;
-
-  size = sizeof (struct GNUNET_CADET_ClientConnect);
-  size += h->n_ports * sizeof (uint32_t);
-  {
-    char buf[size] GNUNET_ALIGN;
-    struct GNUNET_CADET_ClientConnect *msg;
-    uint32_t *ports;
-    uint16_t i;
-
-    /* build connection packet */
-    msg = (struct GNUNET_CADET_ClientConnect *) buf;
-    msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT);
-    msg->header.size = htons (size);
-    ports = (uint32_t *) &msg[1];
-    for (i = 0; i < h->n_ports; i++)
-    {
-      ports[i] = htonl (h->ports[i]);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
-           h->ports[i]);
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Sending %lu bytes long message with %u ports\n",
-         ntohs (msg->header.size), h->n_ports);
-    send_packet (h, &msg->header, NULL);
-  }
-}
-
-
-/**
- * Reconnect to the service, retransmit all infomation to try to restore the
- * original state.
- *
- * @param h handle to the cadet
- *
- * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
- */
-static int
-do_reconnect (struct GNUNET_CADET_Handle *h)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
-
-  /* disconnect */
-  if (NULL != h->th)
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
-    h->th = NULL;
-  }
-  if (NULL != h->client)
-  {
-    GNUNET_CLIENT_disconnect (h->client);
-  }
-
-  /* connect again */
-  h->client = GNUNET_CLIENT_connect ("cadet", h->cfg);
-  if (h->client == NULL)
-  {
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-    h->reconnect_time =
-        GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
-                                  GNUNET_TIME_relative_multiply
-                                  (h->reconnect_time, 2));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Next retry in %s\n",
-         GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
-                                                 GNUNET_NO));
-    GNUNET_break (0);
-    return GNUNET_NO;
-  }
-  else
-  {
-    h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
-  }
-  send_connect (h);
-  return GNUNET_YES;
-}
-
-/**
- * Reconnect callback: tries to reconnect again after a failer previous
- * reconnecttion
- * @param cls closure (cadet handle)
- * @param tc task context
- */
-static void
-reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CADET_Handle *h = cls;
-
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  do_reconnect (h);
-}
-
-
-/**
- * Reconnect to the service, retransmit all infomation to try to restore the
- * original state.
- *
- * @param h handle to the cadet
- *
- * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
- */
-static void
-reconnect (struct GNUNET_CADET_Handle *h)
-{
-  struct GNUNET_CADET_Channel *ch;
-  struct GNUNET_CADET_Channel *next;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Requested RECONNECT, destroying all channels\n");
-  h->in_receive = GNUNET_NO;
-  for (ch = h->channels_head; NULL != ch; ch = next)
-  {
-    next = ch->next;
-    destroy_channel (ch, GNUNET_YES);
-  }
-  if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
-                                                      &reconnect_cbk, h);
-}
-
-
-/******************************************************************************/
-/***********************      RECEIVE HANDLERS     
****************************/
-/******************************************************************************/
-
-/**
- * Process the new channel notification and add it to the channels in the 
handle
- *
- * @param h     The cadet handle
- * @param msg   A message with the details of the new incoming channel
- */
-static void
-process_channel_created (struct GNUNET_CADET_Handle *h,
-                        const struct GNUNET_CADET_ChannelMessage *msg)
-{
-  struct GNUNET_CADET_Channel *ch;
-  CADET_ChannelNumber chid;
-  uint32_t port;
-
-  chid = ntohl (msg->channel_id);
-  port = ntohl (msg->port);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X:%u\n", chid, 
port);
-  if (chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (NULL != h->new_channel)
-  {
-    void *ctx;
-
-    ch = create_channel (h, chid);
-    ch->allow_send = GNUNET_NO;
-    ch->peer = GNUNET_PEER_intern (&msg->peer);
-    ch->cadet = h;
-    ch->chid = chid;
-    ch->port = port;
-    ch->options = ntohl (msg->opt);
-
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  created channel %p\n", ch);
-    ctx = h->new_channel (h->cls, ch, &msg->peer, ch->port, ch->options);
-    if (NULL != ctx)
-      ch->ctx = ctx;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
-  }
-  else
-  {
-    struct GNUNET_CADET_ChannelMessage d_msg;
-
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming channels\n");
-
-    d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-    d_msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
-    d_msg.channel_id = msg->channel_id;
-    memset (&d_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
-    d_msg.port = 0;
-    d_msg.opt = 0;
-
-    send_packet (h, &d_msg.header, NULL);
-  }
-  return;
-}
-
-
-/**
- * Process the channel destroy notification and free associated resources
- *
- * @param h     The cadet handle
- * @param msg   A message with the details of the channel being destroyed
- */
-static void
-process_channel_destroy (struct GNUNET_CADET_Handle *h,
-                         const struct GNUNET_CADET_ChannelMessage *msg)
-{
-  struct GNUNET_CADET_Channel *ch;
-  CADET_ChannelNumber chid;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel Destroy received from service\n");
-  chid = ntohl (msg->channel_id);
-  ch = retrieve_channel (h, chid);
-
-  if (NULL == ch)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " destroying channel %X\n", ch->chid);
-  destroy_channel (ch, GNUNET_YES);
-}
-
-
-/**
- * Process the incoming data packets, call appropriate handlers.
- *
- * @param h         The cadet handle
- * @param message   A message encapsulating the data
- */
-static void
-process_incoming_data (struct GNUNET_CADET_Handle *h,
-                       const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_MessageHeader *payload;
-  const struct GNUNET_CADET_MessageHandler *handler;
-  struct GNUNET_CADET_LocalData *dmsg;
-  struct GNUNET_CADET_Channel *ch;
-  size_t size;
-  unsigned int i;
-  uint16_t type;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
-  dmsg = (struct GNUNET_CADET_LocalData *) message;
-  ch = retrieve_channel (h, ntohl (dmsg->id));
-  if (NULL == ch)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  payload = (struct GNUNET_MessageHeader *) &dmsg[1];
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s data on channel %s [%X]\n",
-       GM_f2s (ch->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV),
-       GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (dmsg->id));
-
-  size = ntohs (message->size);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  %u bytes\n", size);
-
-  if (NULL == ch)
-  {
-    /* Channel was ignored/destroyed, probably service didn't get it yet */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
-    return;
-  }
-  type = ntohs (payload->type);
-  size = ntohs (payload->size);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  payload type %s\n", GM_m2s (type));
-  for (i = 0; i < h->n_handlers; i++)
-  {
-    handler = &h->message_handlers[i];
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    checking handler for type %u\n",
-         handler->type);
-    if (handler->type == type)
-    {
-      if (GNUNET_OK !=
-          handler->callback (h->cls, ch, &ch->ctx, payload))
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
-        GNUNET_CADET_channel_destroy (ch);
-        return;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG,
-             "callback completed successfully\n");
-        return;
-      }
-    }
-  }
-}
-
-
-/**
- * Process a local ACK message, enabling the client to send
- * more data to the service.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-static void
-process_ack (struct GNUNET_CADET_Handle *h,
-             const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalAck *msg;
-  struct GNUNET_CADET_Channel *ch;
-  CADET_ChannelNumber chid;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
-  msg = (struct GNUNET_CADET_LocalAck *) message;
-  chid = ntohl (msg->channel_id);
-  ch = retrieve_channel (h, chid);
-  if (NULL == ch)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X!\n", ch->chid);
-  ch->allow_send = GNUNET_YES;
-  if (NULL == h->th && 0 < ch->packet_size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n");
-    h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ch->packet_size,
-                                                 GNUNET_TIME_UNIT_FOREVER_REL,
-                                                 GNUNET_YES, &send_callback, 
h);
-  }
-}
-
-
-/*
- * Process a local reply about info on all channels, pass info to the user.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-// static void
-// process_get_channels (struct GNUNET_CADET_Handle *h,
-//                      const struct GNUNET_MessageHeader *message)
-// {
-//   struct GNUNET_CADET_LocalInfo *msg;
-//
-//   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n");
-//
-//   if (NULL == h->channels_cb)
-//   {
-//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
-//     return;
-//   }
-//
-//   msg = (struct GNUNET_CADET_LocalInfo *) message;
-//   if (ntohs (message->size) !=
-//       (sizeof (struct GNUNET_CADET_LocalInfo) +
-//        sizeof (struct GNUNET_PeerIdentity)))
-//   {
-//     GNUNET_break_op (0);
-//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-//                 "Get channels message: size %hu - expected %u\n",
-//                 ntohs (message->size),
-//                 sizeof (struct GNUNET_CADET_LocalInfo));
-//     return;
-//   }
-//   h->channels_cb (h->channels_cls,
-//                   ntohl (msg->channel_id),
-//                   &msg->owner,
-//                   &msg->destination);
-// }
-
-
-
-/*
- * Process a local monitor_channel reply, pass info to the user.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-// static void
-// process_show_channel (struct GNUNET_CADET_Handle *h,
-//                      const struct GNUNET_MessageHeader *message)
-// {
-//   struct GNUNET_CADET_LocalInfo *msg;
-//   size_t esize;
-//
-//   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n");
-//
-//   if (NULL == h->channel_cb)
-//   {
-//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
-//     return;
-//   }
-//
-//   /* Verify message sanity */
-//   msg = (struct GNUNET_CADET_LocalInfo *) message;
-//   esize = sizeof (struct GNUNET_CADET_LocalInfo);
-//   if (ntohs (message->size) != esize)
-//   {
-//     GNUNET_break_op (0);
-//     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-//                 "Show channel message: size %hu - expected %u\n",
-//                 ntohs (message->size),
-//                 esize);
-//
-//     h->channel_cb (h->channel_cls, NULL, NULL);
-//     h->channel_cb = NULL;
-//     h->channel_cls = NULL;
-//
-//     return;
-//   }
-//
-//   h->channel_cb (h->channel_cls,
-//                  &msg->destination,
-//                  &msg->owner);
-// }
-
-
-
-/**
- * Process a local reply about info on all tunnels, pass info to the user.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-static void
-process_get_peers (struct GNUNET_CADET_Handle *h,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalInfoPeer *msg;
-  uint16_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Peer messasge received\n");
-
-  if (NULL == h->info_cb.peers_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
-    return;
-  }
-
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size)
-  {
-    h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0);
-    h->info_cb.peers_cb = NULL;
-    h->info_cls = NULL;
-    return;
-  }
-
-  msg = (struct GNUNET_CADET_LocalInfoPeer *) message;
-  h->info_cb.peers_cb (h->info_cls, &msg->destination,
-                       (int) ntohs (msg->tunnel),
-                       (unsigned int ) ntohs (msg->paths),
-                       0);
-}
-
-
-/**
- * Process a local peer info reply, pass info to the user.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-static void
-process_get_peer (struct GNUNET_CADET_Handle *h,
-                  const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalInfoTunnel *msg;
-  size_t esize;
-  size_t msize;
-  unsigned int ch_n;
-  unsigned int c_n;
-  struct GNUNET_CADET_Hash *conns;
-  CADET_ChannelNumber *chns;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n");
-  if (NULL == h->info_cb.tunnel_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
-    return;
-  }
-
-  /* Verify message sanity */
-  msg = (struct GNUNET_CADET_LocalInfoTunnel *) message;
-  msize = ntohs (message->size);
-  esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
-  if (esize > msize)
-  {
-    GNUNET_break_op (0);
-    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
-    goto clean_cls;
-  }
-  ch_n = ntohl (msg->channels);
-  c_n = ntohl (msg->connections);
-  esize += ch_n * sizeof (CADET_ChannelNumber);
-  esize += c_n * sizeof (struct GNUNET_CADET_Hash);
-  if (msize != esize)
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n",
-                msize, esize, ch_n, c_n);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n",
-                sizeof (struct GNUNET_CADET_LocalInfoTunnel),
-                sizeof (CADET_ChannelNumber), sizeof (struct GNUNET_HashCode));
-    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
-    goto clean_cls;
-  }
-
-  /* Call Callback with tunnel info. */
-  conns = (struct GNUNET_CADET_Hash *) &msg[1];
-  chns = (CADET_ChannelNumber *) &conns[c_n];
-  h->info_cb.tunnel_cb (h->info_cls, &msg->destination,
-                        ch_n, c_n, chns, conns,
-                        ntohs (msg->estate), ntohs (msg->cstate));
-
-  clean_cls:
-  h->info_cb.tunnel_cb = NULL;
-  h->info_cls = NULL;
-}
-
-
-/**
- * Process a local reply about info on all tunnels, pass info to the user.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-static void
-process_get_tunnels (struct GNUNET_CADET_Handle *h,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalInfoTunnel *msg;
-  uint16_t size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnels messasge received\n");
-
-  if (NULL == h->info_cb.tunnels_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
-    return;
-  }
-
-  size = ntohs (message->size);
-  if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size)
-  {
-    h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0);
-    h->info_cb.tunnels_cb = NULL;
-    h->info_cls = NULL;
-    return;
-  }
-
-  msg = (struct GNUNET_CADET_LocalInfoTunnel *) message;
-  h->info_cb.tunnels_cb (h->info_cls, &msg->destination,
-                         ntohl (msg->channels), ntohl (msg->connections),
-                         ntohs (msg->estate), ntohs (msg->cstate));
-
-}
-
-
-/**
- * Process a local tunnel info reply, pass info to the user.
- *
- * @param h Cadet handle.
- * @param message Message itself.
- */
-static void
-process_get_tunnel (struct GNUNET_CADET_Handle *h,
-                    const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalInfoTunnel *msg;
-  size_t esize;
-  size_t msize;
-  unsigned int ch_n;
-  unsigned int c_n;
-  struct GNUNET_CADET_Hash *conns;
-  CADET_ChannelNumber *chns;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n");
-  if (NULL == h->info_cb.tunnel_cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ignored\n");
-    return;
-  }
-
-  /* Verify message sanity */
-  msg = (struct GNUNET_CADET_LocalInfoTunnel *) message;
-  msize = ntohs (message->size);
-  esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
-  if (esize > msize)
-  {
-    GNUNET_break_op (0);
-    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
-    goto clean_cls;
-  }
-  ch_n = ntohl (msg->channels);
-  c_n = ntohl (msg->connections);
-  esize += ch_n * sizeof (CADET_ChannelNumber);
-  esize += c_n * sizeof (struct GNUNET_CADET_Hash);
-  if (msize != esize)
-  {
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n",
-                msize, esize, ch_n, c_n);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n",
-                sizeof (struct GNUNET_CADET_LocalInfoTunnel),
-                sizeof (CADET_ChannelNumber), sizeof (struct GNUNET_HashCode));
-    h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0);
-    goto clean_cls;
-  }
-
-  /* Call Callback with tunnel info. */
-  conns = (struct GNUNET_CADET_Hash *) &msg[1];
-  chns = (CADET_ChannelNumber *) &conns[c_n];
-  h->info_cb.tunnel_cb (h->info_cls, &msg->destination,
-                ch_n, c_n, chns, conns,
-                ntohs (msg->estate), ntohs (msg->cstate));
-
-clean_cls:
-  h->info_cb.tunnel_cb = NULL;
-  h->info_cls = NULL;
-}
-
-
-/**
- * Function to process all messages received from the service
- *
- * @param cls closure
- * @param msg message received, NULL on timeout or fatal error
- */
-static void
-msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CADET_Handle *h = cls;
-  uint16_t type;
-
-  if (msg == NULL)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "Cadet service disconnected, reconnecting\n", h);
-    reconnect (h);
-    return;
-  }
-  type = ntohs (msg->type);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
-       GM_m2s (type));
-  switch (type)
-  {
-    /* Notify of a new incoming channel */
-  case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    process_channel_created (h, (struct GNUNET_CADET_ChannelMessage *) msg);
-    break;
-    /* Notify of a channel disconnection */
-  case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: /* TODO separate(gid 
problem)*/
-  case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-    process_channel_destroy (h, (struct GNUNET_CADET_ChannelMessage *) msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA:
-    process_incoming_data (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK:
-    process_ack (h, msg);
-    break;
-//   case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
-//     process_get_channels (h, msg);
-//     break;
-//   case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
-//     process_show_channel (h, msg);
-//     break;
-  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
-    process_get_peers (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
-    process_get_peer (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
-    process_get_tunnels (h, msg);
-    break;
-  case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
-    process_get_tunnel (h, msg);
-    break;
-//   case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
-//     process_show_channel (h, msg);
-//     break;
-  default:
-    /* We shouldn't get any other packages, log and ignore */
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "unsolicited message form service (type %s)\n",
-         GM_m2s (ntohs (msg->type)));
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
-  if (GNUNET_YES == h->in_receive)
-  {
-    GNUNET_CLIENT_receive (h->client, &msg_received, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "in receive off, not calling CLIENT_receive\n");
-  }
-}
-
-
-/******************************************************************************/
-/************************       SEND FUNCTIONS     
****************************/
-/******************************************************************************/
-
-/**
- * Function called to send a message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, the cadet handle
- * @param size number of bytes available in buf
- * @param buf where the callee should write the connect message
- * @return number of bytes written to buf
- */
-static size_t
-send_callback (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_CADET_Handle *h = cls;
-  struct GNUNET_CADET_TransmitHandle *th;
-  struct GNUNET_CADET_TransmitHandle *next;
-  struct GNUNET_CADET_Channel *ch;
-  char *cbuf = buf;
-  size_t tsize;
-  size_t psize;
-  size_t nsize;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
-  if ((0 == size) || (NULL == buf))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
-    reconnect (h);
-    h->th = NULL;
-    return 0;
-  }
-  tsize = 0;
-  next = h->th_head;
-  nsize = message_ready_size (h);
-  while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
-  {
-    ch = th->channel;
-    if (GNUNET_YES == th_is_payload (th))
-    {
-      struct GNUNET_CADET_LocalData *dmsg;
-      struct GNUNET_MessageHeader *mh;
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload\n");
-      if (GNUNET_NO == ch->allow_send)
-      {
-        /* This channel is not ready to transmit yet, try next message */
-        next = th->next;
-        continue;
-      }
-      ch->packet_size = 0;
-      GNUNET_assert (size >= th->size);
-      dmsg = (struct GNUNET_CADET_LocalData *) cbuf;
-      mh = (struct GNUNET_MessageHeader *) &dmsg[1];
-      psize = th->notify (th->notify_cls,
-                          size - sizeof (struct GNUNET_CADET_LocalData),
-                          mh);
-      if (psize > 0)
-      {
-        psize += sizeof (struct GNUNET_CADET_LocalData);
-        GNUNET_assert (size >= psize);
-        dmsg->header.size = htons (psize);
-        dmsg->id = htonl (ch->chid);
-        dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload type %s\n",
-             GM_m2s (ntohs (mh->type)));
-                ch->allow_send = GNUNET_NO;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG,
-             "#  callback returned size 0, "
-             "application canceled transmission\n");
-      }
-    }
-    else
-    {
-      struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  cadet internal traffic, type %s\n",
-           GM_m2s (ntohs (mh->type)));
-      memcpy (cbuf, &th[1], th->size);
-      psize = th->size;
-    }
-    if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-      GNUNET_SCHEDULER_cancel (th->timeout_task);
-    GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-    GNUNET_free (th);
-    next = h->th_head;
-    nsize = message_ready_size (h);
-    cbuf += psize;
-    size -= psize;
-    tsize += psize;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "#  total size: %u\n", tsize);
-  h->th = NULL;
-  size = message_ready_size (h);
-  if (0 != size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "#  next size: %u\n", size);
-    h->th =
-        GNUNET_CLIENT_notify_transmit_ready (h->client, size,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             GNUNET_YES, &send_callback, h);
-  }
-  else
-  {
-    if (NULL != h->th_head)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  can't transmit any more\n");
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "#  nothing left to transmit\n");
-  }
-  if (GNUNET_NO == h->in_receive)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
-    h->in_receive = GNUNET_YES;
-    GNUNET_CLIENT_receive (h->client, &msg_received, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
-  return tsize;
-}
-
-
-/**
- * Auxiliary function to send an already constructed packet to the service.
- * Takes care of creating a new queue element, copying the message and
- * calling the tmt_rdy function if necessary.
- *
- * @param h cadet handle
- * @param msg message to transmit
- * @param channel channel this send is related to (NULL if N/A)
- */
-static void
-send_packet (struct GNUNET_CADET_Handle *h,
-             const struct GNUNET_MessageHeader *msg,
-             struct GNUNET_CADET_Channel *channel)
-{
-  struct GNUNET_CADET_TransmitHandle *th;
-  size_t msize;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
-       GM_m2s(ntohs(msg->type)));
-  msize = ntohs (msg->size);
-  th = GNUNET_malloc (sizeof (struct GNUNET_CADET_TransmitHandle) + msize);
-  th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
-  th->size = msize;
-  th->channel = channel;
-  memcpy (&th[1], msg, msize);
-  add_to_queue (h, th);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
-  if (NULL != h->th)
-    return;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", 
msize);
-  h->th =
-      GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &send_callback, h);
-}
-
-
-/******************************************************************************/
-/**********************      API CALL DEFINITIONS     
*************************/
-/******************************************************************************/
-
-struct GNUNET_CADET_Handle *
-GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
-                     GNUNET_CADET_InboundChannelNotificationHandler 
new_channel,
-                     GNUNET_CADET_ChannelEndHandler cleaner,
-                     const struct GNUNET_CADET_MessageHandler *handlers,
-                     const uint32_t *ports)
-{
-  struct GNUNET_CADET_Handle *h;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n");
-  h = GNUNET_new (struct GNUNET_CADET_Handle);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
-  h->cfg = cfg;
-  h->new_channel = new_channel;
-  h->cleaner = cleaner;
-  h->client = GNUNET_CLIENT_connect ("cadet", cfg);
-  if (h->client == NULL)
-  {
-    GNUNET_break (0);
-    GNUNET_free (h);
-    return NULL;
-  }
-  h->cls = cls;
-  h->message_handlers = handlers;
-  h->ports = ports;
-  h->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-  h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (NULL != ports && ports[0] != 0 && NULL == new_channel)
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "no new channel handler given, ports parameter is useless!!\n");
-  }
-  if ((NULL == ports || ports[0] == 0) && NULL != new_channel)
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "no ports given, new channel handler will never be called!!\n");
-  }
-  /* count handlers */
-  for (h->n_handlers = 0;
-       handlers && handlers[h->n_handlers].type;
-       h->n_handlers++) ;
-  for (h->n_ports = 0;
-       ports && ports[h->n_ports];
-       h->n_ports++) ;
-  send_connect (h);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect() END\n");
-  return h;
-}
-
-
-void
-GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
-{
-  struct GNUNET_CADET_Channel *ch;
-  struct GNUNET_CADET_Channel *aux;
-  struct GNUNET_CADET_TransmitHandle *th;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET DISCONNECT\n");
-
-  ch = handle->channels_head;
-  while (NULL != ch)
-  {
-    aux = ch->next;
-    if (ch->chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-    {
-      GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid);
-    }
-    destroy_channel (ch, GNUNET_YES);
-    ch = aux;
-  }
-  while ( (th = handle->th_head) != NULL)
-  {
-    struct GNUNET_MessageHeader *msg;
-
-    /* Make sure it is an allowed packet (everything else should have been
-     * already canceled).
-     */
-    GNUNET_break (GNUNET_NO == th_is_payload (th));
-    msg = (struct GNUNET_MessageHeader *) &th[1];
-    switch (ntohs(msg->type))
-    {
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT:
-      case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-      case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
-      case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
-        break;
-      default:
-        GNUNET_break (0);
-        LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
-             ntohs(msg->type));
-    }
-
-    GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
-    GNUNET_free (th);
-  }
-
-  if (NULL != handle->th)
-  {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
-    handle->th = NULL;
-  }
-  if (NULL != handle->client)
-  {
-    GNUNET_CLIENT_disconnect (handle->client);
-    handle->client = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel(handle->reconnect_task);
-    handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_free (handle);
-}
-
-
-/**
- * Create a new channel towards a remote peer.
- *
- * If the destination port is not open by any peer or the destination peer
- * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called
- * for this channel.
- *
- * @param h cadet handle
- * @param channel_ctx client's channel context to associate with the channel
- * @param peer peer identity the channel should go to
- * @param port Port number.
- * @param options CadetOption flag field, with all desired option bits set to 
1.
- *
- * @return handle to the channel
- */
-struct GNUNET_CADET_Channel *
-GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
-                            void *channel_ctx,
-                            const struct GNUNET_PeerIdentity *peer,
-                            uint32_t port,
-                            enum GNUNET_CADET_ChannelOption options)
-{
-  struct GNUNET_CADET_Channel *ch;
-  struct GNUNET_CADET_ChannelMessage msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Creating new channel to %s:%u\n",
-       GNUNET_i2s (peer), port);
-  ch = create_channel (h, 0);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", ch);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", ch->chid);
-  ch->ctx = channel_ctx;
-  ch->peer = GNUNET_PEER_intern (peer);
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
-  msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
-  msg.channel_id = htonl (ch->chid);
-  msg.port = htonl (port);
-  msg.peer = *peer;
-  msg.opt = htonl (options);
-  ch->allow_send = 0;
-  send_packet (h, &msg.header, ch);
-  return ch;
-}
-
-
-void
-GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
-{
-  struct GNUNET_CADET_Handle *h;
-  struct GNUNET_CADET_ChannelMessage msg;
-  struct GNUNET_CADET_TransmitHandle *th;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying channel\n");
-  h = channel->cadet;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-  msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage));
-  msg.channel_id = htonl (channel->chid);
-  memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
-  msg.port = 0;
-  msg.opt = 0;
-  th = h->th_head;
-  while (th != NULL)
-  {
-    struct GNUNET_CADET_TransmitHandle *aux;
-    if (th->channel == channel)
-    {
-      aux = th->next;
-      /* FIXME call the handler? */
-      if (GNUNET_YES == th_is_payload (th))
-        th->notify (th->notify_cls, 0, NULL);
-      GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
-      GNUNET_free (th);
-      th = aux;
-    }
-    else
-      th = th->next;
-  }
-
-  destroy_channel (channel, GNUNET_YES);
-  send_packet (h, &msg.header, NULL);
-}
-
-
-/**
- * Get information about a channel.
- *
- * @param channel Channel handle.
- * @param option Query (GNUNET_CADET_OPTION_*).
- * @param ... dependant on option, currently not used
- *
- * @return Union with an answer to the query.
- */
-const union GNUNET_CADET_ChannelInfo *
-GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
-                              enum GNUNET_CADET_ChannelOption option, ...)
-{
-  static int bool_flag;
-  const union GNUNET_CADET_ChannelInfo *ret;
-
-  switch (option)
-  {
-    case GNUNET_CADET_OPTION_NOBUFFER:
-    case GNUNET_CADET_OPTION_RELIABLE:
-    case GNUNET_CADET_OPTION_OOORDER:
-      if (0 != (option & channel->options))
-        bool_flag = GNUNET_YES;
-      else
-        bool_flag = GNUNET_NO;
-      ret = (const union GNUNET_CADET_ChannelInfo *) &bool_flag;
-      break;
-    case GNUNET_CADET_OPTION_PEER:
-      ret = (const union GNUNET_CADET_ChannelInfo *) GNUNET_PEER_resolve2 
(channel->peer);
-      break;
-    default:
-      GNUNET_break (0);
-      return NULL;
-  }
-
-  return ret;
-}
-
-struct GNUNET_CADET_TransmitHandle *
-GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel, int 
cork,
-                                   struct GNUNET_TIME_Relative maxdelay,
-                                   size_t notify_size,
-                                   GNUNET_CONNECTION_TransmitReadyNotify 
notify,
-                                   void *notify_cls)
-{
-  struct GNUNET_CADET_TransmitHandle *th;
-
-  GNUNET_assert (NULL != channel);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    on channel %X\n", channel->chid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    allow_send %d\n", channel->allow_send);
-  if (channel->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
-  GNUNET_assert (NULL != notify);
-  GNUNET_assert (0 == channel->packet_size); // Only one data packet allowed
-  th = GNUNET_new (struct GNUNET_CADET_TransmitHandle);
-  th->channel = channel;
-  th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
-  th->size = notify_size + sizeof (struct GNUNET_CADET_LocalData);
-  channel->packet_size = th->size;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
-  th->notify = notify;
-  th->notify_cls = notify_cls;
-  add_to_queue (channel->cadet, th);
-  if (NULL != channel->cadet->th)
-    return th;
-  if (GNUNET_NO == channel->allow_send)
-    return th;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    call client notify tmt rdy\n");
-  channel->cadet->th =
-      GNUNET_CLIENT_notify_transmit_ready (channel->cadet->client, th->size,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, &send_callback,
-                                           channel->cadet);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY END\n");
-  return th;
-}
-
-
-void
-GNUNET_CADET_notify_transmit_ready_cancel (struct GNUNET_CADET_TransmitHandle 
*th)
-{
-  struct GNUNET_CADET_Handle *cadet;
-
-  th->channel->packet_size = 0;
-  cadet = th->channel->cadet;
-  if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (th->timeout_task);
-  GNUNET_CONTAINER_DLL_remove (cadet->th_head, cadet->th_tail, th);
-  GNUNET_free (th);
-  if ((0 == message_ready_size (cadet)) && (NULL != cadet->th))
-  {
-    /* queue empty, no point in asking for transmission */
-    GNUNET_CLIENT_notify_transmit_ready_cancel (cadet->th);
-    cadet->th = NULL;
-  }
-}
-
-
-void
-GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
-{
-  send_ack (channel);
-}
-
-
-static void
-send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type)
-{
-  struct GNUNET_MessageHeader msg;
-
-  msg.size = htons (sizeof (msg));
-  msg.type = htons (type);
-  send_packet (h, &msg, NULL);
-}
-
-
-/**
- * Request information about peers known to the running cadet service.
- * The callback will be called for every peer known to the service.
- * Only one info request (of any kind) can be active at once.
- *
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the cadet peer.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- *
- * @return #GNUNET_OK / #GNUNET_SYSERR
- */
-int
-GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h,
-                       GNUNET_CADET_PeersCB callback,
-                       void *callback_cls)
-{
-  if (NULL != h->info_cb.peers_cb)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
-  h->info_cb.peers_cb = callback;
-  h->info_cls = callback_cls;
-  return GNUNET_OK;
-}
-
-
-/**
- * Cancel a peer info request. The callback will not be called (anymore).
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Cadet handle.
- *
- * @return Closure given to GNUNET_CADET_get_peers.
- */
-void *
-GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h)
-{
-  void *cls;
-
-  cls = h->info_cls;
-  h->info_cb.peers_cb = NULL;
-  h->info_cls = NULL;
-  return cls;
-}
-
-
-/**
- * Request information about a peer known to the running cadet peer.
- * The callback will be called for the tunnel once.
- * Only one info request (of any kind) can be active at once.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the cadet peer.
- * @param id Peer whose tunnel to examine.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- *
- * @return #GNUNET_OK / #GNUNET_SYSERR
- */
-int
-GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h,
-                      const struct GNUNET_PeerIdentity *id,
-                      GNUNET_CADET_PeerCB callback,
-                      void *callback_cls)
-{
-  struct GNUNET_CADET_LocalInfo msg;
-
-  if (NULL != h->info_cb.peer_cb)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  memset (&msg, 0, sizeof (msg));
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
-  msg.peer = *id;
-  send_packet (h, &msg.header, NULL);
-  h->info_cb.peer_cb = callback;
-  h->info_cls = callback_cls;
-  return GNUNET_OK;
-}
-
-
-/**
- * Request information about tunnels of the running cadet peer.
- * The callback will be called for every tunnel of the service.
- * Only one info request (of any kind) can be active at once.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the cadet peer.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- *
- * @return #GNUNET_OK / #GNUNET_SYSERR
- */
-int
-GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h,
-                         GNUNET_CADET_TunnelsCB callback,
-                         void *callback_cls)
-{
-  if (NULL != h->info_cb.tunnels_cb)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
-  h->info_cb.tunnels_cb = callback;
-  h->info_cls = callback_cls;
-  return GNUNET_OK;
-}
-
-
-/**
- * Cancel a monitor request. The monitor callback will not be called.
- *
- * @param h Cadet handle.
- *
- * @return Closure given to GNUNET_CADET_get_tunnels.
- */
-void *
-GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h)
-{
-  void *cls;
-
-  h->info_cb.tunnels_cb = NULL;
-  cls = h->info_cls;
-  h->info_cls = NULL;
-
-  return cls;
-}
-
-
-
-/**
- * Request information about a tunnel of the running cadet peer.
- * The callback will be called for the tunnel once.
- * Only one info request (of any kind) can be active at once.
- *
- * WARNING: unstable API, likely to change in the future!
- *
- * @param h Handle to the cadet peer.
- * @param id Peer whose tunnel to examine.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- *
- * @return #GNUNET_OK / #GNUNET_SYSERR
- */
-int
-GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h,
-                        const struct GNUNET_PeerIdentity *id,
-                        GNUNET_CADET_TunnelCB callback,
-                        void *callback_cls)
-{
-  struct GNUNET_CADET_LocalInfo msg;
-
-  if (NULL != h->info_cb.tunnel_cb)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  memset (&msg, 0, sizeof (msg));
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
-  msg.peer = *id;
-  send_packet (h, &msg.header, NULL);
-  h->info_cb.tunnel_cb = callback;
-  h->info_cls = callback_cls;
-  return GNUNET_OK;
-}
-
-
-/**
- * Request information about a specific channel of the running cadet peer.
- *
- * WARNING: unstable API, likely to change in the future!
- * FIXME Add destination option.
- *
- * @param h Handle to the cadet peer.
- * @param initiator ID of the owner of the channel.
- * @param channel_number Channel number.
- * @param callback Function to call with the requested data.
- * @param callback_cls Closure for @c callback.
- *
- * @return #GNUNET_OK / #GNUNET_SYSERR
- */
-int
-GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h,
-                         struct GNUNET_PeerIdentity *initiator,
-                         unsigned int channel_number,
-                         GNUNET_CADET_ChannelCB callback,
-                         void *callback_cls)
-{
-  struct GNUNET_CADET_LocalInfo msg;
-
-  if (NULL != h->info_cb.channel_cb)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL);
-  msg.peer = *initiator;
-  msg.channel_id = htonl (channel_number);
-//   msg.reserved = 0;
-  send_packet (h, &msg.header, NULL);
-  h->info_cb.channel_cb = callback;
-  h->info_cls = callback_cls;
-  return GNUNET_OK;
-}
-
-
-/**
- * Function called to notify a client about the connection
- * begin ready to queue more data.  "buf" will be
- * NULL and "size" zero if the connection was closed for
- * writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-cadet_mq_ntr (void *cls, size_t size,
-             void *buf)
-{
-  struct GNUNET_MQ_Handle *mq = cls;
-  struct CadetMQState *state = GNUNET_MQ_impl_state (mq);
-  const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
-  uint16_t msize;
-
-  state->th = NULL;
-  if (NULL == buf)
-  {
-    GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
-    return 0;
-  }
-  msize = ntohs (msg->size);
-  GNUNET_assert (msize <= size);
-  memcpy (buf, msg, msize);
-  GNUNET_MQ_impl_send_continue (mq);
-  return msize;
-}
-
-
-/**
- * Signature of functions implementing the
- * sending functionality of a message queue.
- *
- * @param mq the message queue
- * @param msg the message to send
- * @param impl_state state of the implementation
- */
-static void
-cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
-                   const struct GNUNET_MessageHeader *msg, void *impl_state)
-{
-  struct CadetMQState *state = impl_state;
-
-  GNUNET_assert (NULL == state->th);
-  state->th =
-      GNUNET_CADET_notify_transmit_ready (state->channel,
-                                         /* FIXME: add option for corking */
-                                         GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         ntohs (msg->size),
-                                         cadet_mq_ntr, mq);
-
-}
-
-
-/**
- * Signature of functions implementing the
- * destruction of a message queue.
- * Implementations must not free 'mq', but should
- * take care of 'impl_state'.
- *
- * @param mq the message queue to destroy
- * @param impl_state state of the implementation
- */
-static void
-cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
-{
-  struct CadetMQState *state = impl_state;
-
-  if (NULL != state->th)
-    GNUNET_CADET_notify_transmit_ready_cancel (state->th);
-
-  GNUNET_free (state);
-}
-
-
-/**
- * Create a message queue for a cadet channel.
- * The message queue can only be used to transmit messages,
- * not to receive them.
- *
- * @param channel the channel to create the message qeue for
- * @return a message queue to messages over the channel
- */
-struct GNUNET_MQ_Handle *
-GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel)
-{
-  struct GNUNET_MQ_Handle *mq;
-  struct CadetMQState *state;
-
-  state = GNUNET_new (struct CadetMQState);
-  state->channel = channel;
-
-  mq = GNUNET_MQ_queue_for_callbacks (cadet_mq_send_impl,
-                                      cadet_mq_destroy_impl,
-                                      NULL, /* FIXME: cancel impl. */
-                                      state,
-                                      NULL, /* no msg handlers */
-                                      NULL, /* no err handlers */
-                                      NULL); /* no handler cls */
-  return mq;
-}
-

Deleted: gnunet/src/mesh/cadet_common.c
===================================================================
--- gnunet/src/mesh/cadet_common.c      2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_common.c      2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,348 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/cadet_common.c
- * @brief CADET helper functions
- * @author Bartlomiej Polot
- */
-
-#include "cadet.h"
-
-/**
- * @brief Translate a fwd variable into a string representation, for logging.
- *
- * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO)
- *
- * @return String representing FWD or BCK.
- */
-char *
-GM_f2s (int fwd)
-{
-  if (GNUNET_YES == fwd)
-  {
-    return "FWD";
-  }
-  else if (GNUNET_NO == fwd)
-  {
-    return "BCK";
-  }
-  else
-  {
-    /* Not an error, can happen with CONNECTION_BROKEN messages. */
-    return "";
-  }
-}
-
-int
-GM_is_pid_bigger (uint32_t bigger, uint32_t smaller)
-{
-    return (GNUNET_YES == PID_OVERFLOW (smaller, bigger) ||
-            (bigger > smaller && GNUNET_NO == PID_OVERFLOW (bigger, smaller)));
-}
-
-
-uint32_t
-GM_max_pid (uint32_t a, uint32_t b)
-{
-  if (GM_is_pid_bigger(a, b))
-    return a;
-  return b;
-}
-
-
-uint32_t
-GM_min_pid (uint32_t a, uint32_t b)
-{
-  if (GM_is_pid_bigger(a, b))
-    return b;
-  return a;
-}
-
-
-const struct GNUNET_HashCode *
-GM_h2hc (const struct GNUNET_CADET_Hash *id)
-{
-  static struct GNUNET_HashCode hc;
-  memcpy (&hc, id, sizeof (*id));
-
-  return &hc;
-}
-
-
-const char *
-GM_h2s (const struct GNUNET_CADET_Hash *id)
-{
-  static char s[53];
-
-  memcpy (s, GNUNET_h2s_full (GM_h2hc (id)), 52);
-  s[52] = '\0';
-
-  return s;
-}
-
-
-#if !defined(GNUNET_CULL_LOGGING)
-const char *
-GM_m2s (uint16_t m)
-{
-  static char buf[32];
-  const char *t;
-
-  switch (m)
-  {
-      /**
-       * Request the creation of a path
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-      t = "CONNECTION_CREATE";
-      break;
-
-      /**
-       * Request the modification of an existing path
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-      t = "CONNECTION_ACK";
-      break;
-
-      /**
-       * Notify that a connection of a path is no longer valid
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
-      t = "CONNECTION_BROKEN";
-      break;
-
-      /**
-       * At some point, the route will spontaneously change
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED:
-      t = "PATH_CHANGED";
-      break;
-
-      /**
-       * Transport payload data.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-      t = "DATA";
-      break;
-
-    /**
-     * Confirm receipt of payload data.
-     */
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      t = "DATA_ACK";
-      break;
-
-      /**
-       * Key exchange encapsulation.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
-      t = "KX";
-      break;
-
-      /**
-       * New ephemeral key.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL:
-      t = "KX_EPHEMERAL";
-      break;
-
-      /**
-       * Challenge to test peer's session key.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_KX_PING:
-      t = "KX_PING";
-      break;
-
-      /**
-       * Answer to session key challenge.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_KX_PONG:
-      t = "KX_PONG";
-      break;
-
-      /**
-       * Request the destuction of a path
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
-      t = "CONNECTION_DESTROY";
-      break;
-
-      /**
-       * ACK for a data packet.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
-      t = "ACK";
-      break;
-
-      /**
-       * POLL for ACK.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
-      t = "POLL";
-      break;
-
-      /**
-       * Announce origin is still alive.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
-      t = "KEEPALIVE";
-      break;
-
-    /**
-       * Connect to the cadet service, specifying subscriptions
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT:
-      t = "LOCAL_CONNECT";
-      break;
-
-      /**
-       * Ask the cadet service to create a new tunnel
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-      t = "CHANNEL_CREATE";
-      break;
-
-      /**
-       * Ask the cadet service to destroy a tunnel
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-      t = "CHANNEL_DESTROY";
-      break;
-
-      /**
-       * Confirm the creation of a channel.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-      t = "CHANNEL_ACK";
-      break;
-
-      /**
-       * Confirm the creation of a channel.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      t = "CHANNEL_NACK";
-      break;
-
-      /**
-       * Encrypted payload.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-      t = "ENCRYPTED";
-      break;
-
-      /**
-       * Local payload traffic
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA:
-      t = "LOCAL_DATA";
-      break;
-
-      /**
-       * Local ACK for data.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK:
-      t = "LOCAL_ACK";
-      break;
-
-      /**
-       * Local monitoring of channels.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
-      t = "LOCAL_INFO_CHANNELS";
-      break;
-
-      /**
-       * Local monitoring of a channel.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
-      t = "LOCAL_INFO_CHANNEL";
-      break;
-
-      /**
-       * Local monitoring of service.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
-      t = "LOCAL_INFO_TUNNELS";
-      break;
-
-      /**
-       * Local monitoring of service.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
-      t = "LOCAL_INFO_TUNNEL";
-      break;
-
-      /**
-       * Local information about all connections of service.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTIONS:
-      t = "LOCAL_INFO_CONNECTIONS";
-      break;
-
-      /**
-       * Local information of service about a specific connection.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTION:
-      t = "LOCAL_INFO_CONNECTION";
-      break;
-
-      /**
-       * Local information about all peers known to the service.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
-      t = "LOCAL_INFO_PEERS";
-      break;
-
-      /**
-       * Local information of service about a specific peer.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
-      t = "LOCAL_INFO_PEER";
-      break;
-
-      /**
-       * Traffic (net-cat style) used by the Command Line Interface.
-       */
-    case GNUNET_MESSAGE_TYPE_CADET_CLI:
-      t = "CLI";
-      break;
-
-      /**
-       * 640kb should be enough for everybody
-       */
-    case 299:
-      t = "RESERVE_END";
-      break;
-
-    default:
-      sprintf(buf, "%u (UNKNOWN TYPE)", m);
-      return buf;
-  }
-  sprintf(buf, "{%18s}", t);
-  return buf;
-}
-#else
-const char *
-GM_m2s (uint16_t m)
-{
-  return "";
-}
-#endif

Deleted: gnunet/src/mesh/cadet_path.c
===================================================================
--- gnunet/src/mesh/cadet_path.c        2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_path.c        2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,213 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/cadet_path.c
- * @brief Path handling functions
- * @author Bartlomiej Polot
- */
-
-#include "cadet.h"
-#include "cadet_path.h"
-#include "gnunet-service-cadet_peer.h"
-
-/**
- * @brief Destroy a path after some time has past.
- *
- * If the path is returned from DHT again after a while, try again.
- *
- * @param cls Closure (path to destroy).
- * @param tc Task context.
- */
-static void
-path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetPeerPath *path = cls;
-  struct CadetPeer *peer;
-
-  path->path_delete = GNUNET_SCHEDULER_NO_TASK;
-  peer = GMP_get_short (path->peers[path->length - 1]);
-  GMP_remove_path (peer, path);
-}
-
-
-/**
- * Create a new path
- *
- * @param length How many hops will the path have.
- *
- * @return A newly allocated path with a peer array of the specified length.
- */
-struct CadetPeerPath *
-path_new (unsigned int length)
-{
-  struct CadetPeerPath *p;
-
-  p = GNUNET_new (struct CadetPeerPath);
-  if (length > 0)
-  {
-    p->length = length;
-    p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id));
-  }
-  return p;
-}
-
-
-/**
- * Invert the path
- *
- * @param path the path to invert
- */
-void
-path_invert (struct CadetPeerPath *path)
-{
-  GNUNET_PEER_Id aux;
-  unsigned int i;
-
-  for (i = 0; i < path->length / 2; i++)
-  {
-    aux = path->peers[i];
-    path->peers[i] = path->peers[path->length - i - 1];
-    path->peers[path->length - i - 1] = aux;
-  }
-}
-
-
-/**
- * Duplicate a path, incrementing short peer's rc.
- *
- * @param path The path to duplicate.
- */
-struct CadetPeerPath *
-path_duplicate (const struct CadetPeerPath *path)
-{
-  struct CadetPeerPath *aux;
-  unsigned int i;
-
-  aux = path_new (path->length);
-  memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id));
-  for (i = 0; i < aux->length; i++)
-    GNUNET_PEER_change_rc (aux->peers[i], 1);
-  return aux;
-}
-
-
-/**
- * Get the length of a path.
- *
- * @param path The path to measure, with the local peer at any point of it.
- *
- * @return Number of hops to reach destination.
- *         UINT_MAX in case the peer is not in the path.
- */
-unsigned int
-path_get_length (struct CadetPeerPath *path)
-{
-  if (NULL == path)
-    return UINT_MAX;
-  return path->length;
-}
-
-
-
-/**
- * Mark path as invalid: keep it aroud for a while to avoid trying it in a 
loop.
- *
- * DHT_get sometimes returns bad cached results, for instance, on a locally
- * cached result where the PUT followed a path that is no longer current.
- *
- * @param p Path to invalidate.
- */
-void
-path_invalidate (struct CadetPeerPath *p)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
-    return;
-
-  p->path_delete = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
-                                                 &path_destroy_delayed, p);
-}
-
-
-/**
- * Test if a path is valid (or at least not known to be invalid).
- *
- * @param path Path to test.
- *
- * @return #GNUNET_YES If the path is valid or unknown,
- *         #GNUNET_NO If the path is known to be invalid.
- */
-int
-path_is_valid (const struct CadetPeerPath *path)
-{
-  return (GNUNET_SCHEDULER_NO_TASK == path->path_delete);
-}
-
-
-/**
- * Destroy the path and free any allocated resources linked to it
- *
- * @param p the path to destroy
- *
- * @return GNUNET_OK on success
- */
-int
-path_destroy (struct CadetPeerPath *p)
-{
-  if (NULL == p)
-    return GNUNET_OK;
-
-  GNUNET_PEER_decrement_rcs (p->peers, p->length);
-  GNUNET_free_non_null (p->peers);
-  if (GNUNET_SCHEDULER_NO_TASK != p->path_delete)
-    GNUNET_SCHEDULER_cancel (p->path_delete);
-  GNUNET_free (p);
-  return GNUNET_OK;
-}
-
-char *
-path_2s (struct CadetPeerPath *p)
-{
-  char *s;
-  char *old;
-  unsigned int i;
-
-  old = GNUNET_strdup ("");
-  for (i = 0; i < p->length; i++)
-  {
-    GNUNET_asprintf (&s, "%s %s",
-                     old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
-    GNUNET_free_non_null (old);
-    old = s;
-  }
-  return s;
-}
-
-void
-path_debug (struct CadetPeerPath *p)
-{
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n");
-  for (i = 0; i < p->length; i++)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %s\n",
-                GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i])));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n");
-}

Deleted: gnunet/src/mesh/cadet_path.h
===================================================================
--- gnunet/src/mesh/cadet_path.h        2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_path.h        2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,185 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/cadet_path.h
- * @brief Path handling functions
- * @author Bartlomiej Polot
- */
-
-#include "gnunet-service-cadet_connection.h"
-
-#ifndef CADET_PATH_H_
-#define CADET_PATH_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-  #if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/**
- * Information regarding a possible path to reach a single peer
- */
-struct CadetPeerPath
-{
-
-    /**
-     * Linked list
-     */
-  struct CadetPeerPath *next;
-  struct CadetPeerPath *prev;
-
-    /**
-     * List of all the peers that form the path from origin to target.
-     */
-  GNUNET_PEER_Id *peers;
-
-    /**
-     * Number of peers (hops) in the path
-     */
-  unsigned int length;
-
-    /**
-     * User defined data store.
-     */
-  struct CadetConnection *c;
-
-    /**
-     * Path's score, how reliable is the path.
-     */
-//   int score;
-
-  /**
-   * Task to delete the path.
-   * We tried it, it didn't work, don't try again in a while.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier path_delete;
-
-};
-
-/******************************************************************************/
-/*************************        FUNCTIONS       
*****************************/
-/******************************************************************************/
-
-/**
- * Create a new path.
- *
- * @param length How many hops will the path have.
- *
- * @return A newly allocated path with a peer array of the specified length.
- */
-struct CadetPeerPath *
-path_new (unsigned int length);
-
-
-/**
- * Invert the path.
- *
- * @param path The path to invert.
- */
-void
-path_invert (struct CadetPeerPath *path);
-
-
-/**
- * Duplicate a path, incrementing short peer's rc.
- *
- * @param path The path to duplicate.
- */
-struct CadetPeerPath *
-path_duplicate (const struct CadetPeerPath *path);
-
-
-/**
- * Get the length of a path.
- *
- * @param path The path to measure, with the local peer at any point of it.
- *
- * @return Number of hops to reach destination.
- *         UINT_MAX in case the peer is not in the path.
- */
-unsigned int
-path_get_length (struct CadetPeerPath *path);
-
-/**
- * Mark path as invalid: keep it aroud for a while to avoid trying it in a 
loop.
- *
- * DHT_get sometimes returns bad cached results, for instance, on a locally
- * cached result where the PUT followed a path that is no longer current.
- *
- * @param p Path to invalidate.
- */
-void
-path_invalidate (struct CadetPeerPath *p);
-
-/**
- * Test if a path is valid (or at least not known to be invalid).
- *
- * @param path Path to test.
- *
- * @return #GNUNET_YES If the path is valid or unknown,
- *         #GNUNET_NO If the path is known to be invalid.
- */
-int
-path_is_valid (const struct CadetPeerPath *path);
-
-/**
- * Destroy the path and free any allocated resources linked to it
- *
- * @param p the path to destroy
- *
- * @return GNUNET_OK on success
- */
-int
-path_destroy (struct CadetPeerPath *p);
-
-/**
- * Path -> allocated one line string. Caller must free.
- *
- * @param p Path.
- */
-char *
-path_2s (struct CadetPeerPath *p);
-
-/**
- * Print info about the path for debug.
- *
- * @param p Path to debug.
- */
-void
-path_debug (struct CadetPeerPath *p);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-  #endif
-  #ifdef __cplusplus
-}
-#endif
-
-
-/* ifndef CADET_PATH_H */
-#endif

Deleted: gnunet/src/mesh/cadet_protocol.h
===================================================================
--- gnunet/src/mesh/cadet_protocol.h    2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_protocol.h    2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,459 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @author Bartlomiej Polot
- * @file cadet/cadet_protocol.h
- */
-
-#ifndef CADET_PROTOCOL_H_
-#define CADET_PROTOCOL_H_
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "cadet.h"
-
-#ifdef __cplusplus
-
-struct GNUNET_CADET_TunnelMessage;
-extern "C"
-{
-#if 0
-  /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-/******************************************************************************/
-/********************      CADET NETWORK MESSAGES     
**************************/
-/******************************************************************************/
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Message for cadet connection creation.
- */
-struct GNUNET_CADET_ConnectionCreate
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
-     *
-     * Size: sizeof (struct GNUNET_CADET_ConnectionCreate) +
-     *       path_length * sizeof (struct GNUNET_PeerIdentity)
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the connection
-     */
-  struct GNUNET_CADET_Hash cid;
-
-    /**
-     * path_length structs defining the *whole* path from the origin [0] to the
-     * final destination [path_length-1].
-     */
-  /* struct GNUNET_PeerIdentity peers[path_length]; */
-};
-
-/**
- * Message for ack'ing a connection
- */
-struct GNUNET_CADET_ConnectionACK
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the connection.
-     */
-  struct GNUNET_CADET_Hash cid;
-
-};
-
-
-/**
- * Message for encapsulation of a Key eXchange message in a connection.
- */
-struct GNUNET_CADET_KX
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_KX.
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the connection.
-     */
-  struct GNUNET_CADET_Hash cid;
-
-  /* Specific KX message follows. */
-};
-
-
-/**
- * Message transmitted with the signed ephemeral key of a peer.  The
- * session key is then derived from the two ephemeral keys (ECDHE).
- *
- * As far as possible, same as CORE's EphemeralKeyMessage.
- */
-struct GNUNET_CADET_KX_Ephemeral
-{
-
-  /**
-   * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Status of the sender (should be in "enum PeerStateMachine"), nbo.
-   */
-  int32_t sender_status GNUNET_PACKED;
-
-  /**
-   * An ECC signature of the 'origin' asserting the validity of
-   * the given ephemeral key.
-   */
-  struct GNUNET_CRYPTO_EddsaSignature signature;
-
-  /**
-   * Information about what is being signed.
-   */
-  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
-
-  /**
-   * At what time was this key created (beginning of validity).
-   */
-  struct GNUNET_TIME_AbsoluteNBO creation_time;
-
-  /**
-   * When does the given ephemeral key expire (end of validity).
-   */
-  struct GNUNET_TIME_AbsoluteNBO expiration_time;
-
-  /**
-   * Ephemeral public ECC key (always for NIST P-521) encoded in a format 
suitable
-   * for network transmission as created using 'gcry_sexp_sprint'.
-   */
-  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
-
-  /**
-   * Public key of the signing peer (persistent version, not the ephemeral 
public key).
-   */
-  struct GNUNET_PeerIdentity origin_identity;
-};
-
-
-/**
- * We're sending an (encrypted) PING to the other peer to check if he
- * can decrypt.  The other peer should respond with a PONG with the
- * same content, except this time encrypted with the receiver's key.
- */
-struct GNUNET_CADET_KX_Ping
-{
-  /**
-   * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_PING.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Seed for the IV
-   */
-  uint32_t iv GNUNET_PACKED;
-
-  /**
-   * Intended target of the PING, used primarily to check
-   * that decryption actually worked.
-   */
-  struct GNUNET_PeerIdentity target;
-
-  /**
-   * Random number chosen to make reply harder.
-   */
-  uint32_t nonce GNUNET_PACKED;
-};
-
-
-/**
- * Response to a PING.  Includes data from the original PING.
- */
-struct GNUNET_CADET_KX_Pong
-{
-  /**
-   * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_PONG.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Seed for the IV
-   */
-  uint32_t iv GNUNET_PACKED;
-
-  /**
-   * Same nonce as in the reve.
-   */
-  uint32_t nonce GNUNET_PACKED;
-};
-
-
-/**
- * Tunnel(ed) message.
- */
-struct GNUNET_CADET_Encrypted
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the connection.
-   */
-  struct GNUNET_CADET_Hash cid;
-
-  /**
-   * ID of the packet (hop by hop).
-   */
-  uint32_t pid GNUNET_PACKED;
-
-  /**
-   * Number of hops to live.
-   */
-  uint32_t ttl GNUNET_PACKED;
-
-  /**
-   * Initialization Vector for payload encryption.
-   */
-  uint32_t iv GNUNET_PACKED;
-
-  /**
-   * MAC of the encrypted message, used to verify message integrity.
-   * Everything after this value  will be encrypted and authenticated.
-   */
-  struct GNUNET_CADET_Hash hmac;
-
-  /**
-   * Encrypted content follows.
-   */
-};
-
-
-/**
- * Message to create a Channel.
- */
-struct GNUNET_CADET_ChannelCreate
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the channel
-   */
-  CADET_ChannelNumber chid GNUNET_PACKED;
-
-  /**
-   * Destination port.
-   */
-  uint32_t port GNUNET_PACKED;
-
-  /**
-   * Channel options.
-   */
-  uint32_t opt GNUNET_PACKED;
-};
-
-
-/**
- * Message to manage a Channel (ACK, NACK, Destroy).
- */
-struct GNUNET_CADET_ChannelManage
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_{ACK|NACK|DESTROY}
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the channel
-   */
-  CADET_ChannelNumber chid GNUNET_PACKED;
-};
-
-
-/**
- * Message for cadet data traffic.
- */
-struct GNUNET_CADET_Data
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_UNICAST,
-     *       GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * Unique ID of the payload message
-     */
-  uint32_t mid GNUNET_PACKED;
-
-    /**
-     * ID of the channel
-     */
-  CADET_ChannelNumber chid GNUNET_PACKED;
-
-    /**
-     * Payload follows
-     */
-};
-
-
-/**
- * Message to acknowledge end-to-end data.
- */
-struct GNUNET_CADET_DataACK
-{
-  /**
-   * Type: GNUNET_MESSAGE_TYPE_CADET_DATA_ACK
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * ID of the channel
-   */
-  CADET_ChannelNumber chid GNUNET_PACKED;
-
-  /**
-   * Bitfield of already-received newer messages
-   * pid +  1 @ LSB
-   * pid + 64 @ MSB
-   */
-  uint64_t futures GNUNET_PACKED;
-
-  /**
-   * Last message ID received.
-   */
-  uint32_t mid GNUNET_PACKED;
-};
-
-
-/**
- * Message to acknowledge cadet encrypted traffic.
- */
-struct GNUNET_CADET_ACK
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_ACK
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * Maximum packet ID authorized.
-     */
-  uint32_t ack GNUNET_PACKED;
-
-    /**
-     * ID of the connection.
-     */
-  struct GNUNET_CADET_Hash cid;
-};
-
-
-/**
- * Message to query a peer about its Flow Control status regarding a tunnel.
- */
-struct GNUNET_CADET_Poll
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_POLL
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * Last packet sent.
-     */
-  uint32_t pid GNUNET_PACKED;
-
-    /**
-     * ID of the connection.
-     */
-  struct GNUNET_CADET_Hash cid;
-
-};
-
-
-/**
- * Message for notifying a disconnection in a path
- */
-struct GNUNET_CADET_ConnectionBroken
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the connection.
-     */
-  struct GNUNET_CADET_Hash cid;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer1;
-
-    /**
-     * ID of the endpoint
-     */
-  struct GNUNET_PeerIdentity peer2;
-};
-
-
-/**
- * Message to destroy a connection.
- */
-struct GNUNET_CADET_ConnectionDestroy
-{
-    /**
-     * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
-     */
-  struct GNUNET_MessageHeader header;
-
-    /**
-     * ID of the connection.
-     */
-  struct GNUNET_CADET_Hash cid;
-};
-
-
-GNUNET_NETWORK_STRUCT_END
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef CADET_PROTOCOL_H */
-#endif
-/* end of cadet_protocol.h */

Deleted: gnunet/src/mesh/cadet_test_lib.c
===================================================================
--- gnunet/src/mesh/cadet_test_lib.c    2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_test_lib.c    2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,295 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file cadet/cadet_test_lib.c
- * @author Bartlomiej Polot
- * @brief library for writing CADET tests
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "cadet_test_lib.h"
-#include "gnunet_cadet_service.h"
-
-/**
- * Test context for a CADET Test.
- */
-struct GNUNET_CADET_TEST_Context
-{
-  /**
-   * Array of running peers.
-   */
-  struct GNUNET_TESTBED_Peer **peers;
-
-  /**
-   * Array of handles to the CADET for each peer.
-   */
-  struct GNUNET_CADET_Handle **cadetes;
-
-  /**
-   * Operation associated with the connection to the CADET.
-   */
-  struct GNUNET_TESTBED_Operation **ops;
-
-  /**
-   * Main function of the test to run once all CADETs are available.
-   */
-  GNUNET_CADET_TEST_AppMain app_main;
-
-  /**
-   * Closure for 'app_main'.
-   */
-  void *app_main_cls;
-
-  /**
-   * Number of peers running, size of the arrays above.
-   */
-  unsigned int num_peers;
-
-  /**
-   * Handler for incoming tunnels.
-   */
-  GNUNET_CADET_InboundChannelNotificationHandler *new_channel;
-
-  /**
-   * Cleaner for destroyed incoming tunnels.
-   */
-  GNUNET_CADET_ChannelEndHandler *cleaner;
-
-  /**
-   * Message handlers.
-   */
-  struct GNUNET_CADET_MessageHandler* handlers;
-
-  /**
-   * Application ports.
-   */
-  const uint32_t *ports;
-
-};
-
-
-/**
- * Context for a cadet adapter callback.
- */
-struct GNUNET_CADET_TEST_AdapterContext
-{
-  /**
-   * Peer number for the particular peer.
-   */
-  unsigned int peer;
-
-  /**
-   * General context.
-   */
-  struct GNUNET_CADET_TEST_Context *ctx;
-};
-
-
-/**
- * Adapter function called to establish a connection to
- * the CADET service.
- *
- * @param cls closure
- * @param cfg configuration of the peer to connect to; will be available until
- *          GNUNET_TESTBED_operation_done() is called on the operation returned
- *          from GNUNET_TESTBED_service_connect()
- * @return service handle to return in 'op_result', NULL on error
- */
-static void *
-cadet_connect_adapter (void *cls,
-                      const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
-  struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
-  struct GNUNET_CADET_Handle *h;
-
-  h = GNUNET_CADET_connect (cfg,
-                           (void *) (long) actx->peer,
-                           ctx->new_channel,
-                           ctx->cleaner,
-                           ctx->handlers,
-                           ctx->ports);
-  return h;
-}
-
-
-/**
- * Adapter function called to destroy a connection to
- * the CADET service.
- *
- * @param cls closure
- * @param op_result service handle returned from the connect adapter
- */
-static void
-cadet_disconnect_adapter (void *cls,
-                         void *op_result)
-{
-  struct GNUNET_CADET_Handle *cadet = op_result;
-  struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
-
-  GNUNET_free (actx);
-  GNUNET_CADET_disconnect (cadet);
-}
-
-
-/**
- * Callback to be called when a service connect operation is completed.
- *
- * @param cls The callback closure from functions generating an operation.
- * @param op The operation that has been finished.
- * @param ca_result The service handle returned from
- *                  GNUNET_TESTBED_ConnectAdapter() (cadet handle).
- * @param emsg Error message in case the operation has failed.
- *             NULL if operation has executed successfully.
- */
-static void
-cadet_connect_cb (void *cls,
-                 struct GNUNET_TESTBED_Operation *op,
-                 void *ca_result,
-                 const char *emsg)
-{
-  struct GNUNET_CADET_TEST_Context *ctx = cls;
-  unsigned int i;
-
-  if (NULL != emsg)
-  {
-    fprintf (stderr, "Failed to connect to CADET service: %s\n",
-             emsg);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  for (i = 0; i < ctx->num_peers; i++)
-    if (op == ctx->ops[i])
-    {
-      ctx->cadetes[i] = ca_result;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i);
-    }
-  for (i = 0; i < ctx->num_peers; i++)
-    if (NULL == ctx->cadetes[i])
-      return; /* still some CADET connections missing */
-  /* all CADET connections ready! */
-  ctx->app_main (ctx->app_main_cls,
-                 ctx,
-                 ctx->num_peers,
-                 ctx->peers,
-                 ctx->cadetes);
-}
-
-
-void
-GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
-{
-  unsigned int i;
-
-  for (i = 0; i < ctx->num_peers; i++)
-  {
-    GNUNET_assert (NULL != ctx->ops[i]);
-    GNUNET_TESTBED_operation_done (ctx->ops[i]);
-    ctx->ops[i] = NULL;
-  }
-  GNUNET_free (ctx->ops);
-  GNUNET_free (ctx->cadetes);
-  GNUNET_free (ctx);
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Callback run when the testbed is ready (peers running and connected to
- * each other)
- *
- * @param cls Closure (context).
- * @param h the run handle
- * @param num_peers Number of peers that are running.
- * @param peers Handles to each one of the @c num_peers peers.
- * @param links_succeeded the number of overlay link connection attempts that
- *          succeeded
- * @param links_failed the number of overlay link connection attempts that
- *          failed
- */
-static void
-cadet_test_run (void *cls,
-               struct GNUNET_TESTBED_RunHandle *h,
-               unsigned int num_peers,
-               struct GNUNET_TESTBED_Peer **peers,
-               unsigned int links_succeeded,
-               unsigned int links_failed)
-{
-  struct GNUNET_CADET_TEST_Context *ctx = cls;
-  unsigned int i;
-
-  if  (num_peers != ctx->num_peers)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n",
-                num_peers, ctx->num_peers);
-    exit (1);
-  }
-  ctx->peers = peers;
-  for (i = 0; i < num_peers; i++)
-  {
-    struct GNUNET_CADET_TEST_AdapterContext *newctx;
-    newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
-    newctx->peer = i;
-    newctx->ctx = ctx;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i);
-    ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
-                                                  peers[i],
-                                                  "cadet",
-                                                  &cadet_connect_cb,
-                                                  ctx,
-                                                  &cadet_connect_adapter,
-                                                  &cadet_disconnect_adapter,
-                                                  newctx);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]);
-  }
-}
-
-
-void
-GNUNET_CADET_TEST_run (const char *testname,
-                      const char *cfgname,
-                      unsigned int num_peers,
-                      GNUNET_CADET_TEST_AppMain tmain,
-                      void *tmain_cls,
-                      GNUNET_CADET_InboundChannelNotificationHandler 
new_channel,
-                      GNUNET_CADET_ChannelEndHandler cleaner,
-                      struct GNUNET_CADET_MessageHandler* handlers,
-                      const uint32_t *ports)
-{
-  struct GNUNET_CADET_TEST_Context *ctx;
-
-  ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
-  ctx->num_peers = num_peers;
-  ctx->ops = GNUNET_malloc (num_peers * sizeof (struct 
GNUNET_TESTBED_Operation *));
-  ctx->cadetes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_CADET_Handle 
*));
-  ctx->app_main = tmain;
-  ctx->app_main_cls = tmain_cls;
-  ctx->new_channel = new_channel;
-  ctx->cleaner = cleaner;
-  ctx->handlers = handlers;
-  ctx->ports = ports;
-  GNUNET_TESTBED_test_run (testname,
-                           cfgname,
-                           num_peers,
-                           0LL, NULL, NULL,
-                           &cadet_test_run, ctx);
-}
-
-/* end of cadet_test_lib.c */

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

Deleted: gnunet/src/mesh/cadet_tunnel_tree.c
===================================================================
--- gnunet/src/mesh/cadet_tunnel_tree.c 2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_tunnel_tree.c 2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,1174 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/cadet_tunnel_tree.c
- * @brief Tunnel tree handling functions
- * @author Bartlomiej Polot
- */
-
-#include "cadet.h"
-#include "cadet_tunnel_tree.h"
-
-#define CADET_TREE_DEBUG GNUNET_YES
-
-
-/**
- * Node of path tree for a tunnel
- */
-struct CadetTunnelTreeNode
-{
-  /**
-   * Peer this node describes
-   */
-  GNUNET_PEER_Id peer;
-
-  /**
-   * Parent node in the tree
-   */
-  struct CadetTunnelTreeNode *parent;
-
-  /**
-   * DLL of siblings
-   */
-  struct CadetTunnelTreeNode *next;
-
-  /**
-   * DLL of siblings
-   */
-  struct CadetTunnelTreeNode *prev;
-
-  /**
-   * DLL of children
-   */
-  struct CadetTunnelTreeNode *children_head;
-
-  /**
-   * DLL of children
-   */
-  struct CadetTunnelTreeNode *children_tail;
-
-    /**
-     * Status of the peer in the tunnel
-     */
-  enum CadetPeerState status;
-};
-
-
-/**
- * Tree to reach all peers in the tunnel
- */
-struct CadetTunnelTree
-{
-  /**
-   * Root node of peer tree
-   */
-  struct CadetTunnelTreeNode *root;
-
-  /**
-   * Node that represents our position in the tree (for non local tunnels)
-   */
-  struct CadetTunnelTreeNode *me;
-
-  /**
-   * DLL of disconneted nodes
-   */
-  struct CadetTunnelTreeNode *disconnected_head;
-
-  /**
-   * DLL of disconneted nodes
-   */
-  struct CadetTunnelTreeNode *disconnected_tail;
-
-  /**
-   * Cache of all peers and the first hop to them.
-   * Indexed by PeerIdentity, contains a pointer to the PeerIdentity
-   * of 1st hop.
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *first_hops;
-
-};
-
-
-/**
- * Create a new path
- *
- * @param length How many hops will the path have.
- *
- * @return A newly allocated path with a peer array of the specified length.
- */
-struct CadetPeerPath *
-path_new (unsigned int length)
-{
-  struct CadetPeerPath *p;
-
-  p = GNUNET_new (struct CadetPeerPath);
-  if (length > 0)
-  {
-    p->length = length;
-    p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id));
-  }
-  return p;
-}
-
-
-/**
- * Invert the path
- *
- * @param path the path to invert
- */
-void
-path_invert (struct CadetPeerPath *path)
-{
-  GNUNET_PEER_Id aux;
-  unsigned int i;
-
-  for (i = 0; i < path->length / 2; i++)
-  {
-    aux = path->peers[i];
-    path->peers[i] = path->peers[path->length - i - 1];
-    path->peers[path->length - i - 1] = aux;
-  }
-}
-
-
-/**
- * Duplicate a path, incrementing short peer's rc.
- *
- * @param path The path to duplicate.
- */
-struct CadetPeerPath *
-path_duplicate (struct CadetPeerPath *path)
-{
-  struct CadetPeerPath *aux;
-  unsigned int i;
-
-  aux = path_new (path->length);
-  memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id));
-  for (i = 0; i < path->length; i++)
-    GNUNET_PEER_change_rc (path->peers[i], 1);
-  return aux;
-}
-
-
-/**
- * Recusively update the info about what is the first hop to reach the node
- *
- * @param tree Tree this nodes belongs to.
- * @param parent The node form which to start updating.
- * @param hop If known, ID of the first hop.
- *            If not known, NULL to find out and pass on children.
- */
-static void
-tree_node_update_first_hops (struct CadetTunnelTree *tree,
-                             struct CadetTunnelTreeNode *parent,
-                             struct GNUNET_PeerIdentity *hop);
-
-
-/**
- * Get the length of a path.
- *
- * @param path The path to measure, with the local peer at any point of it.
- *
- * @return Number of hops to reach destination.
- *         UINT_MAX in case the peer is not in the path.
- */
-unsigned int
-path_get_length (struct CadetPeerPath *path)
-{
-  if (NULL == path)
-    return UINT_MAX;
-  return path->length;
-}
-
-
-/**
- * Destroy the path and free any allocated resources linked to it
- *
- * @param p the path to destroy
- *
- * @return GNUNET_OK on success
- */
-int
-path_destroy (struct CadetPeerPath *p)
-{
-  if (NULL == p)
-    return GNUNET_OK;
-  GNUNET_PEER_decrement_rcs (p->peers, p->length);
-  GNUNET_free_non_null (p->peers);
-  GNUNET_free (p);
-  return GNUNET_OK;
-}
-
-
-
-/**
- * Allocates and initializes a new node.
- * Sets ID and parent of the new node and inserts it in the DLL of the parent
- *
- * @param parent Node that will be the parent from the new node, NULL for root
- * @param peer Short Id of the new node
- *
- * @return Newly allocated node
- */
-static struct CadetTunnelTreeNode *
-tree_node_new (struct CadetTunnelTreeNode *parent, GNUNET_PEER_Id peer)
-{
-  struct CadetTunnelTreeNode *node;
-
-  node = GNUNET_new (struct CadetTunnelTreeNode);
-  node->peer = peer;
-  GNUNET_PEER_change_rc (peer, 1);
-  node->parent = parent;
-  if (NULL != parent)
-    GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail,
-                                 node);
-
-  return node;
-}
-
-
-/**
- * Recursively find the given peer.
- *
- * @param parent Node where to start looking.
- * @param peer_id Short ID of the peer to find.
- *
- * @return Pointer to the node of the peer. NULL if not found.
- */
-static struct CadetTunnelTreeNode *
-tree_node_find_peer (struct CadetTunnelTreeNode *parent, GNUNET_PEER_Id 
peer_id)
-{
-  struct CadetTunnelTreeNode *n;
-  struct CadetTunnelTreeNode *r;
-
-  if (parent->peer == peer_id)
-    return parent;
-  for (n = parent->children_head; NULL != n; n = n->next)
-  {
-    r = tree_node_find_peer (n, peer_id);
-    if (NULL != r)
-      return r;
-  }
-  return NULL;
-}
-
-
-/**
- * Recusively update the info about what is the first hop to reach the node
- *
- * @param tree Tree this nodes belongs to.
- * @param parent ID from node form which to start updating.
- * @param hop If known, ID of the first hop.
- *            If not known, NULL to find out and pass on children.
- */
-static void
-tree_node_update_first_hops (struct CadetTunnelTree *tree,
-                             struct CadetTunnelTreeNode *parent,
-                             struct GNUNET_PeerIdentity *hop)
-{
-  struct GNUNET_PeerIdentity pi;
-  struct GNUNET_PeerIdentity *copy;
-  struct GNUNET_PeerIdentity id;
-  struct CadetTunnelTreeNode *n;
-
-#if CADET_TREE_DEBUG
-  GNUNET_PEER_resolve (parent->peer, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Finding first hop for %s.\n",
-              GNUNET_i2s (&id));
-#endif
-  if (NULL == hop)
-  {
-    struct CadetTunnelTreeNode *aux;
-    struct CadetTunnelTreeNode *old;
-
-    aux = old = parent;
-    while (aux != tree->me)
-    {
-#if CADET_TREE_DEBUG
-      GNUNET_PEER_resolve (aux->peer, &id);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   ... checking %s.\n",
-                  GNUNET_i2s (&id));
-#endif
-      old = aux;
-      aux = aux->parent;
-      GNUNET_assert (NULL != aux);
-    }
-#if CADET_TREE_DEBUG
-    GNUNET_PEER_resolve (old->peer, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   It's %s!\n",
-                GNUNET_i2s (&id));
-#endif
-    hop = &pi;
-    GNUNET_PEER_resolve (old->peer, hop);
-  }
-  GNUNET_PEER_resolve (parent->peer, &id);
-  copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
-  if (NULL == copy)
-    copy = GNUNET_new (struct GNUNET_PeerIdentity);
-  *copy = *hop;
-
-  (void) GNUNET_CONTAINER_multihashmap_put (tree->first_hops, &id.hashPubKey,
-                                            copy,
-                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
-  for (n = parent->children_head; NULL != n; n = n->next)
-  {
-    tree_node_update_first_hops (tree, n, hop);
-  }
-}
-
-
-static void
-tree_node_debug (struct CadetTunnelTreeNode *n, uint16_t level)
-{
-  struct CadetTunnelTreeNode *c;
-  struct GNUNET_PeerIdentity id;;
-  uint16_t i;
-
-  for (i = 0; i < level; i++)
-    FPRINTF (stderr, "%s",  "  ");
-  if (n->status == CADET_PEER_READY)
-    FPRINTF (stderr, "%s",  "#");
-  if (n->status == CADET_PEER_SEARCHING)
-    FPRINTF (stderr, "%s",  "+");
-  if (n->status == CADET_PEER_RELAY)
-    FPRINTF (stderr, "%s",  "-");
-  if (n->status == CADET_PEER_RECONNECTING)
-    FPRINTF (stderr, "%s",  "*");
-
-  GNUNET_PEER_resolve (n->peer, &id);
-  FPRINTF (stderr, "%s, [%u, %p] ", GNUNET_i2s (&id), n->peer, n);
-  if (NULL != n->parent)
-  {
-    GNUNET_PEER_resolve (n->parent->peer, &id);
-    FPRINTF (stderr, "(-> %s [%u])\n", GNUNET_i2s (&id), n->parent->peer);
-  }
-  else
-    FPRINTF (stderr, "%s",  "(root)\n");
-  for (c = n->children_head; NULL != c; c = c->next)
-    tree_node_debug (c, level + 1);
-}
-
-
-/**
- * Destroys and frees the node and all children
- *
- * @param parent Parent node to be destroyed
- */
-static void
-tree_node_destroy (struct CadetTunnelTreeNode *parent)
-{
-  struct CadetTunnelTreeNode *n;
-  struct CadetTunnelTreeNode *next;
-
-  if (NULL == parent)
-    return;
-#if CADET_TREE_DEBUG
-  struct GNUNET_PeerIdentity id;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying node %u\n",
-              parent->peer);
-  GNUNET_PEER_resolve (parent->peer, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   (%s)\n", GNUNET_i2s (&id));
-#endif
-  n = parent->children_head;
-  while (NULL != n)
-  {
-    next = n->next;
-    tree_node_destroy (n);
-    n = next;
-  }
-  GNUNET_PEER_change_rc (parent->peer, -1);
-  if (NULL != parent->parent)
-    GNUNET_CONTAINER_DLL_remove (parent->parent->children_head,
-                                 parent->parent->children_tail, parent);
-  GNUNET_free (parent);
-}
-
-
-
-/**
- * Create a new tree.
- *
- * @param peer A short peer id of the root of the tree.
- *
- * @return A newly allocated and initialized tunnel tree.
- */
-struct CadetTunnelTree *
-tree_new (GNUNET_PEER_Id peer)
-{
-  struct CadetTunnelTree *tree;
-
-  tree = GNUNET_new (struct CadetTunnelTree);
-  tree->first_hops = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
-  tree->root = tree_node_new (NULL, peer);
-  tree->root->status = CADET_PEER_ROOT;
-
-  if (1 == peer)
-  {
-    tree->me = tree->root;
-  }
-
-  return tree;
-}
-
-
-/**
- * Set the status of a node.
- *
- * @param tree Tree.
- * @param peer A short peer id of the node.
- * @param status New status to set.
- */
-void
-tree_set_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer,
-                 enum CadetPeerState status)
-{
-  struct CadetTunnelTreeNode *n;
-
-  n = tree_find_peer (tree, peer);
-  if (NULL == n)
-    return;
-  n->status = status;
-}
-
-
-/**
- * Get the status of a node.
- *
- * @param tree Tree whose node's status we want to now.
- * @param peer A short peer id of the node.
- *
- * @return Status of the peer.
- */
-enum CadetPeerState
-tree_get_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer)
-{
-  struct CadetTunnelTreeNode *n;
-
-  n = tree_find_peer (tree, peer);
-  if (NULL == n)
-    return CADET_PEER_INVALID;
-  return n->status;
-}
-
-
-/**
- * Get the id of the predecessor of the local node.
- *
- * @param tree Tree whose local id we want to now.
- *
- * @return Short peer id of local peer.
- */
-GNUNET_PEER_Id
-tree_get_predecessor (struct CadetTunnelTree *tree)
-{
-  if (NULL != tree->me && NULL != tree->me->parent)
-    return tree->me->parent->peer;
-  else
-    return (GNUNET_PEER_Id) 0;
-}
-
-
-/**
- * Find the first peer whom to send a packet to go down this path
- *
- * @param t The tunnel tree to use
- * @param peer The peerinfo of the peer we are trying to reach
- *
- * @return peerinfo of the peer who is the first hop in the tunnel
- *         NULL on error
- *
- * FIXME use PEER_Id
- */
-struct GNUNET_PeerIdentity *
-tree_get_first_hop (struct CadetTunnelTree *t, GNUNET_PEER_Id peer)
-{
-  struct GNUNET_PeerIdentity id;
-  struct GNUNET_PeerIdentity *r;
-
-  GNUNET_PEER_resolve (peer, &id);
-  r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
-  if (NULL == r)
-  {
-    struct CadetTunnelTreeNode *n;
-
-    n = tree_find_peer (t, peer);
-    if (NULL != t->me && NULL != n)
-    {
-      tree_node_update_first_hops (t, n, NULL);
-      r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
-      GNUNET_assert (NULL != r);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Tree structure inconsistent! me: %p, n: %p", t->me, n);
-      GNUNET_break (0);
-    }
-  }
-
-  return r;
-}
-
-
-/**
- * Find the given peer in the tree.
- *
- * @param tree Tree where to look for the peer.
- * @param peer_id Short ID of the peer to find.
- *
- * @return Pointer to the node of the peer. NULL if not found.
- */
-struct CadetTunnelTreeNode *
-tree_find_peer (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer_id)
-{
-  return tree_node_find_peer (tree->root, peer_id);
-}
-
-
-/**
- * Recusively mark peer and children as disconnected, notify client
- *
- * @param tree Tree this node belongs to
- * @param parent Node to be clean, potentially with children
- * @param cb Callback to use to notify about disconnected peers.
- * @param cbcls Closure for cb.
- */
-static void
-tree_mark_peers_disconnected (struct CadetTunnelTree *tree,
-                              struct CadetTunnelTreeNode *parent,
-                              CadetTreeCallback cb, void *cbcls)
-{
-  struct GNUNET_PeerIdentity *pi;
-  struct GNUNET_PeerIdentity id;
-  struct CadetTunnelTreeNode *n;
-
-  for (n = parent->children_head; NULL != n; n = n->next)
-  {
-    tree_mark_peers_disconnected (tree, n, cb, cbcls);
-  }
-  if (CADET_PEER_READY == parent->status)
-  {
-    if (NULL != cb)
-      cb (cbcls, parent->peer);
-    parent->status = CADET_PEER_RECONNECTING;
-  }
-
-  /* Remove and free info about first hop */
-  GNUNET_PEER_resolve (parent->peer, &id);
-  pi = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
-  GNUNET_CONTAINER_multihashmap_remove_all (tree->first_hops, &id.hashPubKey);
-  if (NULL != pi)
-    GNUNET_free (pi);
-}
-
-
-/**
- * Iterate over all children of the local node.
- *
- * @param tree Tree to use. Must have "me" set.
- * @param cb Callback to call over each child.
- * @param cb_cls Closure for @c cb.
- */
-void
-tree_iterate_children (struct CadetTunnelTree *tree, CadetTreeCallback cb,
-                       void *cb_cls)
-{
-  struct CadetTunnelTreeNode *n;
-
-  if (NULL == tree->me)
-    return;
-  for (n = tree->me->children_head; NULL != n; n = n->next)
-  {
-    cb (cb_cls, n->peer);
-  }
-}
-
-
-/**
- * Struct to contain a list of pending nodes when iterating a tree.
- */
-struct CadetTreePendingNode {
-
-  /**
-   * DLL next.
-   */
-  struct CadetTreePendingNode *next;
-
-  /**
-   * DLL prev.
-   */
-  struct CadetTreePendingNode *prev;
-
-  /**
-   * Pending node.
-   */
-  struct CadetTunnelTreeNode *node;
-};
-
-
-/**
- * Iterate over all nodes in the tree.
- *
- * @param tree Tree to use..
- * @param cb Callback to call over each child.
- * @param cb_cls Closure for @c cb.
- *
- * TODO: recursive implementation? (s/heap/stack/g)
- */
-void
-tree_iterate_all (struct CadetTunnelTree *tree,
-                  CadetWholeTreeCallback cb,
-                  void *cb_cls)
-{
-  struct CadetTunnelTreeNode *parent;
-  struct CadetTunnelTreeNode *n;
-  struct CadetTreePendingNode *head;
-  struct CadetTreePendingNode *tail;
-  struct CadetTreePendingNode *pending;
-
-  cb (cb_cls, tree->root->peer, 0);
-  pending = GNUNET_new (struct CadetTreePendingNode);
-  pending->node = tree->root;
-  head = tail = NULL;
-  GNUNET_CONTAINER_DLL_insert (head, tail, pending);
-
-  while (NULL != head)
-  {
-    pending = head;
-    parent = pending->node;
-    GNUNET_CONTAINER_DLL_remove (head, tail, pending);
-    GNUNET_free (pending);
-    for (n = parent->children_head; NULL != n; n = n->next)
-    {
-      cb (cb_cls, n->peer, parent->peer);
-      pending = GNUNET_new (struct CadetTreePendingNode);
-      pending->node = n;
-      /* Insert_tail: breadth first, Insert: depth first */
-      GNUNET_CONTAINER_DLL_insert (head, tail, pending);
-    }
-  }
-}
-
-
-/**
- * Iterator to count the children in a tree.
- */
-static void
-count_children_cb (void *cls, GNUNET_PEER_Id peer)
-{
-  unsigned int *i = cls;
-
-  (*i)++;
-}
-
-
-/**
- * Count how many children does the local node have in the tree.
- *
- * @param tree Tree to use. Must have "me" set.
- */
-unsigned int
-tree_count_children (struct CadetTunnelTree *tree)
-{
-  unsigned int i;
-
-  i = 0;
-  tree_iterate_children(tree, &count_children_cb, &i);
-  return i;
-}
-
-
-/**
- * Recusively update the info about what is the first hop to reach the node
- *
- * @param tree Tree this nodes belongs to.
- * @param parent_id Short ID from node form which to start updating.
- * @param hop If known, ID of the first hop.
- *            If not known, NULL to find out and pass on children.
- */
-void
-tree_update_first_hops (struct CadetTunnelTree *tree, GNUNET_PEER_Id parent_id,
-                        struct GNUNET_PeerIdentity *hop)
-{
-  tree_node_update_first_hops (tree, tree_find_peer (tree, parent_id), hop);
-}
-
-
-/**
- * Delete the current path to the peer, including all now unused relays.
- * The destination peer is NOT destroyed, it is returned in order to either set
- * a new path to it or destroy it explicitly, taking care of it's child nodes.
- *
- * @param t Tunnel tree where to delete the path from.
- * @param peer_id Short ID of the destination peer whose path we want to 
remove.
- * @param cb Callback to use to notify about disconnected peers.
- * @param cbcls Closure for cb.
- *
- * @return pointer to the pathless node.
- *         NULL when not found
- */
-struct CadetTunnelTreeNode *
-tree_del_path (struct CadetTunnelTree *t, GNUNET_PEER_Id peer_id,
-               CadetTreeCallback cb, void *cbcls)
-{
-  struct CadetTunnelTreeNode *parent;
-  struct CadetTunnelTreeNode *node;
-  struct CadetTunnelTreeNode *n;
-
-#if CADET_TREE_DEBUG
-  struct GNUNET_PeerIdentity id;
-
-  GNUNET_PEER_resolve (peer_id, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Deleting path to %s.\n",
-              GNUNET_i2s (&id));
-#endif
-  if (NULL == t->root || peer_id == t->root->peer)
-    return NULL;
-
-  for (n = t->disconnected_head; NULL != n; n = n->next)
-  {
-    if (n->peer == peer_id)
-    {
-      /* Was already pathless, waiting for reconnection */
-      GNUNET_CONTAINER_DLL_remove (t->disconnected_head, t->disconnected_tail,
-                                   n);
-      return n;
-    }
-  }
-  n = tree_find_peer (t, peer_id);
-  if (NULL == n)
-    return NULL;
-  node = n;
-
-  parent = n->parent;
-  GNUNET_CONTAINER_DLL_remove (parent->children_head, parent->children_tail, 
n);
-  n->parent = NULL;
-
-  while (CADET_PEER_RELAY == parent->status &&
-         NULL == parent->children_head)
-  {
-#if CADET_TREE_DEBUG
-    GNUNET_PEER_resolve (parent->peer, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Deleting node %s.\n",
-                GNUNET_i2s (&id));
-#endif
-    n = parent->parent;
-    if (parent == t->me)
-      t->me = NULL;
-    tree_node_destroy (parent);
-    parent = n;
-  }
-#if CADET_TREE_DEBUG
-  GNUNET_PEER_resolve (parent->peer, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Not deleted peer %s.\n",
-              GNUNET_i2s (&id));
-#endif
-
-  tree_mark_peers_disconnected (t, node, cb, cbcls);
-
-  return node;
-}
-
-
-/**
- * Return a newly allocated individual path to reach a peer from the local 
peer,
- * according to the path tree of some tunnel.
- *
- * @param t Tunnel from which to read the path tree.
- * @param peer Short ID of the destination peer to whom we want a path.
- *
- * @return A newly allocated individual path to reach the destination peer.
- *         Path must be destroyed afterwards.
- */
-struct CadetPeerPath *
-tree_get_path_to_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer)
-{
-  struct CadetTunnelTreeNode *n;
-  struct CadetPeerPath *p;
-
-  n = tree_find_peer (t, peer);
-  if (NULL == n)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  p = path_new (0);
-
-  /* Building the path (inverted!) */
-  while (n->peer != 1)
-  {
-    GNUNET_array_append (p->peers, p->length, n->peer);
-    GNUNET_PEER_change_rc (n->peer, 1);
-    n = n->parent;
-    if (NULL == n)
-    {
-      GNUNET_break (0);
-      path_destroy (p);
-      return NULL;
-    }
-  }
-  GNUNET_array_append (p->peers, p->length, 1);
-  GNUNET_PEER_change_rc (1, 1);
-
-  path_invert (p);
-
-  return p;
-}
-
-
-
-/**
- * Integrate a stand alone path into the tunnel tree.
- * If the peer toward which the new path is already in the tree, the peer
- * and its children will be maked as disconnected and the callback
- * will be called on each one of them. They will be maked as online only after
- * receiving a PATH ACK for the new path for each one of them, so the caller
- * should take care of sending a new CREATE PATH message for each disconnected
- * peer.
- *
- * @param t Tunnel where to add the new path.
- * @param p Path to be integrated.
- * @param cb Callback to use to notify about peers temporarily disconnecting.
- * @param cbcls Closure for cb.
- *
- * @return GNUNET_OK in case of success.
- *         GNUNET_SYSERR in case of error.
- *
- * TODO: optimize
- * - go backwards on path looking for each peer in the present tree
- * - do not disconnect peers until new path is created & connected
- */
-int
-tree_add_path (struct CadetTunnelTree *t, const struct CadetPeerPath *p,
-               CadetTreeCallback cb, void *cbcls)
-{
-  struct CadetTunnelTreeNode *parent;
-  struct CadetTunnelTreeNode *oldnode;
-  struct CadetTunnelTreeNode *n;
-  struct CadetTunnelTreeNode *c;
-  struct GNUNET_PeerIdentity id;
-  int me;
-  unsigned int i;
-
-#if CADET_TREE_DEBUG
-  GNUNET_PEER_resolve (p->peers[p->length - 1], &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "tree:   Adding path [%u] towards peer %s.\n", p->length,
-              GNUNET_i2s (&id));
-#endif
-
-  GNUNET_assert (0 != p->length);
-  parent = n = t->root;
-  if (n->peer != p->peers[0])
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (1 == p->length)
-    return GNUNET_OK;
-  oldnode = tree_del_path (t, p->peers[p->length - 1], cb, cbcls);
-  /* Look for the first node that is not already present in the tree
-   *
-   * Assuming that the tree is somewhat balanced, O(log n * log N).
-   * - Length of the path is expected to be log N (size of whole network).
-   * - Each level of the tree is expected to have log n children (size of 
tree).
-   */
-  me = t->root->peer == 1 ? 0 : -1;
-  for (i = 1; i < p->length; i++)
-  {
-#if CADET_TREE_DEBUG
-    GNUNET_PEER_resolve (p->peers[i], &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Looking for peer %s.\n",
-                GNUNET_i2s (&id));
-#endif
-    parent = n;
-    if (p->peers[i] == 1)
-      me = i;
-    for (c = n->children_head; NULL != c; c = c->next)
-    {
-      if (c->peer == p->peers[i])
-      {
-#if CADET_TREE_DEBUG
-        GNUNET_PEER_resolve (parent->peer, &id);
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "tree:   Found in children of %s.\n", GNUNET_i2s (&id));
-#endif
-        n = c;
-        break;
-      }
-    }
-    /*  If we couldn't find a child equal to path[i], we have reached the end
-     * of the common path. */
-    if (parent == n)
-      break;
-  }
-#if CADET_TREE_DEBUG
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   All childen visited.\n");
-#endif
-  /* Add the rest of the path as a branch from parent. */
-  while (i < p->length)
-  {
-#if CADET_TREE_DEBUG
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Adding peer %u to %u.\n",
-                p->peers[i], parent->peer);
-    GNUNET_PEER_resolve (p->peers[i], &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Adding peer %s.\n",
-                GNUNET_i2s (&id));
-    GNUNET_PEER_resolve (parent->peer, &id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:            to %s.\n",
-                GNUNET_i2s (&id));
-#endif
-
-    if (i == p->length - 1 && NULL != oldnode)
-    {
-#if CADET_TREE_DEBUG
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "tree:   Putting old node into place.\n");
-#endif
-      oldnode->parent = parent;
-      GNUNET_CONTAINER_DLL_insert (parent->children_head, 
parent->children_tail,
-                                   oldnode);
-      tree_node_update_first_hops (t, oldnode, NULL);
-      n = oldnode;
-    }
-    else
-    {
-#if CADET_TREE_DEBUG
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Creating new node.\n");
-#endif
-      n = tree_node_new (parent, p->peers[i]);
-      n->status = CADET_PEER_RELAY;
-    }
-    if (n->peer == 1)
-    {
-      t->me = n;
-      me = i;
-    }
-    i++;
-    parent = n;
-  }
-  n->status = CADET_PEER_SEARCHING;
-
-  GNUNET_break (-1 != me);
-
-  /* Add info about first hop into hashmap. */
-  if (-1 != me && me < p->length - 1)
-  {
-#if CADET_TREE_DEBUG
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "CADET:   finding first hop (own pos %d/%u)\n", me,
-                p->length - 1);
-#endif
-    GNUNET_PEER_resolve (p->peers[me + 1], &id);
-    tree_update_first_hops (t, p->peers[me + 1], &id);
-  }
-#if CADET_TREE_DEBUG
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "CADET:   was last in path, not updating first hops (%d/%u)\n",
-                me, p->length - 1);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   New node added.\n");
-#endif
-  if (NULL == t->me)
-    t->me = tree_find_peer (t, 1);
-  return GNUNET_OK;
-}
-
-
-/**
- * Notifies a tree that a connection it might be using is broken.
- * Marks all peers down the paths as disconnected and notifies the client.
- *
- * @param t Tree to use.
- * @param p1 Short id of one of the peers (order unimportant)
- * @param p2 Short id of one of the peers (order unimportant)
- * @param cb Function to call for every peer that is marked as disconnected.
- * @param cbcls Closure for cb.
- *
- * @return Short ID of the first disconnected peer in the tree.
- */
-GNUNET_PEER_Id
-tree_notify_connection_broken (struct CadetTunnelTree *t, GNUNET_PEER_Id p1,
-                               GNUNET_PEER_Id p2, CadetTreeCallback cb,
-                               void *cbcls)
-{
-  struct CadetTunnelTreeNode *n;
-  struct CadetTunnelTreeNode *c;
-
-  n = tree_find_peer (t, p1);
-  if (NULL == n)
-    return 0;
-  if (NULL != n->parent && n->parent->peer == p2)
-  {
-    tree_mark_peers_disconnected (t, n, cb, cbcls);
-    GNUNET_CONTAINER_DLL_remove (n->parent->children_head,
-                                 n->parent->children_tail, n);
-    GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, 
n);
-    return p1;
-  }
-  for (c = n->children_head; NULL != c; c = c->next)
-  {
-    if (c->peer == p2)
-    {
-      tree_mark_peers_disconnected (t, c, cb, cbcls);
-      GNUNET_CONTAINER_DLL_remove (n->children_head, n->children_tail, c);
-      GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail,
-                                   c);
-      return p2;
-    }
-  }
-  return 0;
-}
-
-
-/**
- * Deletes a peer from a tunnel, liberating all unused resources on the path to
- * it. It shouldn't have children, if it has they will be destroyed as well.
- * If the tree is not local and no longer has any paths, the root node will be
- * destroyed and marked as NULL.
- *
- * @param t Tunnel tree to use.
- * @param peer Short ID of the peer to remove from the tunnel tree.
- * @param cb Callback to notify client of disconnected peers.
- * @param cbcls Closure for cb.
- *
- * @return GNUNET_OK or GNUNET_SYSERR
- */
-int
-tree_del_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer,
-               CadetTreeCallback cb, void *cbcls)
-{
-  struct CadetTunnelTreeNode *n;
-
-  n = tree_del_path (t, peer, cb, cbcls);
-  if (NULL == n)
-  {
-    GNUNET_break (0);
-    return GNUNET_YES;
-  }
-  tree_node_destroy (n);
-  if (NULL == t->root->children_head && t->me != t->root)
-  {
-    tree_node_destroy (t->root);
-    t->root = NULL;
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-
-
-
-/**
- * Get the cost of the path relative to the already built tunnel tree.
- *
- * @param t The tunnel tree to which compare.
- * @param path The individual path to reach a peer. It has to start at the
- *             root of the tree to be comparable.
- *
- * @return Number of hops to reach destination, UINT_MAX in case the peer is 
not
- *         in the path.
- *
- * TODO: adapt to allow any start / root combination
- * TODO: take in account state of the nodes
- */
-unsigned int
-tree_get_path_cost (struct CadetTunnelTree *t, struct CadetPeerPath *path)
-{
-  struct CadetTunnelTreeNode *n;
-  struct CadetTunnelTreeNode *p;
-  unsigned int i;
-  unsigned int l;
-
-  l = path_get_length (path);
-  p = t->root;
-  if (t->root->peer != path->peers[0])
-  {
-    GNUNET_break (0);
-    return UINT_MAX;
-  }
-  for (i = 1; i < l; i++)
-  {
-    for (n = p->children_head; NULL != n; n = n->next)
-    {
-      if (path->peers[i] == n->peer)
-      {
-        break;
-      }
-    }
-    if (NULL == n)
-      return l - i;
-    p = n;
-  }
-  return l - i;
-}
-
-
-/**
- * Print the tree on stderr
- *
- * @param t The tree
- */
-void
-tree_debug (struct CadetTunnelTree *t)
-{
-  tree_node_debug (t->root, 0);
-  FPRINTF (stderr, "root: %p\n", t->root);
-  FPRINTF (stderr, "me:   %p\n", t->me);
-}
-
-
-/**
- * Iterator over hash map peer entries and frees all data in it.
- * Used prior to destroying a hashmap. Makes you miss anonymous functions in C.
- *
- * @param cls closure
- * @param key current key code (will no longer contain valid data!!)
- * @param value value in the hash map (treated as void *)
- * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
- */
-static int
-iterate_free (void *cls, const struct GNUNET_HashCode * key, void *value)
-{
-  GNUNET_free (value);
-  return GNUNET_YES;
-}
-
-
-/**
- * Destroy the whole tree and free all used memory and Peer_Ids
- *
- * @param t Tree to be destroyed
- */
-void
-tree_destroy (struct CadetTunnelTree *t)
-{
-#if CADET_TREE_DEBUG
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying tree\n");
-#endif
-  tree_node_destroy (t->root);
-  GNUNET_CONTAINER_multihashmap_iterate (t->first_hops, &iterate_free, NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (t->first_hops);
-  GNUNET_free (t);
-}

Deleted: gnunet/src/mesh/cadet_tunnel_tree.h
===================================================================
--- gnunet/src/mesh/cadet_tunnel_tree.h 2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/cadet_tunnel_tree.h 2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,382 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/cadet_tunnel_tree.h
- * @brief Tunnel tree handling functions
- * @author Bartlomiej Polot
- */
-
-#include "cadet.h"
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-/**
- * Information regarding a possible path to reach a single peer
- */
-struct CadetPeerPath
-{
-
-    /**
-     * Linked list
-     */
-  struct CadetPeerPath *next;
-  struct CadetPeerPath *prev;
-
-    /**
-     * List of all the peers that form the path from origin to target.
-     */
-  GNUNET_PEER_Id *peers;
-
-    /**
-     * Number of peers (hops) in the path
-     */
-  unsigned int length;
-
-};
-
-
-/**
- * Node of path tree for a tunnel
- */
-struct CadetTunnelTreeNode;
-
-
-/**
- * Tree to reach all peers in the tunnel
- */
-struct CadetTunnelTree;
-
-
-/******************************************************************************/
-/*************************        FUNCTIONS       
*****************************/
-/******************************************************************************/
-
-/**
- * Create a new path.
- *
- * @param length How many hops will the path have.
- *
- * @return A newly allocated path with a peer array of the specified length.
- */
-struct CadetPeerPath *
-path_new (unsigned int length);
-
-
-/**
- * Invert the path.
- *
- * @param path The path to invert.
- */
-void
-path_invert (struct CadetPeerPath *path);
-
-
-/**
- * Duplicate a path, incrementing short peer's rc.
- *
- * @param path The path to duplicate.
- */
-struct CadetPeerPath *
-path_duplicate (struct CadetPeerPath *path);
-
-
-/**
- * Get the length of a path.
- *
- * @param path The path to measure, with the local peer at any point of it.
- *
- * @return Number of hops to reach destination.
- *         UINT_MAX in case the peer is not in the path.
- */
-unsigned int
-path_get_length (struct CadetPeerPath *path);
-
-
-/**
- * Destroy the path and free any allocated resources linked to it
- *
- * @param p the path to destroy
- *
- * @return GNUNET_OK on success
- */
-int
-path_destroy (struct CadetPeerPath *p);
-
-
-/******************************************************************************/
-
-/**
- * Iterator over all children of a node.
- *
- * @param cls Closure.
- * @param peer_id Short ID of the peer.
- */
-typedef void (*CadetTreeCallback) (void *cls, GNUNET_PEER_Id peer_id);
-
-
-/**
- * Iterator over all nodes in a tree.
- *
- * @param cls Closure.
- * @param peer_id Short ID of the peer.
- * @param peer_id Short ID of the parent of the peer.
- */
-typedef void (*CadetWholeTreeCallback) (void *cls,
-                                       GNUNET_PEER_Id peer_id,
-                                       GNUNET_PEER_Id parent_id);
-
-/**
- * Create a new tunnel tree associated to a tunnel
- *
- * @param peer A short peer id of the root of the tree
- *
- * @return A newly allocated and initialized tunnel tree
- */
-struct CadetTunnelTree *
-tree_new (GNUNET_PEER_Id peer);
-
-
-/**
- * Set the status of a node.
- *
- * @param tree Tree.
- * @param peer A short peer id of the node.
- * @param status New status to set.
- */
-void
-tree_set_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer,
-                 enum CadetPeerState status);
-
-
-/**
- * Get the status of a node.
- *
- * @param tree Tree whose local id we want to now.
- * @param peer A short peer id of the node.
- *
- * @return Short peer id of local peer.
- */
-enum CadetPeerState
-tree_get_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer);
-
-
-/**
- * Get the id of the predecessor of the local node.
- *
- * @param tree Tree whose local id we want to now.
- *
- * @return Short peer id of local peer.
- */
-GNUNET_PEER_Id
-tree_get_predecessor (struct CadetTunnelTree *tree);
-
-
-/**
- * Find the first peer whom to send a packet to go down this path
- *
- * @param t The tunnel tree to use
- * @param peer The peerinfo of the peer we are trying to reach
- *
- * @return peerinfo of the peer who is the first hop in the tunnel
- *         NULL on error
- */
-struct GNUNET_PeerIdentity *
-tree_get_first_hop (struct CadetTunnelTree *t, GNUNET_PEER_Id peer);
-
-
-/**
- * Find the given peer in the tree.
- *
- * @param tree Tree where to look for the peer.
- * @param peer_id Peer to find.
- *
- * @return Pointer to the node of the peer. NULL if not found.
- */
-struct CadetTunnelTreeNode *
-tree_find_peer (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer_id);
-
-
-/**
- * Iterate over all children of the local node.
- *
- * @param tree Tree to use. Must have "me" set.
- * @param cb Callback to call over each child.
- * @param cb_cls Closure for @c cb.
- */
-void
-tree_iterate_children (struct CadetTunnelTree *tree,
-                       CadetTreeCallback cb,
-                       void *cb_cls);
-
-
-/**
- * Iterate over all nodes in the tree.
- *
- * @param tree Tree to use..
- * @param cb Callback to call over each child.
- * @param cb_cls Closure for @c cb.
- *
- * TODO: recursive implementation? (s/heap/stack/g)
- */
-void
-tree_iterate_all (struct CadetTunnelTree *tree,
-                  CadetWholeTreeCallback cb,
-                  void *cb_cls);
-
-/**
- * Count how many children does the local node have in the tree.
- *
- * @param tree Tree to use. Must have "me" set.
- */
-unsigned int
-tree_count_children (struct CadetTunnelTree *tree);
-
-
-/**
- * Recusively update the info about what is the first hop to reach the node
- *
- * @param tree Tree this nodes belongs to.
- * @param parent_id Short ID from node form which to start updating.
- * @param hop If known, ID of the first hop.
- *            If not known, NULL to find out and pass on children.
- */
-void
-tree_update_first_hops (struct CadetTunnelTree *tree, GNUNET_PEER_Id parent_id,
-                        struct GNUNET_PeerIdentity *hop);
-
-/**
- * Delete the current path to the peer, including all now unused relays.
- * The destination peer is NOT destroyed, it is returned in order to either set
- * a new path to it or destroy it explicitly, taking care of it's child nodes.
- *
- * @param t Tunnel tree where to delete the path from.
- * @param peer_id Short ID of the destination peer whose path we want to 
remove.
- * @param cb Callback to use to notify about which peers are going to be
- *           disconnected.
- * @param cbcls Closure for cb.
- *
- * @return pointer to the pathless node.
- *         NULL when not found
- */
-struct CadetTunnelTreeNode *
-tree_del_path (struct CadetTunnelTree *t, GNUNET_PEER_Id peer_id,
-               CadetTreeCallback cb, void *cbcls);
-
-
-/**
- * Return a newly allocated individual path to reach a peer from the local 
peer,
- * according to the path tree of some tunnel.
- *
- * @param t Tunnel from which to read the path tree
- * @param peer Destination peer to whom we want a path
- *
- * @return A newly allocated individual path to reach the destination peer.
- *         Path must be destroyed afterwards.
- */
-struct CadetPeerPath *
-tree_get_path_to_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer);
-
-
-/**
- * Integrate a stand alone path into the tunnel tree.
- *
- * @param t Tunnel where to add the new path.
- * @param p Path to be integrated.
- * @param cb Callback to use to notify about peers temporarily disconnecting.
- * @param cbcls Closure for cb.
- *
- * @return GNUNET_OK in case of success.
- *         GNUNET_SYSERR in case of error.
- */
-int
-tree_add_path (struct CadetTunnelTree *t, const struct CadetPeerPath *p,
-               CadetTreeCallback cb, void *cbcls);
-
-
-/**
- * Notifies a tree that a connection it might be using is broken.
- * Marks all peers down the paths as disconnected and notifies the client.
- *
- * @param t Tree to use.
- * @param p1 Short id of one of the peers (order unimportant)
- * @param p2 Short id of one of the peers (order unimportant)
- * @param cb Function to call for every peer that is marked as disconnected.
- * @param cbcls Closure for cb.
- *
- * @return Short ID of the first disconnected peer in the tree.
- */
-GNUNET_PEER_Id
-tree_notify_connection_broken (struct CadetTunnelTree *t, GNUNET_PEER_Id p1,
-                               GNUNET_PEER_Id p2, CadetTreeCallback cb,
-                               void *cbcls);
-
-
-/**
- * Deletes a peer from a tunnel, liberating all unused resources on the path to
- * it. It shouldn't have children, if it has they will be destroyed as well.
- * If the tree is not local and no longer has any paths, the root node will be
- * destroyed and marked as NULL.
- *
- * FIXME: dont destroy the root
- *
- * @param t Tunnel tree to use.
- * @param peer Short ID of the peer to remove from the tunnel tree.
- * @param cb Callback to notify client of disconnected peers.
- * @param cbcls Closure for cb.
- *
- * @return GNUNET_YES if the tunnel still has nodes
- */
-int
-tree_del_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer,
-               CadetTreeCallback cb, void *cbcls);
-
-
-/**
- * Get the cost of the path relative to the already built tunnel tree
- *
- * @param t The tunnel tree to which compare
- * @param path The individual path to reach a peer
- *
- * @return Number of hops to reach destination, UINT_MAX in case the peer is 
not
- * in the path
- */
-unsigned int
-tree_get_path_cost (struct CadetTunnelTree *t, struct CadetPeerPath *path);
-
-
-/**
- * Print the tree on stderr
- *
- * @param t The tree
- */
-void
-tree_debug (struct CadetTunnelTree *t);
-
-
-/**
- * Destroy the whole tree and free all used memory and Peer_Ids
- *
- * @param t Tree to be destroyed
- */
-void
-tree_destroy (struct CadetTunnelTree *t);

Deleted: gnunet/src/mesh/gnunet-cadet-profiler.c
===================================================================
--- gnunet/src/mesh/gnunet-cadet-profiler.c     2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/gnunet-cadet-profiler.c     2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,1092 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file cadet/gnunet-cadet-profiler.c
- *
- * @brief Profiler for cadet experiments.
- */
-#include <stdio.h>
-#include "platform.h"
-#include "cadet_test_lib.h"
-#include "gnunet_cadet_service.h"
-#include "gnunet_statistics_service.h"
-
-
-#define PING 1
-#define PONG 2
-
-
-/**
- * Paximum ping period in milliseconds. Real period = rand (0, PING_PERIOD)
- */
-#define PING_PERIOD 1000
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
-
-/**
- * Time to wait for stuff that should be rather fast
- */
-#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
300)
-
-/**
- * Total number of rounds.
- */
-#define number_rounds sizeof(rounds)/sizeof(rounds[0])
-
-/**
- * Ratio of peers active. First round always is 1.0.
- */
-static float rounds[] = {0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.0};
-
-/**
- * Message type for pings.
- */
-struct CadetPingMessage
-{
-  /**
-   * Header. Type PING/PONG.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Message number.
-   */
-  uint32_t counter;
-
-  /**
-   * Time the message was sent.
-   */
-  struct GNUNET_TIME_AbsoluteNBO timestamp;
-
-  /**
-   * Round number.
-   */
-  uint32_t round_number;
-};
-
-/**
- * Peer description.
- */
-struct CadetPeer
-{
-  /**
-   * Testbed Operation (to get peer id, etc).
-   */
-  struct GNUNET_TESTBED_Operation *op;
-
-  /**
-   * Peer ID.
-   */
-  struct GNUNET_PeerIdentity id;
-
-  /**
-   * Cadet handle for the root peer
-   */
-  struct GNUNET_CADET_Handle *cadet;
-
-  /**
-   * Channel handle for the root peer
-   */
-  struct GNUNET_CADET_Channel *ch;
-
-  /**
-   * Channel handle for the dest peer
-   */
-  struct GNUNET_CADET_Channel *incoming_ch;
-
-  /**
-   * Channel handle for a warmup channel.
-   */
-  struct GNUNET_CADET_Channel *warmup_ch;
-
-  /**
-   * Number of payload packes sent
-   */
-  int data_sent;
-
-  /**
-   * Number of payload packets received
-   */
-  int data_received;
-
-  /**
-   * Is peer up?
-   */
-  int up;
-
-  /**
-   * Destinaton to ping.
-   */
-  struct CadetPeer *dest;
-
-  /**
-   * Incoming channel for pings.
-   */
-  struct CadetPeer *incoming;
-
-  /**
-   * Task to do the next ping.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier ping_task;
-
-  float mean[number_rounds];
-  float var[number_rounds];
-  unsigned int pongs[number_rounds];
-  unsigned int pings[number_rounds];
-
-};
-
-/**
- * Duration of each round.
- */
-static struct GNUNET_TIME_Relative round_time;
-
-/**
- * GNUNET_PeerIdentity -> CadetPeer
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *ids;
-
-/**
- * Testbed peer handles.
- */
-static struct GNUNET_TESTBED_Peer **testbed_handles;
-
-/**
- * Testbed Operation (to get stats).
- */
-static struct GNUNET_TESTBED_Operation *stats_op;
-
-/**
- * Operation to get peer ids.
- */
-struct CadetPeer *peers;
-
-/**
- * Peer ids counter.
- */
-static unsigned int p_ids;
-
-/**
- * Total number of peers.
- */
-static unsigned long long peers_total;
-
-/**
- * Number of currently running peers.
- */
-static unsigned long long peers_running;
-
-/**
- * Number of peers doing pings.
- */
-static unsigned long long peers_pinging;
-
-/**
- * Test context (to shut down).
- */
-static struct GNUNET_CADET_TEST_Context *test_ctx;
-
-/**
- * Task called to shutdown test.
- */
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
-
-/**
- * Task called to disconnect peers, before shutdown.
- */
-static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-/**
- * Task to perform tests
- */
-static GNUNET_SCHEDULER_TaskIdentifier test_task;
-
-/**
- * Round number.
- */
-static unsigned int current_round;
-
-/**
- * Do preconnect? (Each peer creates a tunnel to one other peer).
- */
-static int do_warmup;
-
-/**
- * Warmup progress.
- */
-static unsigned int peers_warmup;
-
-/**
- * Flag to notify callbacks not to generate any new traffic anymore.
- */
-static int test_finished;
-
-
-/**
- * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
- *
- * Testcase continues when the root receives confirmation of connected peers,
- * on callback funtion ch.
- *
- * @param cls Closure (unsued).
- * @param tc Task Context.
- */
-static void
-start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Calculate a random delay.
- *
- * @param max Exclusive maximum, in ms.
- *
- * @return A time between 0 a max-1 ms.
- */
-static struct GNUNET_TIME_Relative
-delay_ms_rnd (unsigned int max)
-{
-  unsigned int rnd;
-
-  rnd = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max);
-  return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rnd);
-}
-
-
-/**
- * Get the index of a peer in the peers array.
- *
- * @param peer Peer whose index to get.
- *
- * @return Index of peer in peers.
- */
-static unsigned int
-get_index (struct CadetPeer *peer)
-{
-  return peer - peers;
-}
-
-
-/**
- * Show the results of the test (banwidth acheived) and log them to GAUGER
- */
-static void
-show_end_data (void)
-{
-  struct CadetPeer *peer;
-  unsigned int i;
-  unsigned int j;
-
-  for (i = 0; i < number_rounds; i++)
-  {
-    for (j = 0; j < peers_pinging; j++)
-    {
-      peer = &peers[j];
-      FPRINTF (stdout,
-               "ROUND %3u PEER %3u: %10.2f / %10.2f, PINGS: %3u, PONGS: %3u\n",
-               i, j, peer->mean[i], sqrt (peer->var[i] / (peer->pongs[i] - 1)),
-               peer->pings[i], peer->pongs[i]);
-    }
-  }
-}
-
-
-/**
- * Shut down peergroup, clean up.
- *
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ending test.\n");
-  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
-}
-
-
-/**
- * Disconnect from cadet services af all peers, call shutdown.
- *
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-disconnect_cadet_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
-{
-  long line = (long) cls;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "disconnecting cadet service, called from line %ld\n", line);
-  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  for (i = 0; i < peers_total; i++)
-  {
-    if (NULL != peers[i].op)
-      GNUNET_TESTBED_operation_done (peers[i].op);
-
-    if (peers[i].up != GNUNET_YES)
-      continue;
-
-    if (NULL != peers[i].ch)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: channel %p\n", i, peers[i].ch);
-      GNUNET_CADET_channel_destroy (peers[i].ch);
-    }
-    if (NULL != peers[i].warmup_ch)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: warmup channel %p\n",
-                  i, peers[i].warmup_ch);
-      GNUNET_CADET_channel_destroy (peers[i].warmup_ch);
-    }
-    if (NULL != peers[i].incoming_ch)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: incoming channel %p\n",
-                  i, peers[i].incoming_ch);
-      GNUNET_CADET_channel_destroy (peers[i].incoming_ch);
-    }
-  }
-  GNUNET_CADET_TEST_cleanup (test_ctx);
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_handle);
-  }
-  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
-}
-
-
-/**
- * Finish test normally: schedule disconnect and shutdown
- *
- * @param line Line in the code the abort is requested from (__LINE__).
- */
-static void
-abort_test (long line)
-{
-  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
-                                                (void *) line);
-  }
-}
-
-/**
- * Stats callback. Finish the stats testbed operation and when all stats have
- * been iterated, shutdown the test.
- *
- * @param cls closure
- * @param op the operation that has been finished
- * @param emsg error message in case the operation has failed; will be NULL if
- *          operation has executed successfully.
- */
-static void
-stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "... collecting statistics done.\n");
-  GNUNET_TESTBED_operation_done (stats_op);
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
-                                              (void *) __LINE__);
-
-}
-
-
-/**
- * Process statistic values.
- *
- * @param cls closure
- * @param peer the peer the statistic belong to
- * @param subsystem name of subsystem that created the statistic
- * @param name the name of the datum
- * @param value the current value
- * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
- * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
- */
-static int
-stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
-                const char *subsystem, const char *name,
-                uint64_t value, int is_persistent)
-{
-  uint32_t i;
-
-  i = GNUNET_TESTBED_get_index (peer);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " STATS %u - %s [%s]: %llu\n",
-              i, subsystem, name, value);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Task check that keepalives were sent and received.
- *
- * @param cls Closure (NULL).
- * @param tc Task Context.
- */
-static void
-collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start collecting statistics...\n");
-  stats_op = GNUNET_TESTBED_get_statistics (peers_total, testbed_handles,
-                                            NULL, NULL,
-                                            stats_iterator, stats_cont, NULL);
-}
-
-
-/**
- * @brief Finish profiler normally. Signal finish and start collecting stats.
- *
- * @param cls Closure (unused).
- * @param tc Task context.
- */
-static void
-finish_profiler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  test_finished = GNUNET_YES;
-  show_end_data();
-  GNUNET_SCHEDULER_add_now (&collect_stats, NULL);
-}
-
-/**
- * Set the total number of running peers.
- *
- * @param target Desired number of running peers.
- */
-static void
-adjust_running_peers (unsigned int target)
-{
-  struct GNUNET_TESTBED_Operation *op;
-  unsigned int delta;
-  unsigned int run;
-  unsigned int i;
-  unsigned int r;
-
-  GNUNET_assert (target <= peers_total);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "adjust peers to %u\n", target);
-  if (target > peers_running)
-  {
-    delta = target - peers_running;
-    run = GNUNET_YES;
-  }
-  else
-  {
-    delta = peers_running - target;
-    run = GNUNET_NO;
-  }
-
-  for (i = 0; i < delta; i++)
-  {
-    do {
-      r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                    peers_total - peers_pinging);
-      r += peers_pinging;
-    } while (peers[r].up == run || NULL != peers[r].incoming);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "St%s peer %u: %s\n",
-                run ? "arting" : "opping", r, GNUNET_i2s (&peers[r].id));
-
-    if (GNUNET_SCHEDULER_NO_TASK != peers[r].ping_task)
-      GNUNET_SCHEDULER_cancel (peers[r].ping_task);
-    peers[r].ping_task = GNUNET_SCHEDULER_NO_TASK;
-
-    peers[r].up = run;
-
-    if (NULL != peers[r].ch)
-      GNUNET_CADET_channel_destroy (peers[r].ch);
-    peers[r].ch = NULL;
-    if (NULL != peers[r].dest)
-    {
-      if (NULL != peers[r].dest->incoming_ch)
-        GNUNET_CADET_channel_destroy (peers[r].dest->incoming_ch);
-      peers[r].dest->incoming_ch = NULL;
-    }
-
-    op = GNUNET_TESTBED_peer_manage_service (&peers[r], testbed_handles[r],
-                                             "cadet", NULL, NULL, run);
-    GNUNET_break (NULL != op);
-    peers_running += run ? 1 : -1;
-    GNUNET_assert (peers_running > 0);
-  }
-}
-
-
-/**
- * @brief Move to next round.
- *
- * @param cls Closure (round #).
- * @param tc Task context.
- */
-static void
-next_rnd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ROUND %ld\n", current_round);
-  if (0.0 == rounds[current_round])
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finishing\n");
-    GNUNET_SCHEDULER_add_now (&finish_profiler, NULL);
-    return;
-  }
-  adjust_running_peers (rounds[current_round] * peers_total);
-  current_round++;
-
-  GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL);
-}
-
-
-/**
- * Transmit ping callback.
- *
- * @param cls Closure (peer for PING, NULL for PONG).
- * @param size Size of the tranmist buffer.
- * @param buf Pointer to the beginning of the buffer.
- *
- * @return Number of bytes written to buf.
- */
-static size_t
-tmt_rdy_ping (void *cls, size_t size, void *buf);
-
-
-/**
- * Transmit pong callback.
- *
- * @param cls Closure (copy of PING message, to be freed).
- * @param size Size of the buffer we have.
- * @param buf Buffer to copy data to.
- */
-static size_t
-tmt_rdy_pong (void *cls, size_t size, void *buf)
-{
-  struct CadetPingMessage *ping = cls;
-  struct CadetPingMessage *pong;
-
-  if (0 == size || NULL == buf)
-  {
-    GNUNET_free (ping);
-    return 0;
-  }
-  pong = (struct CadetPingMessage *) buf;
-  memcpy (pong, ping, sizeof (*ping));
-  pong->header.type = htons (PONG);
-
-  GNUNET_free (ping);
-  return sizeof (*ping);
-}
-
-
-/**
- * @brief Send a ping to destination
- *
- * @param cls Closure (peer).
- * @param tc Task context.
- */
-static void
-ping (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetPeer *peer = (struct CadetPeer *) cls;
-
-  peer->ping_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0
-      || GNUNET_YES == test_finished)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u -> %u (%u)\n",
-              get_index (peer), get_index (peer->dest), peer->data_sent);
-
-  GNUNET_CADET_notify_transmit_ready (peer->ch, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     sizeof (struct CadetPingMessage),
-                                     &tmt_rdy_ping, peer);
-}
-
-/**
- * @brief Reply with a pong to origin.
- *
- * @param cls Closure (peer).
- * @param tc Task context.
- */
-static void
-pong (struct GNUNET_CADET_Channel *channel, const struct CadetPingMessage 
*ping)
-{
-  struct CadetPingMessage *copy;
-
-  copy = GNUNET_new (struct CadetPingMessage);
-  memcpy (copy, ping, sizeof (*ping));
-  GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     sizeof (struct CadetPingMessage),
-                                     &tmt_rdy_pong, copy);
-}
-
-
-/**
- * Transmit ping callback
- *
- * @param cls Closure (peer).
- * @param size Size of the buffer we have.
- * @param buf Buffer to copy data to.
- */
-static size_t
-tmt_rdy_ping (void *cls, size_t size, void *buf)
-{
-  struct CadetPeer *peer = (struct CadetPeer *) cls;
-  struct CadetPingMessage *msg = buf;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tmt_rdy called, filling buffer\n");
-  if (size < sizeof (struct CadetPingMessage) || NULL == buf)
-  {
-    GNUNET_break (GNUNET_YES == test_finished);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "size %u, buf %p, data_sent %u, data_received %u\n",
-                size, buf, peer->data_sent, peer->data_received);
-
-    return 0;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending: msg %d\n", peer->data_sent);
-  msg->header.size = htons (size);
-  msg->header.type = htons (PING);
-  msg->counter = htonl (peer->data_sent++);
-  msg->round_number = htonl (current_round);
-  msg->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
-  peer->pings[current_round]++;
-  peer->ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (PING_PERIOD),
-                                                  &ping, peer);
-
-  return sizeof (struct CadetPingMessage);
-}
-
-
-/**
- * Function is called whenever a PING message is received.
- *
- * @param cls closure (peer #, set from GNUNET_CADET_connect)
- * @param channel connection to the other end
- * @param channel_ctx place to store local state associated with the channel
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-ping_handler (void *cls, struct GNUNET_CADET_Channel *channel,
-              void **channel_ctx,
-              const struct GNUNET_MessageHeader *message)
-{
-  long n = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u got PING\n", n);
-  GNUNET_CADET_receive_done (channel);
-  if (GNUNET_NO == test_finished)
-    pong (channel, (struct CadetPingMessage *) message);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Function is called whenever a PONG message is received.
- *
- * @param cls closure (peer #, set from GNUNET_CADET_connect)
- * @param channel connection to the other end
- * @param channel_ctx place to store local state associated with the channel
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-pong_handler (void *cls, struct GNUNET_CADET_Channel *channel,
-              void **channel_ctx,
-              const struct GNUNET_MessageHeader *message)
-{
-  long n = (long) cls;
-  struct CadetPeer *peer;
-  struct CadetPingMessage *msg;
-  struct GNUNET_TIME_Absolute send_time;
-  struct GNUNET_TIME_Relative latency;
-  unsigned int r /* Ping round */;
-  float delta;
-
-  GNUNET_CADET_receive_done (channel);
-  peer = &peers[n];
-
-  msg = (struct CadetPingMessage *) message;
-
-  send_time = GNUNET_TIME_absolute_ntoh (msg->timestamp);
-  latency = GNUNET_TIME_absolute_get_duration (send_time);
-  r = ntohl (msg->round_number);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n",
-              get_index (peer), get_index (peer->dest), ntohl (msg->counter),
-              GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
-
-  /* Online variance calculation */
-  peer->pongs[r]++;
-  delta = latency.rel_value_us - peer->mean[r];
-  peer->mean[r] = peer->mean[r] + delta/peer->pongs[r];
-  peer->var[r] += delta * (latency.rel_value_us - peer->mean[r]);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Handlers, for diverse services
- */
-static struct GNUNET_CADET_MessageHandler handlers[] = {
-  {&ping_handler, PING, sizeof (struct CadetPingMessage)},
-  {&pong_handler, PONG, sizeof (struct CadetPingMessage)},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Method called whenever another peer has added us to a channel
- * the other peer initiated.
- *
- * @param cls Closure.
- * @param channel New handle to the channel.
- * @param initiator Peer that started the channel.
- * @param port Port this channel is connected to.
- * @param options channel option flags
- * @return Initial channel context for the channel
- *         (can be NULL -- that's not an error).
- */
-static void *
-incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel,
-                 const struct GNUNET_PeerIdentity *initiator,
-                 uint32_t port, enum GNUNET_CADET_ChannelOption options)
-{
-  long n = (long) cls;
-  struct CadetPeer *peer;
-
-  peer = GNUNET_CONTAINER_multipeermap_get (ids, initiator);
-  GNUNET_assert (NULL != peer);
-  if (NULL == peers[n].incoming)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %3u: %u <= %u\n",
-                peers_warmup, n, get_index (peer));
-    peers_warmup++;
-    if (peers_warmup < peers_total)
-      return NULL;
-    if (GNUNET_SCHEDULER_NO_TASK != test_task)
-    {
-      GNUNET_SCHEDULER_cancel (test_task);
-      test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                &start_test, NULL);
-    }
-    return NULL;
-  }
-  GNUNET_assert (peer == peers[n].incoming);
-  GNUNET_assert (peer->dest == &peers[n]);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <= %u %p\n",
-              n, get_index (peer), channel);
-  peers[n].incoming_ch = channel;
-
-  return NULL;
-}
-
-/**
- * Function called whenever an inbound channel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_CADET_connect)
- * @param channel connection to the other end (henceforth invalid)
- * @param channel_ctx place where local state associated
- *                   with the channel is stored
- */
-static void
-channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel,
-                 void *channel_ctx)
-{
-  long n = (long) cls;
-  struct CadetPeer *peer = &peers[n];
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Channel %p disconnected at peer %ld\n", channel, n);
-  if (peer->ch == channel)
-    peer->ch = NULL;
-}
-
-
-/**
- * Select a random peer that has no incoming channel
- *
- * @param peer ID of the peer connecting. NULL if irrelevant (warmup).
- *
- * @return Random peer not yet connected to.
- */
-static struct CadetPeer *
-select_random_peer (struct CadetPeer *peer)
-{
-  unsigned int r;
-
-  do
-  {
-    r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total);
-  } while (NULL != peers[r].incoming);
-  peers[r].incoming = peer;
-
-  return &peers[r];
-}
-
-/**
- * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
- *
- * Testcase continues when the root receives confirmation of connected peers,
- * on callback funtion ch.
- *
- * @param cls Closure (unsued).
- * @param tc Task Context.
- */
-static void
-start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  enum GNUNET_CADET_ChannelOption flags;
-  unsigned long i;
-
-  test_task = GNUNET_SCHEDULER_NO_TASK;
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start profiler\n");
-
-  flags = GNUNET_CADET_OPTION_DEFAULT;
-  for (i = 0; i < peers_pinging; i++)
-  {
-    peers[i].dest = select_random_peer (&peers[i]);
-    peers[i].ch = GNUNET_CADET_channel_create (peers[i].cadet, NULL,
-                                              &peers[i].dest->id,
-                                              1, flags);
-    if (NULL == peers[i].ch)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Channel %lu failed\n", i);
-      GNUNET_CADET_TEST_cleanup (test_ctx);
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u => %u %p\n",
-                i, get_index (peers[i].dest), peers[i].ch);
-    peers[i].ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (2000),
-                                                       &ping, &peers[i]);
-  }
-  peers_running = peers_total;
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  disconnect_task =
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(round_time,
-                                                                number_rounds 
+ 1),
-                                  &disconnect_cadet_peers,
-                                  (void *) __LINE__);
-  GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL);
-}
-
-
-/**
- * Do warmup: create some channels to spread information about the topology.
- */
-static void
-warmup (void)
-{
-  struct CadetPeer *peer;
-  unsigned int i;
-
-  for (i = 0; i < peers_total; i++)
-  {
-    peer = select_random_peer (NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %u => %u\n",
-                i, get_index (peer));
-    peers[i].warmup_ch =
-      GNUNET_CADET_channel_create (peers[i].cadet, NULL, &peer->id,
-                                  1, GNUNET_CADET_OPTION_DEFAULT);
-    if (NULL == peers[i].warmup_ch)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Warmup %u failed\n", i);
-      GNUNET_CADET_TEST_cleanup (test_ctx);
-      return;
-    }
-  }
-}
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cls the closure from GNUNET_TESTBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed;
- *             NULL if the operation is successfull
- */
-static void
-peer_id_cb (void *cls,
-       struct GNUNET_TESTBED_Operation *op,
-       const struct GNUNET_TESTBED_PeerInformation *pinfo,
-       const char *emsg)
-{
-  long n = (long) cls;
-
-  if (NULL == pinfo || NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
-    abort_test (__LINE__);
-    return;
-  }
-  peers[n].id = *(pinfo->result.id);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u  id: %s\n",
-              n, GNUNET_i2s (&peers[n].id));
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONTAINER_multipeermap_put (ids, &peers[n].id, 
&peers[n],
-                                                   
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
-
-  GNUNET_TESTBED_operation_done (peers[n].op);
-  peers[n].op = NULL;
-
-  p_ids++;
-  if (p_ids < peers_total)
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting profiler\n");
-  if (do_warmup)
-  {
-    struct GNUNET_TIME_Relative delay;
-
-    warmup();
-    delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
-                                           100 * peers_total);
-    test_task = GNUNET_SCHEDULER_add_delayed (delay, &start_test, NULL);
-    return; /* start_test from incoming_channel */
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting in a second...\n");
-  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                            &start_test, NULL);
-}
-
-/**
- * test main: start test when all peers are connected
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param testbed_peers Array of peers.
- * @param cadetes Handle to each of the CADETs of the peers.
- */
-static void
-tmain (void *cls,
-       struct GNUNET_CADET_TEST_Context *ctx,
-       unsigned int num_peers,
-       struct GNUNET_TESTBED_Peer **testbed_peers,
-       struct GNUNET_CADET_Handle **cadetes)
-{
-  unsigned long i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
-  test_ctx = ctx;
-  GNUNET_assert (peers_total == num_peers);
-  peers_running = num_peers;
-  testbed_handles = testbed_peers;
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_cadet_peers,
-                                                  (void *) __LINE__);
-  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                                  &shutdown_task, NULL);
-  for (i = 0; i < peers_total; i++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requesting id %ld\n", i);
-    peers[i].up = GNUNET_YES;
-    peers[i].cadet = cadetes[i];
-    peers[i].op =
-      GNUNET_TESTBED_peer_get_information (testbed_handles[i],
-                                           GNUNET_TESTBED_PIT_IDENTITY,
-                                           &peer_id_cb, (void *) i);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "requested peer ids\n");
-  /* Continues from pi_cb -> do_test */
-}
-
-
-/**
- * Main: start profiler.
- */
-int
-main (int argc, char *argv[])
-{
-  static uint32_t ports[2];
-  const char *config_file;
-
-  config_file = ".profiler.conf";
-
-  if (4 > argc)
-  {
-    fprintf (stderr, "usage: %s ROUND_TIME PEERS PINGS [DO_WARMUP]\n", 
argv[0]);
-    fprintf (stderr, "example: %s 30s 16 1 Y\n", argv[0]);
-    return 1;
-  }
-
-  if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[1], 
&round_time))
-  {
-    fprintf (stderr, "%s is not a valid time\n", argv[1]);
-    return 1;
-  }
-
-  peers_total = atoll (argv[2]);
-  if (2 > peers_total)
-  {
-    fprintf (stderr, "%s peers is not valid (> 2)\n", argv[1]);
-    return 1;
-  }
-  peers = GNUNET_malloc (sizeof (struct CadetPeer) * peers_total);
-
-  peers_pinging = atoll (argv[3]);
-
-  if (peers_total < 2 * peers_pinging)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "not enough peers, total should be > 2 * peers_pinging\n");
-    return 1;
-  }
-
-  do_warmup = (5 > argc || argv[4][0] != 'N');
-
-  ids = GNUNET_CONTAINER_multipeermap_create (2 * peers_total, GNUNET_YES);
-  GNUNET_assert (NULL != ids);
-  p_ids = 0;
-  test_finished = GNUNET_NO;
-  ports[0] = 1;
-  ports[1] = 0;
-  GNUNET_CADET_TEST_run ("cadet-profiler", config_file, peers_total,
-                        &tmain, NULL, /* tmain cls */
-                        &incoming_channel, &channel_cleaner,
-                        handlers, ports);
-  GNUNET_free (peers);
-
-  return 0;
-}
-
-/* end of gnunet-cadet-profiler.c */
-

Deleted: gnunet/src/mesh/gnunet-cadet.c
===================================================================
--- gnunet/src/mesh/gnunet-cadet.c      2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/gnunet-cadet.c      2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,851 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-cadet.c
- * @brief Print information about cadet tunnels and peers.
- * @author Bartlomiej Polot
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_cadet_service.h"
-#include "cadet.h"
-
-
-/**
- * Option -m.
- */
-static int monitor_connections;
-
-/**
- * Option -P.
- */
-static int request_peers;
-
-/**
- * Option --peer
- */
-static char *peer_id;
-
-/**
- * Option -T.
- */
-static int request_tunnels;
-
-/**
- * Option --tunnel
- */
-static char *tunnel_id;
-
-/**
- * Option --connection
- */
-static char *conn_id;
-
-/**
- * Option --channel
- */
-static char *channel_id;
-
-/**
- * Port to listen on (-p).
- */
-static uint32_t listen_port;
-
-/**
- * Request echo service
- */
-int echo;
-
-/**
- * Time of last echo request.
- */
-struct GNUNET_TIME_Absolute echo_time;
-
-/**
- * Task for next echo request.
- */
-GNUNET_SCHEDULER_TaskIdentifier echo_task;
-
-/**
- * Peer to connect to.
- */
-static char *target_id;
-
-/**
- * Port to connect to
- */
-static uint32_t target_port;
-
-/**
- * Data pending in netcat mode.
- */
-size_t data_size;
-
-
-/**
- * Cadet handle.
- */
-static struct GNUNET_CADET_Handle *mh;
-
-/**
- * Channel handle.
- */
-static struct GNUNET_CADET_Channel *ch;
-
-/**
- * Shutdown task handle.
- */
-GNUNET_SCHEDULER_TaskIdentifier sd;
-
-
-
-static void
-listen_stdio (void);
-
-
-
-/**
- * Task run in monitor mode when the user presses CTRL-C to abort.
- * Stops monitoring activity.
- *
- * @param cls Closure (unused).
- * @param tc scheduler context
- */
-static void
-shutdown_task (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
-  if (NULL != ch)
-  {
-    GNUNET_CADET_channel_destroy (ch);
-    ch = NULL;
-  }
-  if (NULL != mh)
-  {
-    GNUNET_CADET_disconnect (mh);
-        mh = NULL;
-  }
-}
-
-
-/**
- * Function called to notify a client about the connection
- * begin ready to queue more data.  "buf" will be
- * NULL and "size" zero if the connection was closed for
- * writing in the meantime.
- *
- * FIXME
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-size_t
-data_ready (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *msg;
-  size_t total_size;
-
-  if (NULL == buf || 0 == size)
-  {
-    GNUNET_SCHEDULER_shutdown();
-    return 0;
-  }
-
-  total_size = data_size + sizeof (struct GNUNET_MessageHeader);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending %u bytes\n", data_size);
-  GNUNET_assert (size >= total_size);
-
-  msg = buf;
-  msg->size = htons (total_size);
-  msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_CLI);
-  memcpy (&msg[1], cls, data_size);
-  if (GNUNET_NO == echo)
-  {
-    listen_stdio ();
-  }
-  else
-  {
-    echo_time = GNUNET_TIME_absolute_get ();
-  }
-
-  return total_size;
-}
-
-
-/**
- * Task run in monitor mode when the user presses CTRL-C to abort.
- * Stops monitoring activity.
- *
- * @param cls Closure (unused).
- * @param tc scheduler context
- */
-static void
-read_stdio (void *cls,
-            const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  static char buf[60000];
-
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    return;
-  }
-
-  data_size = read (0, buf, 60000);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stdio read %u bytes\n", data_size);
-  if (data_size < 1)
-  {
-    GNUNET_SCHEDULER_shutdown();
-    return;
-  }
-  GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     data_size
-                                     + sizeof (struct GNUNET_MessageHeader),
-                                     &data_ready, buf);
-}
-
-
-/**
- * Start listening to stdin
- */
-static void
-listen_stdio (void)
-{
-  struct GNUNET_NETWORK_FDSet *rs;
-
-  rs = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_set_native (rs, 0);
-  GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                               GNUNET_TIME_UNIT_FOREVER_REL,
-                               rs, NULL,
-                               &read_stdio, NULL);
-  GNUNET_NETWORK_fdset_destroy (rs);
-}
-
-
-/**
- * Function called whenever a channel is destroyed.  Should clean up
- * any associated state.
- *
- * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
- *
- * @param cls closure (set from #GNUNET_CADET_connect)
- * @param channel connection to the other end (henceforth invalid)
- * @param channel_ctx place where local state associated
- *                   with the channel is stored
- */
-static void
-channel_ended (void *cls,
-               const struct GNUNET_CADET_Channel *channel,
-               void *channel_ctx)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n");
-  GNUNET_break (channel == ch);
-  ch = NULL;
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Method called whenever another peer has added us to a channel
- * the other peer initiated.
- * Only called (once) upon reception of data with a message type which was
- * subscribed to in #GNUNET_CADET_connect.
- *
- * A call to #GNUNET_CADET_channel_destroy causes te channel to be ignored. In
- * this case the handler MUST return NULL.
- *
- * @param cls closure
- * @param channel new handle to the channel
- * @param initiator peer that started the channel
- * @param port Port this channel is for.
- * @param options CadetOption flag field, with all active option bits set to 1.
- *
- * @return initial channel context for the channel
- *         (can be NULL -- that's not an error)
- */
-static void *
-channel_incoming (void *cls,
-                  struct GNUNET_CADET_Channel * channel,
-                  const struct GNUNET_PeerIdentity * initiator,
-                  uint32_t port, enum GNUNET_CADET_ChannelOption options)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Incoming channel %p on port %u\n",
-              channel, port);
-  if (NULL != ch)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A channel already exists\n");
-    return NULL;
-  }
-  if (0 == listen_port)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not listening to channels\n");
-    return NULL;
-  }
-  ch = channel;
-  if (GNUNET_NO == echo)
-  {
-    listen_stdio ();
-    return NULL;
-  }
-  data_size = 0;
-  return NULL;
-}
-
-/**
- * @brief Send an echo request to the remote peer.
- *
- * @param cls Closure (NULL).
- * @param tc Task context.
- */
-static void
-send_echo (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || NULL == ch)
-    return;
-
-  GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     sizeof (struct GNUNET_MessageHeader),
-                                     &data_ready, NULL);
-}
-
-
-
-/**
- * Call CADET's monitor API, get info of one connection.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_PeerIdentity pid;
-  enum GNUNET_CADET_ChannelOption opt;
-
-  GNUNET_assert (NULL == ch);
-
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_public_key_from_string (target_id,
-                                                  strlen (target_id),
-                                                  &pid.public_key))
-  {
-    FPRINTF (stderr,
-             _("Invalid target `%s'\n"),
-             target_id);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id);
-  opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE;
-  ch = GNUNET_CADET_channel_create (mh, NULL, &pid, target_port, opt);
-  if (GNUNET_NO == echo)
-    listen_stdio ();
-  else
-    GNUNET_SCHEDULER_add_now (send_echo, NULL);
-}
-
-
-/**
- * Function called whenever a message is received.
- *
- * Each time the function must call #GNUNET_CADET_receive_done on the channel
- * in order to receive the next message. This doesn't need to be immediate:
- * can be delayed if some processing is done on the message.
- *
- * @param cls Closure (set from #GNUNET_CADET_connect).
- * @param channel Connection to the other end.
- * @param channel_ctx Place to store local state associated with the channel.
- * @param message The actual message.
- * @return #GNUNET_OK to keep the channel open,
- *         #GNUNET_SYSERR to close it (signal serious error).
- */
-static int
-data_callback (void *cls,
-               struct GNUNET_CADET_Channel *channel,
-               void **channel_ctx,
-               const struct GNUNET_MessageHeader *message)
-{
-  uint16_t len;
-  ssize_t done;
-  uint16_t off;
-  const char *buf;
-  GNUNET_break (ch == channel);
-
-  if (GNUNET_YES == echo)
-  {
-    if (0 != listen_port)
-    {
-      /* Just listening to echo incoming messages*/
-      GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
-                                        GNUNET_TIME_UNIT_FOREVER_REL,
-                                        sizeof (struct GNUNET_MessageHeader),
-                                        &data_ready, NULL);
-      return GNUNET_OK;
-    }
-    else
-    {
-      struct GNUNET_TIME_Relative latency;
-
-      latency = GNUNET_TIME_absolute_get_duration (echo_time);
-      echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
-      FPRINTF (stdout, "time: %s\n",
-               GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
-      echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                &send_echo, NULL);
-    }
-  }
-
-  len = ntohs (message->size) - sizeof (*message);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len);
-  buf = (const char *) &message[1];
-  off = 0;
-  while (off < len)
-  {
-    done = write (1, &buf[off], len - off);
-    if (done <= 0)
-    {
-      if (-1 == done)
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                             "write");
-      return GNUNET_SYSERR;
-    }
-    off += done;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called to retrieve information about all peers in CADET, called
- * once per peer.
- *
- * After last peer has been reported, an additional call with NULL is done.
- *
- * @param cls Closure.
- * @param peer Peer, or NULL on "EOF".
- * @param tunnel Do we have a tunnel towards this peer?
- * @param n_paths Number of known paths towards this peer.
- * @param best_path How long is the best path?
- *                  (0 = unknown, 1 = ourselves, 2 = neighbor)
- */
-static void
-peers_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
-                int tunnel, unsigned int n_paths, unsigned int best_path)
-{
-  if (NULL == peer)
-  {
-    if (GNUNET_YES != monitor_connections)
-    {
-      GNUNET_SCHEDULER_shutdown();
-    }
-    return;
-  }
-  FPRINTF (stdout, "%s tunnel: %c, paths: %u\n",
-           GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths);
-}
-
-/**
- * Method called to retrieve information about a specific peer
- * known to the service.
- *
- * @param cls Closure.
- * @param peer Peer ID.
- * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO
- * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO
- * @param n_paths Number of paths known towards peer.
- * @param paths Array of PEER_IDs representing all paths to reach the peer.
- *              Each path starts with the local peer.
- *              Each path ends with the destination peer (given in @c peer).
- */
-void
-peer_callback (void *cls,
-               const struct GNUNET_PeerIdentity *peer,
-               int tunnel,
-               int neighbor,
-               unsigned int n_paths,
-               struct GNUNET_PeerIdentity *paths)
-{
-}
-
-
-/**
- * Method called to retrieve information about all tunnels in CADET.
- *
- * @param cls Closure.
- * @param peer Destination peer.
- * @param channels Number of channels.
- * @param connections Number of connections.
- * @param estate Encryption state.
- * @param cstate Connectivity state.
- */
-void
-tunnels_callback (void *cls,
-                  const struct GNUNET_PeerIdentity *peer,
-                  unsigned int channels,
-                  unsigned int connections,
-                  uint16_t estate,
-                  uint16_t cstate)
-{
-  if (NULL == peer)
-  {
-    if (GNUNET_YES != monitor_connections)
-    {
-      GNUNET_SCHEDULER_shutdown();
-    }
-    return;
-  }
-  FPRINTF (stdout, "%s [ENC: %u, CON: %u] CHs: %u, CONNs: %u\n",
-           GNUNET_i2s_full (peer), estate, cstate, channels, connections);
-}
-
-
-/**
- * Method called to retrieve information about a specific tunnel the cadet peer
- * has established, o`r is trying to establish.
- *
- * @param cls Closure.
- * @param peer Peer towards whom the tunnel is directed.
- * @param n_channels Number of channels.
- * @param n_connections Number of connections.
- * @param channels Channels.
- * @param connections Connections.
- * @param estate Encryption status.
- * @param cstate Connectivity status.
- */
-void
-tunnel_callback (void *cls,
-                 const struct GNUNET_PeerIdentity *peer,
-                 unsigned int n_channels,
-                 unsigned int n_connections,
-                 uint32_t *channels,
-                 struct GNUNET_CADET_Hash *connections,
-                 unsigned int estate,
-                 unsigned int cstate)
-{
-  unsigned int i;
-
-  if (NULL != peer)
-  {
-    FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer));
-    FPRINTF (stdout, "- %u channels\n", n_channels);
-    for (i = 0; i < n_channels; i++)
-      FPRINTF (stdout, "   %u\n", channels[i]);
-    FPRINTF (stdout, "- %u connections\n", n_connections);
-    for (i = 0; i < n_connections; i++)
-      FPRINTF (stdout, "   %s\n", GM_h2s (&connections[i]));
-    FPRINTF (stdout, "- enc state: %u\n", estate);
-    FPRINTF (stdout, "- con state: %u\n", cstate);
-  }
-  if (GNUNET_YES != monitor_connections)
-  {
-    GNUNET_SCHEDULER_shutdown();
-  }
-  return;
-
-}
-
-
-/**
- * Call CADET's meta API, get all peers known to a peer.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-get_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
-    return;
-  }
-  GNUNET_CADET_get_peers (mh, &peers_callback, NULL);
-}
-
-
-/**
- * Call CADET's monitor API, get info of one peer.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-show_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_PeerIdentity pid;
-
-  if (GNUNET_OK !=
-    GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
-                                                strlen (peer_id),
-                                                &pid.public_key))
-  {
-    fprintf (stderr,
-             _("Invalid peer ID `%s'\n"),
-             peer_id);
-    GNUNET_SCHEDULER_shutdown();
-    return;
-  }
-  GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL);
-}
-
-/**
- * Call CADET's meta API, get all tunnels known to a peer.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-get_tunnels (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
-    return;
-  }
-  GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL);
-}
-
-
-/**
- * Call CADET's monitor API, get info of one tunnel.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_PeerIdentity pid;
-
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id,
-                                                  strlen (tunnel_id),
-                                                  &pid.public_key))
-  {
-    fprintf (stderr,
-             _("Invalid tunnel owner `%s'\n"),
-             tunnel_id);
-    GNUNET_SCHEDULER_shutdown();
-    return;
-  }
-  GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL);
-}
-
-
-/**
- * Call CADET's monitor API, get info of one channel.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-show_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
-}
-
-
-/**
- * Call CADET's monitor API, get info of one connection.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext
- */
-static void
-show_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
- * @param cfg configuration
- */
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  GNUNET_CADET_InboundChannelNotificationHandler *newch = NULL;
-  GNUNET_CADET_ChannelEndHandler *endch = NULL;
-  static const struct GNUNET_CADET_MessageHandler handlers[] = {
-    {&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0},
-    {NULL, 0, 0} /* FIXME add option to monitor msg types */
-  };
-  static uint32_t *ports = NULL;
-  /* FIXME add option to monitor apps */
-
-  target_id = args[0];
-  target_port = args[0] && args[1] ? atoi(args[1]) : 0;
-  if ( (0 != (request_peers | request_tunnels)
-        || 0 != monitor_connections
-        || NULL != tunnel_id
-        || NULL != conn_id
-        || NULL != channel_id)
-       && target_id != NULL)
-  {
-    FPRINTF (stderr,
-             _("You must NOT give a TARGET"
-               "when using 'request all' options\n"));
-    return;
-  }
-
-  if (NULL != target_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating channel to %s\n",
-                target_id);
-    GNUNET_SCHEDULER_add_now (&create_channel, NULL);
-    endch = &channel_ended;
-  }
-  else if (0 != listen_port)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Listen\n");
-    newch = &channel_incoming;
-    endch = &channel_ended;
-    ports = GNUNET_malloc (sizeof (uint32_t) * 2);
-    ports[0] = listen_port;
-  }
-  else if (NULL != peer_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n");
-    GNUNET_SCHEDULER_add_now (&show_peer, NULL);
-  }
-  else if (NULL != tunnel_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n");
-    GNUNET_SCHEDULER_add_now (&show_tunnel, NULL);
-  }
-  else if (NULL != channel_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n");
-    GNUNET_SCHEDULER_add_now (&show_channel, NULL);
-  }
-  else if (NULL != conn_id)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n");
-    GNUNET_SCHEDULER_add_now (&show_connection, NULL);
-  }
-  else if (GNUNET_YES == request_peers)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n");
-    GNUNET_SCHEDULER_add_now (&get_peers, NULL);
-  }
-  else if (GNUNET_YES == request_tunnels)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n");
-    GNUNET_SCHEDULER_add_now (&get_tunnels, NULL);
-  }
-  else
-  {
-    FPRINTF (stderr, "No action requested\n");
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to cadet\n");
-  mh = GNUNET_CADET_connect (cfg,
-                            NULL, /* cls */
-                            newch, /* new channel */
-                            endch, /* cleaner */
-                            handlers,
-                            ports);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done\n");
-  if (NULL == mh)
-    GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
-  else
-    sd = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                       shutdown_task, NULL);
-
-}
-
-
-/**
- * The main function to obtain peer information.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  int res;
-  const char helpstr[] = "Create channels and retreive info about cadets 
status.";
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-//     {'a', "channel", "TUNNEL_ID:CHANNEL_ID",
-//      gettext_noop ("provide information about a particular channel"),
-//      GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id},
-    {'C', "connection", "CONNECTION_ID",
-     gettext_noop ("provide information about a particular connection"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id},
-    {'e', "echo", NULL,
-     gettext_noop ("activate echo mode"),
-     GNUNET_NO, &GNUNET_GETOPT_set_one, &echo},
-//     {'m', "monitor", NULL,
-//      gettext_noop ("provide information about all events (continuously)"),
-//      GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_mode},
-    {'o', "open-port", NULL,
-     gettext_noop ("port to listen to (default; 0)"),
-     GNUNET_YES, &GNUNET_GETOPT_set_uint, &listen_port},
-    {'p', "peer", "PEER_ID",
-     gettext_noop ("provide information about a patricular peer"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id},
-    {'P', "peers", NULL,
-      gettext_noop ("provide information about all peers"),
-      GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers},
-    {'t', "tunnel", "TUNNEL_ID",
-     gettext_noop ("provide information about a particular tunnel"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id},
-    {'T', "tunnels", NULL,
-     gettext_noop ("provide information about all tunnels"),
-     GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels},
-
-    GNUNET_GETOPT_OPTION_END
-  };
-
-  monitor_connections = GNUNET_NO;
-
-  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
-    return 2;
-
-  res = GNUNET_PROGRAM_run (argc, argv, "gnunet-cadet (OPTIONS | TARGET PORT)",
-                            gettext_noop (helpstr),
-                            options, &run, NULL);
-
-  GNUNET_free ((void *) argv);
-
-  if (GNUNET_OK == res)
-    return 0;
-  else
-    return 1;
-}
-
-/* end of gnunet-cadet.c */

Deleted: gnunet/src/mesh/gnunet-service-cadet.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet.c      2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/gnunet-service-cadet.c      2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,181 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001-2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet.c
- * @brief GNUnet CADET service with encryption
- * @author Bartlomiej Polot
- *
- *  FIXME in progress:
- * - rekey - reliability interaction
- * - channel retransmit timing
- *
- * TODO:
- * - relay corking down to core
- * - set ttl relative to path length
- * TODO END
- *
- * Dictionary:
- * - peer: other cadet 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 "cadet.h"
-#include "gnunet_statistics_service.h"
-
-#include "gnunet-service-cadet_local.h"
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_hello.h"
-
-
-/******************************************************************************/
-/***********************      GLOBAL VARIABLES     
****************************/
-/******************************************************************************/
-
-/****************************** Global variables 
******************************/
-
-/**
- * Handle to the statistics service.
- */
-struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-struct GNUNET_PeerIdentity my_full_id;
-
-
-/**
- * Signal that shutdown is happening: prevent recover measures.
- */
-int shutting_down;
-
-/*************************** Static global variables 
**************************/
-
-/**
- * Own private key.
- */
-static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
-
-
-/******************************************************************************/
-/************************      MAIN FUNCTIONS      
****************************/
-/******************************************************************************/
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- * @param tc unused
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
-
-  shutting_down = GNUNET_YES;
-
-  GML_shutdown ();
-  GMH_shutdown ();
-  GMC_shutdown ();
-  GMT_shutdown ();
-  GMD_shutdown ();
-  GMP_shutdown ();
-
-  GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-  stats = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
-}
-
-
-/**
- * Process cadet requests.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
-
-  stats = GNUNET_STATISTICS_create ("cadet", 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");
-  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,
-              "STARTING SERVICE (CADET) for peer [%s]\n",
-              GNUNET_i2s (&my_full_id));
-
-  GML_init (server);    /* Local clients */
-  GMH_init (c);         /* Hellos */
-  GMC_init (c);         /* Connections */
-  GMP_init (c);         /* Peers */
-  GMD_init (c);         /* DHT */
-  GMT_init (c, my_private_key); /* Tunnels */
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cadet service running\n");
-}
-
-
-/**
- * The main function for the cadet service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  int ret;
-  int r;
-
-  shutting_down = GNUNET_NO;
-  r = GNUNET_SERVICE_run (argc, argv, "cadet", GNUNET_SERVICE_OPTION_NONE, 
&run,
-                          NULL);
-  GNUNET_free (my_private_key);
-  ret = (GNUNET_OK == r) ? 0 : 1;
-
-  return ret;
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_channel.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_channel.c      2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_channel.c      2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,2432 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-
-#include "cadet.h"
-#include "cadet_protocol.h"
-
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_local.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__)
-
-#define CADET_RETRANSMIT_TIME    GNUNET_TIME_relative_multiply(\
-                                    GNUNET_TIME_UNIT_MILLISECONDS, 250)
-#define CADET_RETRANSMIT_MARGIN  4
-
-
-/**
- * All the states a connection can be in.
- */
-enum CadetChannelState
-{
-  /**
-   * Uninitialized status, should never appear in operation.
-   */
-  CADET_CHANNEL_NEW,
-
-  /**
-   * Connection create message sent, waiting for ACK.
-   */
-  CADET_CHANNEL_SENT,
-
-  /**
-   * Connection confirmed, ready to carry traffic.
-   */
-  CADET_CHANNEL_READY,
-};
-
-
-/**
- * Info holder for channel messages in queues.
- */
-struct CadetChannelQueue
-{
-  /**
-   * Tunnel Queue.
-   */
-  struct CadetTunnel3Queue *tq;
-
-  /**
-   * Message type (DATA/DATA_ACK)
-   */
-  uint16_t type;
-
-  /**
-   * Message copy (for DATAs, to start retransmission timer)
-   */
-  struct CadetReliableMessage *copy;
-
-  /**
-   * Reliability (for DATA_ACKs, to access rel->ack_q)
-   */
-  struct CadetChannelReliability *rel;
-};
-
-
-/**
- * Info needed to retry a message in case it gets lost.
- */
-struct CadetReliableMessage
-{
-    /**
-     * Double linked list, FIFO style
-     */
-  struct CadetReliableMessage    *next;
-  struct CadetReliableMessage    *prev;
-
-    /**
-     * Type of message (payload, channel management).
-     */
-  int16_t type;
-
-    /**
-     * Tunnel Reliability queue this message is in.
-     */
-  struct CadetChannelReliability  *rel;
-
-    /**
-     * ID of the message (ACK needed to free)
-     */
-  uint32_t                      mid;
-
-  /**
-   * Tunnel Queue.
-   */
-  struct CadetChannelQueue       *chq;
-
-    /**
-     * When was this message issued (to calculate ACK delay)
-     */
-  struct GNUNET_TIME_Absolute   timestamp;
-
-  /* struct GNUNET_CADET_Data with payload */
-};
-
-
-/**
- * Info about the traffic state for a client in a channel.
- */
-struct CadetChannelReliability
-{
-    /**
-     * Channel this is about.
-     */
-  struct CadetChannel *ch;
-
-    /**
-     * DLL of messages sent and not yet ACK'd.
-     */
-  struct CadetReliableMessage        *head_sent;
-  struct CadetReliableMessage        *tail_sent;
-
-    /**
-     * DLL of messages received out of order.
-     */
-  struct CadetReliableMessage        *head_recv;
-  struct CadetReliableMessage        *tail_recv;
-
-    /**
-     * Messages received.
-     */
-  unsigned int                      n_recv;
-
-    /**
-     * Next MID to use for outgoing traffic.
-     */
-  uint32_t                          mid_send;
-
-    /**
-     * Next MID expected for incoming traffic.
-     */
-  uint32_t                          mid_recv;
-
-    /**
-     * Handle for queued unique data CREATE, DATA_ACK.
-     */
-  struct CadetChannelQueue           *uniq;
-
-    /**
-     * Can we send data to the client?
-     */
-  int                               client_ready;
-
-  /**
-   * Can the client send data to us?
-   */
-  int                               client_allowed;
-
-    /**
-     * Task to resend/poll in case no ACK is received.
-     */
-  GNUNET_SCHEDULER_TaskIdentifier   retry_task;
-
-    /**
-     * Counter for exponential backoff.
-     */
-  struct GNUNET_TIME_Relative       retry_timer;
-
-    /**
-     * How long does it usually take to get an ACK.
-     */
-  struct GNUNET_TIME_Relative       expected_delay;
-};
-
-
-/**
- * Struct containing all information regarding a channel to a remote client.
- */
-struct CadetChannel
-{
-    /**
-     * Tunnel this channel is in.
-     */
-  struct CadetTunnel3 *t;
-
-    /**
-     * Destination port of the channel.
-     */
-  uint32_t port;
-
-    /**
-     * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
-     */
-  CADET_ChannelNumber gid;
-
-    /**
-     * Local tunnel number for root (owner) client.
-     * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
-     */
-  CADET_ChannelNumber lid_root;
-
-    /**
-     * Local tunnel number for local destination clients (incoming number)
-     * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0).
-     */
-  CADET_ChannelNumber lid_dest;
-
-    /**
-     * Channel state.
-     */
-  enum CadetChannelState state;
-
-    /**
-     * Is the tunnel bufferless (minimum latency)?
-     */
-  int nobuffer;
-
-    /**
-     * Is the tunnel reliable?
-     */
-  int reliable;
-
-    /**
-     * Last time the channel was used
-     */
-  struct GNUNET_TIME_Absolute timestamp;
-
-    /**
-     * Client owner of the tunnel, if any
-     */
-  struct CadetClient *root;
-
-    /**
-     * Client destination of the tunnel, if any.
-     */
-  struct CadetClient *dest;
-
-    /**
-     * Flag to signal the destruction of the channel.
-     * If this is set GNUNET_YES the channel will be destroyed
-     * when the queue is empty.
-     */
-  int destroy;
-
-    /**
-     * Total (reliable) messages pending ACK for this channel.
-     */
-  unsigned int pending_messages;
-
-    /**
-     * Reliability data.
-     * Only present (non-NULL) at the owner of a tunnel.
-     */
-  struct CadetChannelReliability *root_rel;
-
-    /**
-     * Reliability data.
-     * Only present (non-NULL) at the destination of a tunnel.
-     */
-  struct CadetChannelReliability *dest_rel;
-
-};
-
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-/**
- * Destroy a reliable message after it has been acknowledged, either by
- * direct mid ACK or bitfield. Updates the appropriate data structures and
- * timers and frees all memory.
- *
- * @param copy Message that is no longer needed: remote peer got it.
- * @param update_time Is the timing information relevant?
- *                    If this message is ACK in a batch the timing information
- *                    is skewed by the retransmission, count only for the
- *                    retransmitted message.
- */
-static int
-rel_message_free (struct CadetReliableMessage *copy, int update_time);
-
-/**
- * send a channel create message.
- *
- * @param ch Channel for which to send.
- */
-static void
-send_create (struct CadetChannel *ch);
-
-/**
- * Confirm we got a channel create, FWD ack.
- *
- * @param ch The channel to confirm.
- * @param fwd Should we send a FWD ACK? (going dest->root)
- * @param reaction This ACK is a reaction to a duplicate CREATE, don't save.
- */
-static void
-send_ack (struct CadetChannel *ch, int fwd, int reaction);
-
-
-
-/**
- * Test if the channel is loopback: both root and dest are on the local peer.
- *
- * @param ch Channel to test.
- *
- * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise.
- */
-static int
-is_loopback (const struct CadetChannel *ch)
-{
-  if (NULL != ch->t)
-    return GMT_is_loopback (ch->t);
-
-  return (NULL != ch->root && NULL != ch->dest);
-}
-
-
-/**
- * Save a copy of the data message for later retransmission.
- *
- * @param msg Message to copy.
- * @param mid Message ID.
- * @param rel Reliability data for retransmission.
- */
-static struct CadetReliableMessage *
-copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid,
-              struct CadetChannelReliability *rel)
-{
-  struct CadetReliableMessage *copy;
-  uint16_t size;
-
-  size = ntohs (msg->header.size);
-  copy = GNUNET_malloc (sizeof (*copy) + size);
-  copy->mid = mid;
-  copy->rel = rel;
-  copy->type = GNUNET_MESSAGE_TYPE_CADET_DATA;
-  memcpy (&copy[1], msg, size);
-
-  return copy;
-}
-
-/**
- * We have received a message out of order, or the client is not ready.
- * Buffer it until we receive an ACK from the client or the missing
- * message from the channel.
- *
- * @param msg Message to buffer (MUST be of type CADET_DATA).
- * @param rel Reliability data to the corresponding direction.
- */
-static void
-add_buffered_data (const struct GNUNET_CADET_Data *msg,
-                   struct CadetChannelReliability *rel)
-{
-  struct CadetReliableMessage *copy;
-  struct CadetReliableMessage *prev;
-  uint32_t mid;
-
-  mid = ntohl (msg->mid);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data %u\n", mid);
-
-  rel->n_recv++;
-
-  // FIXME do something better than O(n), although n < 64...
-  // FIXME start from the end (most messages are the latest ones)
-  for (prev = rel->head_recv; NULL != prev; prev = prev->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid);
-    if (prev->mid == mid)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n");
-      return;
-    }
-    else if (GM_is_pid_bigger (prev->mid, mid))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n");
-      copy = copy_message (msg, mid, rel);
-      GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv,
-                                          prev, copy);
-      return;
-    }
-  }
-  copy = copy_message (msg, mid, rel);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail!\n");
-  GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n");
-}
-
-
-/**
- * Add a destination client to a channel, initializing all data structures
- * in the channel and the client.
- *
- * @param ch Channel to which add the destination.
- * @param c Client which to add to the channel.
- */
-static void
-add_destination (struct CadetChannel *ch, struct CadetClient *c)
-{
-  if (NULL != ch->dest)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* Assign local id as destination */
-  ch->lid_dest = GML_get_next_chid (c);
-
-  /* Store in client's hashmap */
-  GML_channel_add (c, ch->lid_dest, ch);
-
-  GNUNET_break (NULL == ch->dest_rel);
-  ch->dest_rel = GNUNET_new (struct CadetChannelReliability);
-  ch->dest_rel->ch = ch;
-  ch->dest_rel->expected_delay.rel_value_us = 0;
-  ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME;
-
-  ch->dest = c;
-}
-
-
-/**
- * Set options in a channel, extracted from a bit flag field.
- *
- * @param ch Channel to set options to.
- * @param options Bit array in host byte order.
- */
-static void
-channel_set_options (struct CadetChannel *ch, uint32_t options)
-{
-  ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ?
-  GNUNET_YES : GNUNET_NO;
-  ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ?
-  GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Get a bit flag field with the options of a channel.
- *
- * @param ch Channel to get options from.
- *
- * @return Bit array in host byte order.
- */
-static uint32_t
-channel_get_options (struct CadetChannel *ch)
-{
-  uint32_t options;
-
-  options = 0;
-  if (ch->nobuffer)
-    options |= GNUNET_CADET_OPTION_NOBUFFER;
-  if (ch->reliable)
-    options |= GNUNET_CADET_OPTION_RELIABLE;
-
-  return options;
-}
-
-
-/**
- * Notify a client that the channel is no longer valid.
- *
- * @param ch Channel that is destroyed.
- * @param local_only Should we avoid sending it to other peers?
- */
-static void
-send_destroy (struct CadetChannel *ch, int local_only)
-{
-  struct GNUNET_CADET_ChannelManage msg;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-  msg.header.size = htons (sizeof (msg));
-  msg.chid = htonl (ch->gid);
-
-  /* If root is not NULL, notify.
-   * If it's NULL, check lid_root. When a local destroy comes in, root
-   * is set to NULL but lid_root is left untouched. In this case, do nothing,
-   * the client is the one who requested the channel to be destroyed.
-   */
-  if (NULL != ch->root)
-    GML_send_channel_destroy (ch->root, ch->lid_root);
-  else if (0 == ch->lid_root && GNUNET_NO == local_only)
-    GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
-
-  if (NULL != ch->dest)
-    GML_send_channel_destroy (ch->dest, ch->lid_dest);
-  else if (0 == ch->lid_dest && GNUNET_NO == local_only)
-    GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL);
-}
-
-
-/**
- * Notify the destination client that a new incoming channel was created.
- *
- * @param ch Channel that was created.
- */
-static void
-send_client_create (struct CadetChannel *ch)
-{
-  uint32_t opt;
-
-  if (NULL == ch->dest)
-    return;
-
-  opt = 0;
-  opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
-  opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
-  GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt,
-                           GMT_get_destination (ch->t));
-
-}
-
-
-/**
- * Send data to a client.
- *
- * If the client is ready, send directly, otherwise buffer while listening
- * for a local ACK.
- *
- * @param ch Channel
- * @param msg Message.
- * @param fwd Is this a fwd (root->dest) message?
- */
-static void
-send_client_data (struct CadetChannel *ch,
-                  const struct GNUNET_CADET_Data *msg,
-                  int fwd)
-{
-  if (fwd)
-  {
-    if (ch->dest_rel->client_ready)
-      GML_send_data (ch->dest, msg, ch->lid_dest);
-    else
-      add_buffered_data (msg, ch->dest_rel);
-  }
-  else
-  {
-    if (ch->root_rel->client_ready)
-      GML_send_data (ch->root, msg, ch->lid_root);
-    else
-      add_buffered_data (msg, ch->root_rel);
-  }
-}
-
-
-/**
- * Send a buffered message to the client, for in order delivery or
- * as result of client ACK.
- *
- * @param ch Channel on which to empty the message buffer.
- * @param c Client to send to.
- * @param fwd Is this to send FWD data?.
- */
-static void
-send_client_buffered_data (struct CadetChannel *ch,
-                           struct CadetClient *c,
-                           int fwd)
-{
-  struct CadetReliableMessage *copy;
-  struct CadetChannelReliability *rel;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n");
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-  if (GNUNET_NO == rel->client_ready)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n");
-    return;
-  }
-
-  copy = rel->head_recv;
-  /* We never buffer channel management messages */
-  if (NULL != copy)
-  {
-    if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
-    {
-      struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) &copy[1];
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           " have %u! now expecting %u\n",
-           copy->mid, rel->mid_recv + 1);
-      send_client_data (ch, msg, fwd);
-      rel->n_recv--;
-      rel->mid_recv++;
-      GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE RECV %p\n", copy);
-      GNUNET_free (copy);
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           " reliable && don't have %u, next is %u\n",
-           rel->mid_recv,
-           copy->mid);
-      if (GNUNET_YES == ch->destroy)
-      {
-        /* We don't have the next data piece and the remote peer has closed the
-         * channel. We won't receive it anymore, so just destroy the channel.
-         * FIXME: wait some time to allow other connections to
-         *        deliver missing messages
-         */
-        send_destroy (ch, GNUNET_YES);
-        GMCH_destroy (ch);
-      }
-    }
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n");
-}
-
-
-/**
- * Allow a client to send more data.
- *
- * In case the client was already allowed to send data, do nothing.
- *
- * @param ch Channel.
- * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root)
- */
-static void
-send_client_ack (struct CadetChannel *ch, int fwd)
-{
-  struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel;
-  struct CadetClient *c = fwd ? ch->root : ch->dest;
-
-  if (NULL == c)
-  {
-    GNUNET_break (GNUNET_NO != ch->destroy);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "  sending %s ack to client on channel %s\n",
-       GM_f2s (fwd), GMCH_2s (ch));
-
-  if (NULL == rel)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if (GNUNET_YES == rel->client_allowed)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  already allowed\n");
-    return;
-  }
-  rel->client_allowed = GNUNET_YES;
-
-  GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest);
-}
-
-
-/**
- * Notify the root that the destination rejected the channel.
- *
- * @param ch Rejected channel.
- */
-static void
-send_client_nack (struct CadetChannel *ch)
-{
-  if (NULL == ch->root)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  GML_send_channel_nack (ch->root, ch->lid_root);
-}
-
-
-/**
- * We haven't received an ACK after a certain time: restransmit the message.
- *
- * @param cls Closure (CadetChannelReliability with the message to restransmit)
- * @param tc TaskContext.
- */
-static void
-channel_retransmit_message (void *cls,
-                            const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetChannelReliability *rel = cls;
-  struct CadetReliableMessage *copy;
-  struct CadetChannel *ch;
-  struct GNUNET_CADET_Data *payload;
-  int fwd;
-
-  rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  ch = rel->ch;
-  copy = rel->head_sent;
-  if (NULL == copy)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  payload = (struct GNUNET_CADET_Data *) &copy[1];
-  fwd = (rel == ch->root_rel);
-
-  /* Message not found in the queue that we are going to use. */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid);
-
-  GMCH_send_prebuilt_message (&payload->header, ch, fwd, copy);
-  GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
-}
-
-
-/**
- * We haven't received an Channel ACK after a certain time: resend the CREATE.
- *
- * @param cls Closure (CadetChannelReliability of the channel to recreate)
- * @param tc TaskContext.
- */
-static void
-channel_recreate (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetChannelReliability *rel = cls;
-
-  rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RE-CREATE\n");
-  GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
-
-  if (rel == rel->ch->root_rel)
-  {
-    send_create (rel->ch);
-  }
-  else if (rel == rel->ch->dest_rel)
-  {
-    send_ack (rel->ch, GNUNET_YES, GNUNET_NO);
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-
-}
-
-
-/**
- * Message has been sent: start retransmission timer.
- *
- * @param cls Closure (queue structure).
- * @param t Tunnel.
- * @param q Queue handler (no longer valid).
- * @param type Type of message.
- * @param size Size of the message.
- */
-static void
-ch_message_sent (void *cls,
-                 struct CadetTunnel3 *t,
-                 struct CadetTunnel3Queue *q,
-                 uint16_t type, size_t size)
-{
-  struct CadetChannelQueue *chq = cls;
-  struct CadetReliableMessage *copy = chq->copy;
-  struct CadetChannelReliability *rel;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "channel message sent callback %s\n",
-       GM_m2s (chq->type));
-
-  switch (chq->type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT DATA MID %u\n", copy->mid);
-      GNUNET_assert (chq == copy->chq);
-      copy->timestamp = GNUNET_TIME_absolute_get ();
-      rel = copy->rel;
-      if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task)
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "!! scheduling retry in 4 * %s\n",
-             GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
-                                                     GNUNET_YES));
-        if (0 != rel->expected_delay.rel_value_us)
-        {
-          LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay != 0\n");
-          rel->retry_timer =
-          GNUNET_TIME_relative_multiply (rel->expected_delay,
-                                         CADET_RETRANSMIT_MARGIN);
-        }
-        else
-        {
-          LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay reset\n");
-          rel->retry_timer = CADET_RETRANSMIT_TIME;
-        }
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "!! using delay %s\n",
-             GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
-                                                     GNUNET_NO));
-        rel->retry_task =
-            GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
-                                          &channel_retransmit_message, rel);
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "!! retry task %u\n", rel->retry_task);
-      }
-      copy->chq = NULL;
-      break;
-
-
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT %s\n", GM_m2s (chq->type));
-      rel = chq->rel;
-      GNUNET_assert (rel->uniq == chq);
-      rel->uniq = NULL;
-
-      if (CADET_CHANNEL_READY != rel->ch->state
-          && GNUNET_MESSAGE_TYPE_CADET_DATA_ACK != type
-          && GNUNET_NO == rel->ch->destroy)
-      {
-        GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rel->retry_task);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! STD BACKOFF %s\n",
-             GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
-                                                     GNUNET_NO));
-        rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
-        rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
-                                                        &channel_recreate, 
rel);
-      }
-      break;
-
-    default:
-      GNUNET_break (0);
-  }
-
-  GNUNET_free (chq);
-}
-
-
-/**
- * send a channel create message.
- *
- * @param ch Channel for which to send.
- */
-static void
-send_create (struct CadetChannel *ch)
-{
-  struct GNUNET_CADET_ChannelCreate msgcc;
-
-  msgcc.header.size = htons (sizeof (msgcc));
-  msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
-  msgcc.chid = htonl (ch->gid);
-  msgcc.port = htonl (ch->port);
-  msgcc.opt = htonl (channel_get_options (ch));
-
-  GMCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL);
-}
-
-
-/**
- * Confirm we got a channel create or FWD ack.
- *
- * @param ch The channel to confirm.
- * @param fwd Should we send a FWD ACK? (going dest->root)
- * @param reaction This ACK is a reaction to a duplicate CREATE, don't save.
- */
-static void
-send_ack (struct CadetChannel *ch, int fwd, int reaction)
-{
-  struct GNUNET_CADET_ChannelManage msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending channel %s ack for channel %s\n",
-       GM_f2s (fwd), GMCH_2s (ch));
-
-  msg.chid = htonl (ch->gid);
-  GMCH_send_prebuilt_message (&msg.header, ch, !fwd, reaction ? &msg : NULL);
-}
-
-
-/**
- * Send a message and don't keep any info about it: we won't need to cancel it
- * or resend it.
- *
- * @param msg Header of the message to fire away.
- * @param ch Channel on which the message should go.
- * @param force Is this a forced (undroppable) message?
- */
-static void
-fire_and_forget (const struct GNUNET_MessageHeader *msg,
-                 struct CadetChannel *ch,
-                 int force)
-{
-  GNUNET_break (NULL == GMT_send_prebuilt_message (msg, ch->t, NULL,
-                                                   force, NULL, NULL));
-}
-
-
-/**
- * Notify that a channel create didn't succeed.
- *
- * @param ch The channel to reject.
- */
-static void
-send_nack (struct CadetChannel *ch)
-{
-  struct GNUNET_CADET_ChannelManage msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "  sending channel NACK for channel %s\n",
-       GMCH_2s (ch));
-
-  msg.chid = htonl (ch->gid);
-  GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
-}
-
-
-/**
- * Destroy all reliable messages queued for a channel,
- * during a channel destruction.
- * Frees the reliability structure itself.
- *
- * @param rel Reliability data for a channel.
- */
-static void
-channel_rel_free_all (struct CadetChannelReliability *rel)
-{
-  struct CadetReliableMessage *copy;
-  struct CadetReliableMessage *next;
-
-  if (NULL == rel)
-    return;
-
-  for (copy = rel->head_recv; NULL != copy; copy = next)
-  {
-    next = copy->next;
-    GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH RECV %p\n", copy);
-    GNUNET_break (NULL == copy->chq);
-    GNUNET_free (copy);
-  }
-  for (copy = rel->head_sent; NULL != copy; copy = next)
-  {
-    next = copy->next;
-    GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH %p\n", copy);
-    if (NULL != copy->chq)
-    {
-      if (NULL != copy->chq->tq)
-      {
-        GMT_cancel (copy->chq->tq);
-        /* ch_message_sent will free copy->q */
-      }
-      else
-      {
-        GNUNET_free (copy->chq);
-        GNUNET_break (0);
-      }
-    }
-    GNUNET_free (copy);
-  }
-  if (NULL != rel->uniq && NULL != rel->uniq->tq)
-  {
-    GMT_cancel (rel->uniq->tq);
-    /* ch_message_sent is called freeing uniq */
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
-  {
-    GNUNET_SCHEDULER_cancel (rel->retry_task);
-    rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_free (rel);
-}
-
-
-/**
- * Mark future messages as ACK'd.
- *
- * @param rel Reliability data.
- * @param msg DataACK message with a bitfield of future ACK'd messages.
- */
-static void
-channel_rel_free_sent (struct CadetChannelReliability *rel,
-                       const struct GNUNET_CADET_DataACK *msg)
-{
-  struct CadetReliableMessage *copy;
-  struct CadetReliableMessage *next;
-  uint64_t bitfield;
-  uint64_t mask;
-  uint32_t mid;
-  uint32_t target;
-  unsigned int i;
-
-  bitfield = msg->futures;
-  mid = ntohl (msg->mid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-              "!!! free_sent_reliable %u %llX\n",
-              mid, bitfield);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-              " rel %p, head %p\n",
-              rel, rel->head_sent);
-  for (i = 0, copy = rel->head_sent;
-       i < 64 && NULL != copy && 0 != bitfield;
-       i++)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-                " trying bit %u (mid %u)\n",
-                i, mid + i + 1);
-    mask = 0x1LL << i;
-    if (0 == (bitfield & mask))
-     continue;
-
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n");
-    /* Bit was set, clear the bit from the bitfield */
-    bitfield &= ~mask;
-
-    /* The i-th bit was set. Do we have that copy? */
-    /* Skip copies with mid < target */
-    target = mid + i + 1;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target);
-    while (NULL != copy && GM_is_pid_bigger (target, copy->mid))
-      copy = copy->next;
-
-    /* Did we run out of copies? (previously freed, it's ok) */
-    if (NULL == copy)
-    {
-     LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n");
-     return;
-    }
-
-    /* Did we overshoot the target? (previously freed, it's ok) */
-    if (GM_is_pid_bigger (copy->mid, target))
-    {
-     LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid);
-     continue;
-    }
-
-    /* Now copy->mid == target, free it */
-    next = copy->next;
-    GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES));
-    copy = next;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n");
-}
-
-
-/**
- * Destroy a reliable message after it has been acknowledged, either by
- * direct mid ACK or bitfield. Updates the appropriate data structures and
- * timers and frees all memory.
- *
- * @param copy Message that is no longer needed: remote peer got it.
- * @param update_time Is the timing information relevant?
- *                    If this message is ACK in a batch the timing information
- *                    is skewed by the retransmission, count only for the
- *                    retransmitted message.
- *
- * @return #GNUNET_YES if channel was destroyed as a result of the call,
- *         #GNUNET_NO otherwise.
- */
-static int
-rel_message_free (struct CadetReliableMessage *copy, int update_time)
-{
-  struct CadetChannelReliability *rel;
-  struct GNUNET_TIME_Relative time;
-
-  rel = copy->rel;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid);
-  if (update_time)
-  {
-    time = GNUNET_TIME_absolute_get_duration (copy->timestamp);
-    if (0 == rel->expected_delay.rel_value_us)
-      rel->expected_delay = time;
-    else
-    {
-      rel->expected_delay.rel_value_us *= 7;
-      rel->expected_delay.rel_value_us += time.rel_value_us;
-      rel->expected_delay.rel_value_us /= 8;
-    }
-    LOG (GNUNET_ERROR_TYPE_INFO, "!!!  took %s, new delay %s\n",
-         GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO),
-         GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
-                                                 GNUNET_NO));
-    rel->retry_timer = rel->expected_delay;
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO, "!!! batch free, ignoring timing\n");
-  }
-  rel->ch->pending_messages--;
-  if (NULL != copy->chq)
-  {
-    GMT_cancel (copy->chq->tq);
-    /* copy->q is set to NULL by ch_message_sent */
-  }
-  GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE %p\n", copy);
-  GNUNET_free (copy);
-
-  if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages)
-  {
-    GMCH_destroy (rel->ch);
-    return GNUNET_YES;
-  }
-  return GNUNET_NO;
-}
-
-
-/**
- * Channel was ACK'd by remote peer, mark as ready and cancel retransmission.
- *
- * @param ch Channel to mark as ready.
- * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK)
- */
-static void
-channel_confirm (struct CadetChannel *ch, int fwd)
-{
-  struct CadetChannelReliability *rel;
-  enum CadetChannelState oldstate;
-
-  rel = fwd ? ch->root_rel : ch->dest_rel;
-  if (NULL == rel)
-  {
-    GNUNET_break (GNUNET_NO != ch->destroy);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  channel confirm %s %s\n",
-       GM_f2s (fwd), GMCH_2s (ch));
-  oldstate = ch->state;
-  ch->state = CADET_CHANNEL_READY;
-
-  if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch))
-  {
-    rel->client_ready = GNUNET_YES;
-    rel->expected_delay = rel->retry_timer;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  !! retry timer confirm %s\n",
-         GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO));
-    if (GMT_get_connections_buffer (ch->t) > 0 || GMT_is_loopback (ch->t))
-      send_client_ack (ch, fwd);
-
-    if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
-    {
-      GNUNET_SCHEDULER_cancel (rel->retry_task);
-      rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-    else if (NULL != rel->uniq)
-    {
-      GMT_cancel (rel->uniq->tq);
-      /* ch_message_sent will free and NULL uniq */
-    }
-    else
-    {
-      if (GNUNET_NO == is_loopback (ch))
-      {
-        /* We SHOULD have been trying to retransmit this! */
-        GNUNET_break (0);
-      }
-    }
-  }
-
-  /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */
-  if (GNUNET_YES == fwd)
-    send_ack (ch, GNUNET_NO, GNUNET_NO);
-}
-
-
-/**
- * Save a copy to retransmit in case it gets lost.
- *
- * Initializes all needed callbacks and timers.
- *
- * @param ch Channel this message goes on.
- * @param msg Message to copy.
- * @param fwd Is this fwd traffic?
- */
-static struct CadetReliableMessage *
-channel_save_copy (struct CadetChannel *ch,
-                   const struct GNUNET_MessageHeader *msg,
-                   int fwd)
-{
-  struct CadetChannelReliability *rel;
-  struct CadetReliableMessage *copy;
-  uint32_t mid;
-  uint16_t type;
-  uint16_t size;
-
-  rel = fwd ? ch->root_rel : ch->dest_rel;
-  mid = rel->mid_send - 1;
-  type = ntohs (msg->type);
-  size = ntohs (msg->size);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u %s\n", mid, GM_m2s (type));
-  copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", copy);
-  copy->mid = mid;
-  copy->rel = rel;
-  copy->type = type;
-  memcpy (&copy[1], msg, size);
-  GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
-  ch->pending_messages++;
-
-  return copy;
-}
-
-
-/**
- * Create a new channel.
- *
- * @param t Tunnel this channel is in.
- * @param owner Client that owns the channel, NULL for foreign channels.
- * @param lid_root Local ID for root client.
- *
- * @return A new initialized channel. NULL on error.
- */
-static struct CadetChannel *
-channel_new (struct CadetTunnel3 *t,
-             struct CadetClient *owner,
-             CADET_ChannelNumber lid_root)
-{
-  struct CadetChannel *ch;
-
-  ch = GNUNET_new (struct CadetChannel);
-  ch->root = owner;
-  ch->lid_root = lid_root;
-  ch->t = t;
-
-  GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
-
-  if (NULL != owner)
-  {
-    ch->gid = GMT_get_next_chid (t);
-    GML_channel_add (owner, lid_root, ch);
-  }
-  GMT_add_channel (t, ch);
-
-  return ch;
-}
-
-
-/**
- * Handle a loopback message: call the appropriate handler for the message 
type.
- *
- * @param ch Channel this message is on.
- * @param msgh Message header.
- * @param fwd Is this FWD traffic?
- */
-void
-handle_loopback (struct CadetChannel *ch,
-                 const struct GNUNET_MessageHeader *msgh,
-                 int fwd)
-{
-  uint16_t type;
-
-  type = ntohs (msgh->type);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Loopback %s %s message!\n",
-       GM_f2s (fwd), GM_m2s (type));
-
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-      /* Don't send hop ACK, wait for client to ACK */
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SEND loopback %u (%u)\n",
-           ntohl (((struct GNUNET_CADET_Data *) msgh)->mid), ntohs 
(msgh->size));
-      GMCH_handle_data (ch, (struct GNUNET_CADET_Data *) msgh, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      GMCH_handle_data_ack (ch, (struct GNUNET_CADET_DataACK *) msgh, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-      GMCH_handle_create (ch->t,
-                          (struct GNUNET_CADET_ChannelCreate *) msgh);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-      GMCH_handle_ack (ch,
-                       (struct GNUNET_CADET_ChannelManage *) msgh,
-                       fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      GMCH_handle_nack (ch);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-      GMCH_handle_destroy (ch,
-                           (struct GNUNET_CADET_ChannelManage *) msgh,
-                           fwd);
-      break;
-
-    default:
-      GNUNET_break_op (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "end-to-end message not known (%u)\n",
-           ntohs (msgh->type));
-  }
-}
-
-
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Destroy a channel and free all resources.
- *
- * @param ch Channel to destroy.
- */
-void
-GMCH_destroy (struct CadetChannel *ch)
-{
-  struct CadetClient *c;
-  struct CadetTunnel3 *t;
-
-  if (NULL == ch)
-    return;
-  if (2 == ch->destroy)
-    return; /* recursive call */
-  ch->destroy = 2;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n",
-              GMT_2s (ch->t), ch->gid);
-  GMCH_debug (ch);
-
-  c = ch->root;
-  if (NULL != c)
-  {
-    GML_channel_remove (c, ch->lid_root, ch);
-  }
-
-  c = ch->dest;
-  if (NULL != c)
-  {
-    GML_channel_remove (c, ch->lid_dest, ch);
-  }
-
-  channel_rel_free_all (ch->root_rel);
-  channel_rel_free_all (ch->dest_rel);
-
-  t = ch->t;
-  GMT_remove_channel (t, ch);
-  GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO);
-
-  GNUNET_free (ch);
-  GMT_destroy_if_empty (t);
-}
-
-
-/**
- * Get the channel's public ID.
- *
- * @param ch Channel.
- *
- * @return ID used to identify the channel with the remote peer.
- */
-CADET_ChannelNumber
-GMCH_get_id (const struct CadetChannel *ch)
-{
-  return ch->gid;
-}
-
-
-/**
- * Get the channel tunnel.
- *
- * @param ch Channel to get the tunnel from.
- *
- * @return tunnel of the channel.
- */
-struct CadetTunnel3 *
-GMCH_get_tunnel (const struct CadetChannel *ch)
-{
-  return ch->t;
-}
-
-
-/**
- * Get free buffer space towards the client on a specific channel.
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - 64]
- */
-unsigned int
-GMCH_get_buffer (struct CadetChannel *ch, int fwd)
-{
-  struct CadetChannelReliability *rel;
-
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-
-  /* If rel is NULL it means that the end is not yet created,
-   * most probably is a loopback channel at the point of sending
-   * the ChannelCreate to itself.
-   */
-  if (NULL == rel)
-    return 64;
-
-  return (64 - rel->n_recv);
-}
-
-
-/**
- * Get flow control status of end point: is client allow to send?
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic? (Request root status).
- *
- * @return #GNUNET_YES if client is allowed to send us data.
- */
-int
-GMCH_get_allowed (struct CadetChannel *ch, int fwd)
-{
-  struct CadetChannelReliability *rel;
-
-  rel = fwd ? ch->root_rel : ch->dest_rel;
-
-  if (NULL == rel)
-  {
-    /* Probably shutting down: root/dest NULL'ed to mark disconnection */
-    GNUNET_break (GNUNET_NO != ch->destroy);
-    return 0;
-  }
-
-  return rel->client_allowed;
-}
-
-
-/**
- * Is the root client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GMCH_is_origin (struct CadetChannel *ch, int fwd)
-{
-  struct CadetClient *c;
-
-  c = fwd ? ch->root : ch->dest;
-  return NULL != c;
-}
-
-
-/**
- * Is the destination client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GMCH_is_terminal (struct CadetChannel *ch, int fwd)
-{
-  struct CadetClient *c;
-
-  c = fwd ? ch->dest : ch->root;
-  return NULL != c;
-}
-
-
-/**
- * Send an end-to-end ACK message for the most recent in-sequence payload.
- *
- * If channel is not reliable, do nothing.
- *
- * @param ch Channel this is about.
- * @param fwd Is for FWD traffic? (ACK dest->owner)
- */
-void
-GMCH_send_data_ack (struct CadetChannel *ch, int fwd)
-{
-  struct GNUNET_CADET_DataACK msg;
-  struct CadetChannelReliability *rel;
-  struct CadetReliableMessage *copy;
-  unsigned int delta;
-  uint64_t mask;
-  uint32_t ack;
-
-  if (GNUNET_NO == ch->reliable)
-  {
-    return;
-  }
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-  ack = rel->mid_recv - 1;
-  LOG (GNUNET_ERROR_TYPE_INFO, "===> DATA_ACK for %u\n", ack);
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK);
-  msg.header.size = htons (sizeof (msg));
-  msg.chid = htonl (ch->gid);
-  msg.futures = 0;
-  for (copy = rel->head_recv; NULL != copy; copy = copy->next)
-  {
-    if (copy->type != GNUNET_MESSAGE_TYPE_CADET_DATA)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "!!  Type %s, expected DATA\n",
-           GM_m2s (copy->type));
-      continue;
-    }
-    if (copy->mid == ack + 1)
-    {
-      ack++;
-      continue;
-    }
-    delta = copy->mid - (ack + 1);
-    if (63 < delta)
-      break;
-    mask = 0x1LL << delta;
-    msg.futures |= mask;
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         " !! setting bit for %u (delta %u) (%llX) -> %llX\n",
-         copy->mid, delta, mask, msg.futures);
-  }
-  msg.mid = htonl (ack);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "!!! ACK for %u, futures %llX\n",
-       ack, msg.futures);
-
-  GMCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n");
-}
-
-
-/**
- * Allow a client to send us more data, in case it was choked.
- *
- * @param ch Channel.
- * @param fwd Is this about FWD traffic? (Root client).
- */
-void
-GMCH_allow_client (struct CadetChannel *ch, int fwd)
-{
-  struct CadetChannelReliability *rel;
-  unsigned int buffer;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n");
-
-  if (CADET_CHANNEL_READY != ch->state)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n");
-    return;
-  }
-
-  if (GNUNET_YES == ch->reliable)
-  {
-    rel = fwd ? ch->root_rel : ch->dest_rel;
-    if (NULL == rel)
-    {
-      GNUNET_break (GNUNET_NO != ch->destroy);
-      return;
-    }
-    if (NULL != rel->head_sent)
-    {
-      if (64 <= rel->mid_send - rel->head_sent->mid)
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n");
-        return;
-      }
-      else
-        LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n",
-             rel->head_sent->mid, rel->mid_send);
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n");
-    }
-  }
-
-  if (is_loopback (ch))
-    buffer = GMCH_get_buffer (ch, fwd);
-  else
-    buffer = GMT_get_connections_buffer (ch->t);
-
-  if (0 == buffer)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n");
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer);
-  send_client_ack (ch, fwd);
-}
-
-
-/**
- * Log channel info.
- *
- * @param ch Channel.
- */
-void
-GMCH_debug (struct CadetChannel *ch)
-{
-  if (NULL == ch)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n");
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n",
-              GMT_2s (ch->t), ch->gid, ch);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  root %p/%p\n",
-              ch->root, ch->root_rel);
-  if (NULL != ch->root)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->root));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
-                ch->root_rel->client_ready ? "YES" : "NO");
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_root);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  dest %p/%p\n",
-              ch->dest, ch->dest_rel);
-  if (NULL != ch->dest)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->dest));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
-                ch->dest_rel->client_ready ? "YES" : "NO");
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_dest);
-  }
-}
-
-
-/**
- * Handle an ACK given by a client.
- *
- * Mark client as ready and send him any buffered data we could have for him.
- *
- * @param ch Channel.
- * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK)
- */
-void
-GMCH_handle_local_ack (struct CadetChannel *ch, int fwd)
-{
-  struct CadetChannelReliability *rel;
-  struct CadetClient *c;
-
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-  c   = fwd ? ch->dest     : ch->root;
-
-  rel->client_ready = GNUNET_YES;
-  send_client_buffered_data (ch, c, fwd);
-
-  if (GNUNET_YES == ch->destroy && 0 == rel->n_recv)
-  {
-    send_destroy (ch, GNUNET_YES);
-    GMCH_destroy (ch);
-  }
-  /* if loopback is marked for destruction, no need to ACK to the other peer,
-   * it requested the destruction and is already gone, therefore, else if.
-   */
-  else if (is_loopback (ch))
-  {
-    unsigned int buffer;
-
-    buffer = GMCH_get_buffer (ch, fwd);
-    if (0 < buffer)
-      GMCH_allow_client (ch, fwd);
-
-    return;
-  }
-  GMT_send_connection_acks (ch->t);
-}
-
-
-/**
- * Handle data given by a client.
- *
- * Check whether the client is allowed to send in this tunnel, save if channel
- * is reliable and send an ACK to the client if there is still buffer space
- * in the tunnel.
- *
- * @param ch Channel.
- * @param c Client which sent the data.
- * @param message Message.
- * @param fwd Is this a FWD data?
- *
- * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en 
error.
- */
-int
-GMCH_handle_local_data (struct CadetChannel *ch,
-                        struct CadetClient *c,
-                        struct GNUNET_MessageHeader *message,
-                        int fwd)
-{
-  struct CadetChannelReliability *rel;
-  struct GNUNET_CADET_Data *payload;
-  size_t size = ntohs (message->size);
-  uint16_t p2p_size = sizeof(struct GNUNET_CADET_Data) + size;
-  unsigned char cbuf[p2p_size];
-
-  /* Is the client in the channel? */
-  if ( !( (fwd &&
-           ch->root == c)
-         ||
-          (!fwd &&
-           ch->dest == c) ) )
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-
-  rel = fwd ? ch->root_rel : ch->dest_rel;
-
-  if (GNUNET_NO == rel->client_allowed)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-
-  rel->client_allowed = GNUNET_NO;
-
-  /* Ok, everything is correct, send the message. */
-  payload = (struct GNUNET_CADET_Data *) cbuf;
-  payload->mid = htonl (rel->mid_send);
-  rel->mid_send++;
-  memcpy (&payload[1], message, size);
-  payload->header.size = htons (p2p_size);
-  payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA);
-  payload->chid = htonl (ch->gid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
-  GMCH_send_prebuilt_message (&payload->header, ch, fwd, NULL);
-
-  if (is_loopback (ch))
-  {
-    if (GMCH_get_buffer (ch, fwd) > 0)
-      GMCH_allow_client (ch, fwd);
-
-    return GNUNET_OK;
-  }
-
-  if (GMT_get_connections_buffer (ch->t) > 0)
-  {
-    GMCH_allow_client (ch, fwd);
-  }
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle a channel destroy requested by a client.
- *
- * Destroy the channel and the tunnel in case this was the last channel.
- *
- * @param ch Channel.
- * @param c Client that requested the destruction (to avoid notifying him).
- * @param is_root Is the request coming from root?
- */
-void
-GMCH_handle_local_destroy (struct CadetChannel *ch,
-                           struct CadetClient *c,
-                           int is_root)
-{
-  ch->destroy = GNUNET_YES;
-  /* Cleanup after the tunnel */
-  if (GNUNET_NO == is_root && c == ch->dest)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c));
-    GML_client_delete_channel (c, ch, ch->lid_dest);
-    ch->dest = NULL;
-  }
-  if (GNUNET_YES == is_root && c == ch->root)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c));
-    GML_client_delete_channel (c, ch, ch->lid_root);
-    ch->root = NULL;
-  }
-
-  send_destroy (ch, GNUNET_NO);
-  if (0 == ch->pending_messages)
-    GMCH_destroy (ch);
-}
-
-
-/**
- * Handle a channel create requested by a client.
- *
- * Create the channel and the tunnel in case this was the first0 channel.
- *
- * @param c Client that requested the creation (will be the root).
- * @param msg Create Channel message.
- *
- * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise.
- */
-int
-GMCH_handle_local_create (struct CadetClient *c,
-                          struct GNUNET_CADET_ChannelMessage *msg)
-{
-  struct CadetChannel *ch;
-  struct CadetTunnel3 *t;
-  struct CadetPeer *peer;
-  CADET_ChannelNumber chid;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s:%u\n",
-              GNUNET_i2s (&msg->peer), ntohl (msg->port));
-  chid = ntohl (msg->channel_id);
-
-  /* Sanity check for duplicate channel IDs */
-  if (NULL != GML_channel_get (c, chid))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  peer = GMP_get (&msg->peer);
-  GMP_add_tunnel (peer);
-  t = GMP_get_tunnel (peer);
-
-  if (GMP_get_short_id (peer) == myid)
-  {
-    GMT_change_cstate (t, CADET_TUNNEL3_READY);
-  }
-  else
-  {
-    /* FIXME change to a tunnel API, eliminate ch <-> peer connection */
-    GMP_connect (peer);
-  }
-
-  /* Create channel */
-  ch = channel_new (t, c, chid);
-  if (NULL == ch)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  ch->port = ntohl (msg->port);
-  channel_set_options (ch, ntohl (msg->opt));
-
-  /* In unreliable channels, we'll use the DLL to buffer BCK data */
-  ch->root_rel = GNUNET_new (struct CadetChannelReliability);
-  ch->root_rel->ch = ch;
-  ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME;
-  ch->root_rel->expected_delay.rel_value_us = 0;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GMCH_2s (ch));
-
-  send_create (ch);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Handler for cadet network payload traffic.
- *
- * @param ch Channel for the message.
- * @param msg Unencryted data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_data (struct CadetChannel *ch,
-                  const struct GNUNET_CADET_Data *msg,
-                  int fwd)
-{
-  struct CadetChannelReliability *rel;
-  struct CadetClient *c;
-  uint32_t mid;
-
-  /* If this is a remote (non-loopback) channel, find 'fwd'. */
-  if (GNUNET_SYSERR == fwd)
-  {
-    if (is_loopback (ch))
-    {
-      /* It is a loopback channel after all... */
-      GNUNET_break (0);
-      return;
-    }
-    fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
-  }
-
-  /*  Initialize FWD/BCK data */
-  c   = fwd ? ch->dest     : ch->root;
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-
-  if (NULL == c)
-  {
-    GNUNET_break (GNUNET_NO != ch->destroy);
-    return;
-  }
-
-  if (CADET_CHANNEL_READY != ch->state)
-  {
-    if (GNUNET_NO == fwd)
-    {
-      /* If we are the root, this means the other peer has sent traffic before
-       * receiving our ACK. Even if the SYNACK goes missing, no traffic should
-       * be sent before the ACK.
-       */
-      GNUNET_break_op (0);
-      return;
-    }
-    /* If we are the dest, this means that the SYNACK got to the root but
-     * the ACK went missing. Treat this as an ACK.
-     */
-    channel_confirm (ch, GNUNET_NO);
-  }
-
-  GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO);
-
-  mid = ntohl (msg->mid);
-  LOG (GNUNET_ERROR_TYPE_INFO, "<=== DATA %u %s on channel %s\n",
-       mid, GM_f2s (fwd), GMCH_2s (ch));
-
-  if (GNUNET_NO == ch->reliable ||
-      ( !GM_is_pid_bigger (rel->mid_recv, mid) &&
-        GM_is_pid_bigger (rel->mid_recv + 64, mid) ) )
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "RECV %u (%u)\n",
-         mid, ntohs (msg->header.size));
-    if (GNUNET_YES == ch->reliable)
-    {
-      /* Is this the exact next expected messasge? */
-      if (mid == rel->mid_recv)
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n");
-        rel->mid_recv++;
-        send_client_data (ch, msg, fwd);
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
-        add_buffered_data (msg, rel);
-      }
-    }
-    else
-    {
-      /* Tunnel is unreliable: send to clients directly */
-      /* FIXME: accept Out Of Order traffic */
-      rel->mid_recv = mid + 1;
-      send_client_data (ch, msg, fwd);
-    }
-  }
-  else
-  {
-    GNUNET_break_op (GM_is_pid_bigger (rel->mid_recv, mid));
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "MID %u not expected (%u - %u), dropping!\n",
-         mid, rel->mid_recv, rel->mid_recv + 63);
-  }
-
-  GMCH_send_data_ack (ch, fwd);
-}
-
-
-/**
- * Handler for cadet network traffic end-to-end ACKs.
- *
- * @param ch Channel on which we got this message.
- * @param msg Data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_data_ack (struct CadetChannel *ch,
-                      const struct GNUNET_CADET_DataACK *msg,
-                      int fwd)
-{
-  struct CadetChannelReliability *rel;
-  struct CadetReliableMessage *copy;
-  struct CadetReliableMessage *next;
-  uint32_t ack;
-  int work;
-
-  /* If this is a remote (non-loopback) channel, find 'fwd'. */
-  if (GNUNET_SYSERR == fwd)
-  {
-    if (is_loopback (ch))
-    {
-      /* It is a loopback channel after all... */
-      GNUNET_break (0);
-      return;
-    }
-    /* Inverted: if message came 'FWD' is a 'BCK ACK'. */
-    fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES;
-  }
-
-  ack = ntohl (msg->mid);
-  LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s ACK %u\n", GM_f2s (fwd), ack);
-
-  if (GNUNET_YES == fwd)
-  {
-    rel = ch->root_rel;
-  }
-  else
-  {
-    rel = ch->dest_rel;
-  }
-  if (NULL == rel)
-  {
-    GNUNET_break_op (GNUNET_NO != ch->destroy);
-    return;
-  }
-
-  /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */
-  for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
-  {
-    if (GM_is_pid_bigger (copy->mid, ack))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  head %u, out!\n", copy->mid);
-      channel_rel_free_sent (rel, msg);
-      break;
-    }
-    work = GNUNET_YES;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %u\n", copy->mid);
-    next = copy->next;
-    if (GNUNET_YES == rel_message_free (copy, GNUNET_YES))
-      return;
-  }
-
-  /* ACK client if needed and possible */
-  GMCH_allow_client (ch, fwd);
-
-  /* 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);
-      rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-      if (NULL != rel->head_sent && NULL == rel->head_sent->chq)
-      {
-        struct GNUNET_TIME_Absolute new_target;
-        struct GNUNET_TIME_Relative delay;
-
-        delay = GNUNET_TIME_relative_multiply (rel->retry_timer,
-                                               CADET_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
-    {
-      /* Work was done but no task was pending? Shouldn't happen! */
-      GNUNET_break (0);
-    }
-  }
-}
-
-
-/**
- * Handler for channel create messages.
- *
- * Does not have fwd parameter because it's always 'FWD': channel is incoming.
- *
- * @param t Tunnel this channel will be in.
- * @param msg Channel crate message.
- */
-struct CadetChannel *
-GMCH_handle_create (struct CadetTunnel3 *t,
-                    const struct GNUNET_CADET_ChannelCreate *msg)
-{
-  CADET_ChannelNumber chid;
-  struct CadetChannel *ch;
-  struct CadetClient *c;
-  int new_channel;
-  int reaction;
-
-  reaction = GNUNET_NO;
-  chid = ntohl (msg->chid);
-  ch = GMT_get_channel (t, chid);
-  if (NULL == ch)
-  {
-    /* Create channel */
-    ch = channel_new (t, NULL, 0);
-    ch->gid = chid;
-    channel_set_options (ch, ntohl (msg->opt));
-    new_channel = GNUNET_YES;
-  }
-  else
-  {
-    new_channel = GNUNET_NO;
-  }
-
-  if (GNUNET_YES == new_channel || GMT_is_loopback (t))
-  {
-    /* Find a destination client */
-    ch->port = ntohl (msg->port);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "   port %u\n", ch->port);
-    c = GML_client_get_by_port (ch->port);
-    if (NULL == c)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  no client has port registered\n");
-      if (is_loopback (ch))
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  loopback: destroy on handler\n");
-        send_nack (ch);
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  not loopback: destroy now\n");
-        send_nack (ch);
-        GMCH_destroy (ch);
-      }
-      return NULL;
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  client %p has port registered\n", c);
-    }
-
-    add_destination (ch, c);
-    if (GNUNET_YES == ch->reliable)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n");
-    else
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Not Reliable\n");
-
-    send_client_create (ch);
-    ch->state =  CADET_CHANNEL_SENT;
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  duplicate create channel\n");
-    reaction = GNUNET_YES;
-    if (GNUNET_SCHEDULER_NO_TASK != ch->dest_rel->retry_task)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  clearing retry task\n");
-      /* we were waiting to re-send our 'SYNACK', wait no more! */
-      GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task);
-      ch->dest_rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-  }
-  send_ack (ch, GNUNET_YES, reaction);
-
-  return ch;
-}
-
-
-/**
- * Handler for channel NACK messages.
- *
- * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
- *
- * @param ch Channel.
- */
-void
-GMCH_handle_nack (struct CadetChannel *ch)
-{
-  send_client_nack (ch);
-  GMCH_destroy (ch);
-}
-
-
-/**
- * Handler for channel ack messages.
- *
- * @param ch Channel.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_ack (struct CadetChannel *ch,
-                 const struct GNUNET_CADET_ChannelManage *msg,
-                 int fwd)
-{
-  /* If this is a remote (non-loopback) channel, find 'fwd'. */
-  if (GNUNET_SYSERR == fwd)
-  {
-    if (is_loopback (ch))
-    {
-      /* It is a loopback channel after all... */
-      GNUNET_break (0);
-      return;
-    }
-    fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
-  }
-
-  channel_confirm (ch, !fwd);
-}
-
-
-/**
- * Handler for channel destroy messages.
- *
- * @param ch Channel to be destroyed of.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_destroy (struct CadetChannel *ch,
-                     const struct GNUNET_CADET_ChannelManage *msg,
-                     int fwd)
-{
-  struct CadetChannelReliability *rel;
-
-  /* If this is a remote (non-loopback) channel, find 'fwd'. */
-  if (GNUNET_SYSERR == fwd)
-  {
-    if (is_loopback (ch))
-    {
-      /* It is a loopback channel after all... */
-      GNUNET_break (0);
-      return;
-    }
-    fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
-  }
-
-  GMCH_debug (ch);
-  if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
-  {
-    /* Not for us (don't destroy twice a half-open loopback channel) */
-    return;
-  }
-
-  rel = fwd ? ch->dest_rel : ch->root_rel;
-  if (0 == rel->n_recv)
-  {
-    send_destroy (ch, GNUNET_YES);
-    GMCH_destroy (ch);
-  }
-  else
-  {
-    ch->destroy = GNUNET_YES;
-  }
-}
-
-
-/**
- * Sends an already built message on a channel.
- *
- * If the channel is on a loopback tunnel, notifies the appropriate destination
- * client locally.
- *
- * On a normal channel passes the message to the tunnel for encryption and
- * sending on a connection.
- *
- * This function DOES NOT save the message for retransmission.
- *
- * @param message Message to send. Function makes a copy of it.
- * @param ch Channel on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param existing_copy This is a retransmission, don't save a copy.
- */
-void
-GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                            struct CadetChannel *ch, int fwd,
-                            void *existing_copy)
-{
-  struct CadetChannelQueue *chq;
-  uint16_t type;
-
-  type = ntohs (message->type);
-  LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %s on channel %s\n",
-       GM_m2s (type), GM_f2s (fwd), GMCH_2s (ch));
-
-  if (GMT_is_loopback (ch->t))
-  {
-    handle_loopback (ch, message, fwd);
-    return;
-  }
-
-  switch (type)
-  {
-    struct GNUNET_CADET_Data *payload;
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-
-      payload = (struct GNUNET_CADET_Data *) message;
-      LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %u\n",
-           GM_m2s (type), ntohl (payload->mid));
-      if (GNUNET_YES == ch->reliable)
-      {
-        chq = GNUNET_new (struct CadetChannelQueue);
-        chq->type = type;
-        if (NULL == existing_copy)
-          chq->copy = channel_save_copy (ch, message, fwd);
-        else
-        {
-          chq->copy = (struct CadetReliableMessage *) existing_copy;
-          if (NULL != chq->copy->chq)
-          {
-            /* Last retransmission was queued but not yet sent!
-             * This retransmission was scheduled by a ch_message_sent which
-             * followed a very fast RTT, so the tiny delay made the
-             * retransmission function to execute before the previous
-             * retransmitted message even had a chance to leave the peer.
-             * Cancel this message and wait until the pending
-             * retransmission leaves the peer and ch_message_sent starts
-             * the timer for the next one.
-             */
-            GNUNET_free (chq);
-            LOG (GNUNET_ERROR_TYPE_DEBUG,
-                 "  exisitng copy not yet transmitted!\n");
-            return;
-          }
-          LOG (GNUNET_ERROR_TYPE_DEBUG,
-               "  using existing copy: %p {r:%p q:%p t:%u}\n",
-               existing_copy,
-               chq->copy->rel, chq->copy->chq, chq->copy->type);
-        }
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  new chq: %p\n", chq);
-            chq->copy->chq = chq;
-            chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL,
-                                                 NULL != existing_copy,
-                                                 &ch_message_sent, chq);
-        /* q itself is stored in copy */
-        GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy);
-      }
-      else
-      {
-        fire_and_forget (message, ch, GNUNET_NO);
-      }
-      break;
-
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-      if (GNUNET_YES == fwd || NULL != existing_copy)
-      {
-        /* BCK ACK (going FWD) is just a response for a SYNACK, don't keep*/
-        fire_and_forget (message, ch, GNUNET_YES);
-        return;
-      }
-      /* fall-trough */
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-      chq = GNUNET_new (struct CadetChannelQueue);
-      chq->type = type;
-      chq->rel = fwd ? ch->root_rel : ch->dest_rel;
-      if (NULL != chq->rel->uniq)
-      {
-        if (NULL != chq->rel->uniq->tq)
-        {
-          GMT_cancel (chq->rel->uniq->tq);
-          /* ch_message_sent is called, freeing and NULLing uniq */
-        }
-        else
-        {
-          GNUNET_break (0);
-          GNUNET_free (chq->rel->uniq);
-        }
-      }
-      chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES,
-                                           &ch_message_sent, chq);
-      if (NULL == chq->tq)
-      {
-        GNUNET_break (0);
-        GNUNET_free (chq);
-        chq = NULL;
-        return;
-      }
-      chq->rel->uniq = chq;
-      break;
-
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      fire_and_forget (message, ch, GNUNET_YES);
-      break;
-
-
-    default:
-      GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s unknown!\n", GM_m2s (type));
-      fire_and_forget (message, ch, GNUNET_YES);
-  }
-}
-
-
-/**
- * Get the static string for identification of the channel.
- *
- * @param ch Channel.
- *
- * @return Static string with the channel IDs.
- */
-const char *
-GMCH_2s (const struct CadetChannel *ch)
-{
-  static char buf[64];
-
-  if (NULL == ch)
-    return "(NULL Channel)";
-
-  sprintf (buf, "%s:%u gid:%X (%X / %X)",
-           GMT_2s (ch->t), ch->port, ch->gid, ch->lid_root, ch->lid_dest);
-
-  return buf;
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_channel.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_channel.h      2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_channel.h      2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,349 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_channel.h
- * @brief cadet service; dealing with end-to-end channels
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMCH (Gnunet Cadet CHannel)
- */
-
-#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
-#define GNUNET_SERVICE_CADET_CHANNEL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "cadet_protocol.h"
-#include "cadet.h"
-
-/**
- * Struct containing all information regarding a channel to a remote client.
- */
-struct CadetChannel;
-
-
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_local.h"
-
-
-/**
- * Destroy a channel and free all resources.
- *
- * @param ch Channel to destroy.
- */
-void
-GMCH_destroy (struct CadetChannel *ch);
-
-
-/**
- * Get the channel's public ID.
- *
- * @param ch Channel.
- *
- * @return ID used to identify the channel with the remote peer.
- */
-CADET_ChannelNumber
-GMCH_get_id (const struct CadetChannel *ch);
-
-/**
- * Get the channel tunnel.
- *
- * @param ch Channel to get the tunnel from.
- *
- * @return tunnel of the channel.
- */
-struct CadetTunnel3 *
-GMCH_get_tunnel (const struct CadetChannel *ch);
-
-/**
- * Get free buffer space towards the client on a specific channel.
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - 64]
- */
-unsigned int
-GMCH_get_buffer (struct CadetChannel *ch, int fwd);
-
-
-/**
- * Get flow control status of end point: is client allow to send?
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic? (Request root status).
- *
- * @return #GNUNET_YES if client is allowed to send us data.
- */
-int
-GMCH_get_allowed (struct CadetChannel *ch, int fwd);
-
-
-/**
- * Is the root client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GMCH_is_origin (struct CadetChannel *ch, int fwd);
-
-/**
- * Is the destination client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GMCH_is_terminal (struct CadetChannel *ch, int fwd);
-
-/**
- * Send an end-to-end ACK message for the most recent in-sequence payload.
- *
- * If channel is not reliable, do nothing.
- *
- * @param ch Channel this is about.
- * @param fwd Is for FWD traffic? (ACK dest->owner)
- */
-void
-GMCH_send_data_ack (struct CadetChannel *ch, int fwd);
-
-/**
- * Notify the destination client that a new incoming channel was created.
- *
- * @param ch Channel that was created.
- */
-void
-GMCH_send_create (struct CadetChannel *ch);
-
-/**
- * Allow a client to send us more data, in case it was choked.
- *
- * @param ch Channel.
- * @param fwd Is this about FWD traffic? (Root client).
- */
-void
-GMCH_allow_client (struct CadetChannel *ch, int fwd);
-
-/**
- * Log channel info.
- *
- * @param ch Channel.
- */
-void
-GMCH_debug (struct CadetChannel *ch);
-
-/**
- * Handle an ACK given by a client.
- *
- * Mark client as ready and send him any buffered data we could have for him.
- *
- * @param ch Channel.
- * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK)
- */
-void
-GMCH_handle_local_ack (struct CadetChannel *ch, int fwd);
-
-/**
- * Handle data given by a client.
- *
- * Check whether the client is allowed to send in this tunnel, save if channel
- * is reliable and send an ACK to the client if there is still buffer space
- * in the tunnel.
- *
- * @param ch Channel.
- * @param c Client which sent the data.
- * @param message Message.
- * @param fwd Is this a FWD data?
- *
- * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en 
error.
- */
-int
-GMCH_handle_local_data (struct CadetChannel *ch,
-                        struct CadetClient *c,
-                        struct GNUNET_MessageHeader *message,
-                        int fwd);
-
-/**
- * Handle a channel destroy requested by a client.
- *
- * Destroy the channel and the tunnel in case this was the last channel.
- *
- * @param ch Channel.
- * @param c Client that requested the destruction (to avoid notifying him).
- * @param is_root Is the request coming from root?
- */
-void
-GMCH_handle_local_destroy (struct CadetChannel *ch,
-                           struct CadetClient *c,
-                           int is_root);
-
-/**
- * Handle a channel create requested by a client.
- *
- * Create the channel and the tunnel in case this was the first0 channel.
- *
- * @param c Client that requested the creation (will be the root).
- * @param msg Create Channel message.
- *
- * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise.
- */
-int
-GMCH_handle_local_create (struct CadetClient *c,
-                          struct GNUNET_CADET_ChannelMessage *msg);
-
-/**
- * Handler for cadet network payload traffic.
- *
- * @param ch Channel for the message.
- * @param msg Unencryted data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_data (struct CadetChannel *ch,
-                  const struct GNUNET_CADET_Data *msg,
-                  int fwd);
-
-/**
- * Handler for cadet network traffic end-to-end ACKs.
- *
- * @param ch Channel on which we got this message.
- * @param msg Data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_data_ack (struct CadetChannel *ch,
-                      const struct GNUNET_CADET_DataACK *msg,
-                      int fwd);
-
-/**
- * Handler for channel create messages.
- *
- * Does not have fwd parameter because it's always 'FWD': channel is incoming.
- *
- * @param t Tunnel this channel will be in.
- * @param msg Channel crate message.
- */
-struct CadetChannel *
-GMCH_handle_create (struct CadetTunnel3 *t,
-                    const struct GNUNET_CADET_ChannelCreate *msg);
-
-/**
- * Handler for channel NACK messages.
- *
- * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
- *
- * @param ch Channel.
- */
-void
-GMCH_handle_nack (struct CadetChannel *ch);
-
-/**
- * Handler for channel ack messages.
- *
- * @param ch Channel this channel is to be created in.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_ack (struct CadetChannel *ch,
-                 const struct GNUNET_CADET_ChannelManage *msg,
-                 int fwd);
-
-/**
- * Handler for channel destroy messages.
- *
- * @param ch Channel this channel is to be destroyed of.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GMCH_handle_destroy (struct CadetChannel *ch,
-                     const struct GNUNET_CADET_ChannelManage *msg,
-                     int fwd);
-
-/**
- * Sends an already built message on a channel.
- *
- * If the channel is on a loopback tunnel, notifies the appropriate destination
- * client locally.
- *
- * On a normal channel passes the message to the tunnel for encryption and
- * sending on a connection.
- *
- * This function DOES NOT save the message for retransmission.
- *
- * @param message Message to send. Function makes a copy of it.
- * @param ch Channel on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param existing_copy This is a retransmission, don't save a copy.
- */
-void
-GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                            struct CadetChannel *ch, int fwd,
-                            void *existing_copy);
-
-/**
- * Get the static string for identification of the channel.
- *
- * @param ch Channel.i
- *
- * @return Static string with the channel IDs.
- */
-const char *
-GMCH_2s (const struct CadetChannel *ch);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_SERVICE_CADET_CHANNEL_H */
-#endif
-/* end of gnunet-service-cadet_channel.h */

Deleted: gnunet/src/mesh/gnunet-service-cadet_connection.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_connection.c   2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_connection.c   2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,3176 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001-2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_connection.c
- * @brief GNUnet CADET service connection handling
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-
-#include "cadet_path.h"
-#include "cadet_protocol.h"
-#include "cadet.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_tunnel.h"
-
-
-#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__)
-
-#define CADET_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
-                                  GNUNET_TIME_UNIT_MINUTES,\
-                                  10)
-#define AVG_MSGS                32
-
-
-/******************************************************************************/
-/********************************   STRUCTS  
**********************************/
-/******************************************************************************/
-
-/**
- * Struct to encapsulate all the Flow Control information to a peer to which
- * we are directly connected (on a core level).
- */
-struct CadetFlowControl
-{
-  /**
-   * Connection this controls.
-   */
-  struct CadetConnection *c;
-
-  /**
-   * How many messages are in the queue on this connection.
-   */
-  unsigned int queue_n;
-
-  /**
-   * How many messages do we accept in the queue.
-   */
-  unsigned int queue_max;
-
-  /**
-   * ID of the last packet sent towards the peer.
-   */
-  uint32_t last_pid_sent;
-
-  /**
-   * ID of the last packet received from the peer.
-   */
-  uint32_t last_pid_recv;
-
-  /**
-   * Last ACK sent to the peer (peer can't send more than this PID).
-   */
-  uint32_t last_ack_sent;
-
-  /**
-   * Last ACK sent towards the origin (for traffic towards leaf node).
-   */
-  uint32_t last_ack_recv;
-
-  /**
-   * Task to poll the peer in case of a lost ACK causes stall.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier poll_task;
-
-  /**
-   * How frequently to poll for ACKs.
-   */
-  struct GNUNET_TIME_Relative poll_time;
-
-  /**
-   * Queued poll message, to cancel if not necessary anymore (got ACK).
-   */
-  struct CadetConnectionQueue *poll_msg;
-
-  /**
-   * Queued poll message, to cancel if not necessary anymore (got ACK).
-   */
-  struct CadetConnectionQueue *ack_msg;
-};
-
-/**
- * Keep a record of the last messages sent on this connection.
- */
-struct CadetConnectionPerformance
-{
-  /**
-   * Circular buffer for storing measurements.
-   */
-  double usecsperbyte[AVG_MSGS];
-
-  /**
-   * Running average of @c usecsperbyte.
-   */
-  double avg;
-
-  /**
-   * How many values of @c usecsperbyte are valid.
-   */
-  uint16_t size;
-
-  /**
-   * Index of the next "free" position in @c usecsperbyte.
-   */
-  uint16_t idx;
-};
-
-
-/**
- * Struct containing all information regarding a connection to a peer.
- */
-struct CadetConnection
-{
-  /**
-   * Tunnel this connection is part of.
-   */
-  struct CadetTunnel3 *t;
-
-  /**
-   * Flow control information for traffic fwd.
-   */
-  struct CadetFlowControl fwd_fc;
-
-  /**
-   * Flow control information for traffic bck.
-   */
-  struct CadetFlowControl bck_fc;
-
-  /**
-   * Measure connection performance on the endpoint.
-   */
-  struct CadetConnectionPerformance *perf;
-
-  /**
-   * ID of the connection.
-   */
-  struct GNUNET_CADET_Hash id;
-
-  /**
-   * State of the connection.
-   */
-  enum CadetConnectionState state;
-
-  /**
-   * Path being used for the tunnel. At the origin of the connection
-   * it's a pointer to the destination's path pool, otherwise just a copy.
-   */
-  struct CadetPeerPath *path;
-
-  /**
-   * Position of the local peer in the path.
-   */
-  unsigned int own_pos;
-
-  /**
-   * Task to keep the used paths alive at the owner,
-   * time tunnel out on all the other peers.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
-
-  /**
-   * Task to keep the used paths alive at the destination,
-   * time tunnel out on all the other peers.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
-
-  /**
-   * Queue handle for maintainance traffic. One handle for FWD and BCK since
-   * one peer never needs to maintain both directions (no loopback 
connections).
-   */
-  struct CadetPeerQueue *maintenance_q;
-
-  /**
-   * Counter to do exponential backoff when creating a connection (max 64).
-   */
-  unsigned short create_retry;
-
-  /**
-   * Pending message count.
-   */
-  int pending_messages;
-
-  /**
-   * Destroy flag: if true, destroy on last message.
-   */
-  int destroy;
-};
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetConnectionQueue
-{
-  /**
-   * Peer queue handle, to cancel if necessary.
-   */
-  struct CadetPeerQueue *q;
-
-  /**
-   * Was this a forced message? (Do not account for it)
-   */
-  int forced;
-
-  /**
-   * Continuation to call once sent.
-   */
-  GMC_sent cont;
-
-  /**
-   * Closure for @c cont.
-   */
-  void *cont_cls;
-};
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Connections known, indexed by cid (CadetConnection).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *connections;
-
-/**
- * How many connections are we willing to maintain.
- * Local connections are always allowed, even if there are more connections 
than max.
- */
-static unsigned long long max_connections;
-
-/**
- * How many messages *in total* are we willing to queue, divide by number of
- * connections to get connection queue size.
- */
-static unsigned long long max_msgs_queue;
-
-/**
- * How often to send path keepalives. Paths timeout after 4 missed.
- */
-static struct GNUNET_TIME_Relative refresh_connection_time;
-
-/**
- * How often to send path create / ACKs.
- */
-static struct GNUNET_TIME_Relative create_connection_time;
-
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-#if 0 // avoid compiler warning for unused static function
-static void
-fc_debug (struct CadetFlowControl *fc)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
-              fc->last_pid_recv, fc->last_ack_sent);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
-              fc->last_pid_sent, fc->last_ack_recv);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
-              fc->queue_n, fc->queue_max);
-}
-
-static void
-connection_debug (struct CadetConnection *c)
-{
-  if (NULL == c)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
-              peer2s (c->t->peer), GMC_2s (c));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n",
-              c->state, c->pending_messages);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
-  fc_debug (&c->fwd_fc);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
-  fc_debug (&c->bck_fc);
-}
-#endif
-
-
-/**
- * Schedule next keepalive task, taking in consideration
- * the connection state and number of retries.
- *
- * @param c Connection for which to schedule the next keepalive.
- * @param fwd Direction for the next keepalive.
- */
-static void
-schedule_next_keepalive (struct CadetConnection *c, int fwd);
-
-
-/**
- * Resets the connection timeout task, some other message has done the
- * task's job.
- * - For the first peer on the direction this means to send
- *   a keepalive or a path confirmation message (either create or ACK).
- * - For all other peers, this means to destroy the connection,
- *   due to lack of activity.
- * Starts the timeout if no timeout was running (connection just created).
- *
- * @param c Connection whose timeout to reset.
- * @param fwd Is this forward?
- */
-static void
-connection_reset_timeout (struct CadetConnection *c, int fwd);
-
-
-/**
- * Get string description for tunnel state. Reentrant.
- *
- * @param s Tunnel state.
- *
- * @return String representation.
- */
-static const char *
-GMC_state2s (enum CadetConnectionState s)
-{
-  switch (s)
-  {
-    case CADET_CONNECTION_NEW:
-      return "CADET_CONNECTION_NEW";
-    case CADET_CONNECTION_SENT:
-      return "CADET_CONNECTION_SENT";
-    case CADET_CONNECTION_ACK:
-      return "CADET_CONNECTION_ACK";
-    case CADET_CONNECTION_READY:
-      return "CADET_CONNECTION_READY";
-    case CADET_CONNECTION_DESTROYED:
-      return "CADET_CONNECTION_DESTROYED";
-    default:
-      return "CADET_CONNECTION_STATE_ERROR";
-  }
-}
-
-
-/**
- * Initialize a Flow Control structure to the initial state.
- *
- * @param fc Flow Control structure to initialize.
- */
-static void
-fc_init (struct CadetFlowControl *fc)
-{
-  fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
-  fc->last_pid_recv = (uint32_t) -1;
-  fc->last_ack_sent = (uint32_t) 0;
-  fc->last_ack_recv = (uint32_t) 0;
-  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-  fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
-  fc->queue_n = 0;
-  fc->queue_max = (max_msgs_queue / max_connections) + 1;
-}
-
-
-/**
- * Find a connection.
- *
- * @param cid Connection ID.
- */
-static struct CadetConnection *
-connection_get (const struct GNUNET_CADET_Hash *cid)
-{
-  return GNUNET_CONTAINER_multihashmap_get (connections, GM_h2hc (cid));
-}
-
-
-static void
-connection_change_state (struct CadetConnection* c,
-                         enum CadetConnectionState state)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Connection %s state %s -> %s\n",
-       GMC_2s (c), GMC_state2s (c->state), GMC_state2s (state));
-  if (CADET_CONNECTION_DESTROYED == c->state)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n");
-    return;
-  }
-  c->state = state;
-  if (CADET_CONNECTION_READY == state)
-    c->create_retry = 1;
-}
-
-
-/**
- * Callback called when a queued ACK message is sent.
- *
- * @param cls Closure (FC).
- * @param c Connection this message was on.
- * @param q Queue handler this call invalidates.
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-static void
-ack_sent (void *cls,
-          struct CadetConnection *c,
-          struct CadetConnectionQueue *q,
-          uint16_t type, int fwd, size_t size)
-{
-  struct CadetFlowControl *fc = cls;
-
-  fc->ack_msg = NULL;
-}
-
-
-/**
- * Send an ACK on the connection, informing the predecessor about
- * the available buffer space. Should not be called in case the peer
- * is origin (no predecessor) in the @c fwd direction.
- *
- * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
- * the ACK itself goes "back" (dest->root).
- *
- * @param c Connection on which to send the ACK.
- * @param buffer How much space free to advertise?
- * @param fwd Is this FWD ACK? (Going dest -> root)
- * @param force Don't optimize out.
- */
-static void
-send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
-{
-  struct CadetFlowControl *next_fc;
-  struct CadetFlowControl *prev_fc;
-  struct GNUNET_CADET_ACK msg;
-  uint32_t ack;
-  int delta;
-
-  /* If origin, there is no connection to send ACKs. Wrong function! */
-  if (GMC_is_origin (c, fwd))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "connection %s is origin in %s\n",
-         GMC_2s (c), GM_f2s (fwd));
-    GNUNET_break (0);
-    return;
-  }
-
-  next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "connection send %s ack on %s\n",
-       GM_f2s (fwd), GMC_2s (c));
-
-  /* Check if we need to transmit the ACK. */
-  delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
-  if (3 < delta && buffer < delta && GNUNET_NO == force)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "  last pid recv: %u, last ack sent: %u\n",
-         prev_fc->last_pid_recv, prev_fc->last_ack_sent);
-    return;
-  }
-
-  /* Ok, ACK might be necessary, what PID to ACK? */
-  ack = prev_fc->last_pid_recv + buffer;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " last pid %u, last ack %u, qmax %u, q %u\n",
-       prev_fc->last_pid_recv, prev_fc->last_ack_sent,
-       next_fc->queue_max, next_fc->queue_n);
-  if (ack == prev_fc->last_ack_sent && GNUNET_NO == force)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
-    return;
-  }
-
-  /* Check if message is already in queue */
-  if (NULL != prev_fc->ack_msg)
-  {
-    if (GM_is_pid_bigger (ack, prev_fc->last_ack_sent))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
-      GMC_cancel (prev_fc->ack_msg);
-      /* GMC_cancel triggers ack_sent(), which clears fc->ack_msg */
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n");
-      return;
-    }
-  }
-
-  prev_fc->last_ack_sent = ack;
-
-  /* Build ACK message and send on connection */
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ACK);
-  msg.ack = htonl (ack);
-  msg.cid = c->id;
-
-  prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header,
-                                                GNUNET_MESSAGE_TYPE_CADET_ACK,
-                                                ack, c, !fwd, GNUNET_YES,
-                                                &ack_sent, prev_fc);
-}
-
-
-/**
- * Callback called when a connection queued message is sent.
- *
- * Calculates the average time and connection packet tracking.
- *
- * @param cls Closure (ConnectionQueue Handle).
- * @param c Connection this message was on.
- * @param sent Was it really sent? (Could have been canceled)
- * @param type Type of message sent.
- * @param pid Packet ID, or 0 if not applicable (create, destroy, etc).
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- * @param wait Time spent waiting for core (only the time for THIS message)
- */
-static void
-conn_message_sent (void *cls,
-                   struct CadetConnection *c, int sent,
-                   uint16_t type, uint32_t pid, int fwd, size_t size,
-                   struct GNUNET_TIME_Relative wait)
-{
-  struct CadetConnectionPerformance *p;
-  struct CadetFlowControl *fc;
-  struct CadetConnectionQueue *q = cls;
-  double usecsperbyte;
-  int forced;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "connection message_sent\n");
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s\n",
-       sent ? "" : "not ", GM_f2s (fwd), GM_m2s (type));
-  if (NULL != q)
-  {
-    forced = q->forced;
-    if (NULL != q->cont)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n");
-      q->cont (q->cont_cls, c, q, type, fwd, size);
-    }
-    GNUNET_free (q);
-  }
-  else if (type == GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED)
-  {
-    /* If NULL == q and ENCRYPTED == type, message must have been ch_mngmnt */
-    forced = GNUNET_YES;
-  }
-  else
-  {
-    forced = GNUNET_NO;
-  }
-  if (NULL == c)
-  {
-    GNUNET_break (type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN ||
-                  type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
-    LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n",
-         GM_m2s (type));
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages);
-  c->pending_messages--;
-  if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "!  destroying connection!\n");
-    GMC_destroy (c);
-    return;
-  }
-  /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-      c->maintenance_q = NULL;
-      /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */
-      if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd)
-        schedule_next_keepalive (c, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-      if (GNUNET_YES == sent)
-      {
-        GNUNET_assert (NULL != q);
-        fc->last_pid_sent = pid; // FIXME
-        GMC_send_ack (c, fwd, GNUNET_NO);
-        connection_reset_timeout (c, fwd);
-      }
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "!  Q_N- %p %u\n", fc, fc->queue_n);
-      if (GNUNET_NO == forced)
-      {
-        fc->queue_n--;
-        LOG (GNUNET_ERROR_TYPE_DEBUG,
-            "!   accounting pid %u\n",
-            fc->last_pid_sent);
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG,
-             "!   forced, Q_N not accounting pid %u\n",
-             fc->last_pid_sent);
-      }
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
-      if (GNUNET_YES == sent)
-        connection_reset_timeout (c, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
-      fc->poll_msg = NULL;
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
-      fc->ack_msg = NULL;
-      break;
-
-    default:
-      break;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "!  message sent!\n");
-
-  if (NULL == c->perf)
-    return; /* Only endpoints are interested in timing. */
-
-  p = c->perf;
-  usecsperbyte = ((double) wait.rel_value_us) / size;
-  if (p->size == AVG_MSGS)
-  {
-    /* Array is full. Substract oldest value, add new one and store. */
-    p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
-    p->usecsperbyte[p->idx] = usecsperbyte;
-    p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
-  }
-  else
-  {
-    /* Array not yet full. Add current value to avg and store. */
-    p->usecsperbyte[p->idx] = usecsperbyte;
-    p->avg *= p->size;
-    p->avg += p->usecsperbyte[p->idx];
-    p->size++;
-    p->avg /= p->size;
-  }
-  p->idx = (p->idx + 1) % AVG_MSGS;
-}
-
-
-/**
- * Get the previous hop in a connection
- *
- * @param c Connection.
- *
- * @return Previous peer in the connection.
- */
-static struct CadetPeer *
-get_prev_hop (const struct CadetConnection *c)
-{
-  GNUNET_PEER_Id id;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " get prev hop %s [%u/%u]\n",
-       GMC_2s (c), c->own_pos, c->path->length);
-  if (0 == c->own_pos || c->path->length < 2)
-    id = c->path->peers[0];
-  else
-    id = c->path->peers[c->own_pos - 1];
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ID: %s (%u)\n",
-       GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
-
-  return GMP_get_short (id);
-}
-
-
-/**
- * Get the next hop in a connection
- *
- * @param c Connection.
- *
- * @return Next peer in the connection.
- */
-static struct CadetPeer *
-get_next_hop (const struct CadetConnection *c)
-{
-  GNUNET_PEER_Id id;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n",
-       GMC_2s (c), c->own_pos, c->path->length);
-  if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
-    id = c->path->peers[c->path->length - 1];
-  else
-    id = c->path->peers[c->own_pos + 1];
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ID: %s (%u)\n",
-       GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
-
-  return GMP_get_short (id);
-}
-
-
-/**
- * Get the hop in a connection.
- *
- * @param c Connection.
- * @param fwd Next hop?
- *
- * @return Next peer in the connection.
- */
-static struct CadetPeer *
-get_hop (struct CadetConnection *c, int fwd)
-{
-  if (fwd)
-    return get_next_hop (c);
-  return get_prev_hop (c);
-}
-
-
-/**
- * Is traffic coming from this sender 'FWD' traffic?
- *
- * @param c Connection to check.
- * @param sender Peer identity of neighbor.
- *
- * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore
- *         the traffic is 'FWD'.
- *         #GNUNET_NO for BCK.
- *         #GNUNET_SYSERR for errors.
- */
-static int
-is_fwd (const struct CadetConnection *c,
-        const struct GNUNET_PeerIdentity *sender)
-{
-  GNUNET_PEER_Id id;
-
-  id = GNUNET_PEER_search (sender);
-  if (GMP_get_short_id (get_prev_hop (c)) == id)
-    return GNUNET_YES;
-
-  if (GMP_get_short_id (get_next_hop (c)) == id)
-    return GNUNET_NO;
-
-  GNUNET_break (0);
-  return GNUNET_SYSERR;
-}
-
-
-/**
- * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
- * or a first CONNECTION_ACK directed to us.
- *
- * @param connection Connection to confirm.
- * @param fwd Should we send it FWD? (root->dest)
- *            (First (~SYNACK) goes BCK, second (~ACK) goes FWD)
- */
-static void
-send_connection_ack (struct CadetConnection *connection, int fwd)
-{
-  struct CadetTunnel3 *t;
-
-  t = connection->t;
-  LOG (GNUNET_ERROR_TYPE_INFO, "===> {%14s ACK} on connection %s\n",
-       GM_f2s (!fwd), GMC_2s (connection));
-  GMP_queue_add (get_hop (connection, fwd), NULL,
-                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK,
-                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0,
-                 sizeof (struct GNUNET_CADET_ConnectionACK),
-                 connection, fwd, &conn_message_sent, NULL);
-  connection->pending_messages++;
-  if (CADET_TUNNEL3_NEW == GMT_get_cstate (t))
-    GMT_change_cstate (t, CADET_TUNNEL3_WAITING);
-  if (CADET_CONNECTION_READY != connection->state)
-    connection_change_state (connection, CADET_CONNECTION_SENT);
-}
-
-
-/**
- * Send a notification that a connection is broken.
- *
- * @param c Connection that is broken.
- * @param id1 Peer that has disconnected.
- * @param id2 Peer that has disconnected.
- * @param fwd Direction towards which to send it.
- */
-static void
-send_broken (struct CadetConnection *c,
-             const struct GNUNET_PeerIdentity *id1,
-             const struct GNUNET_PeerIdentity *id2,
-             int fwd)
-{
-  struct GNUNET_CADET_ConnectionBroken msg;
-
-  msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
-  msg.cid = c->id;
-  msg.peer1 = *id1;
-  msg.peer2 = *id2;
-  GMC_send_prebuilt_message (&msg.header,
-                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0,
-                             c, fwd, GNUNET_YES, NULL, NULL);
-}
-
-
-/**
- * Send a notification that a connection is broken, when a connection
- * isn't even known to the local peer.
- *
- * @param connection_id Connection ID.
- * @param id1 Peer that has disconnected, probably local peer.
- * @param id2 Peer that has disconnected can be NULL if unknown.
- * @param peer Peer to notify (neighbor who sent the connection).
- */
-static void
-send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id,
-                     const struct GNUNET_PeerIdentity *id1,
-                     const struct GNUNET_PeerIdentity *id2,
-                     const struct GNUNET_PeerIdentity *peer_id)
-{
-  struct GNUNET_CADET_ConnectionBroken *msg;
-  struct CadetPeer *neighbor;
-
-  LOG (GNUNET_ERROR_TYPE_INFO, "===> BROKEN on unknown connection %s\n",
-       GNUNET_h2s (GM_h2hc (connection_id)));
-
-  msg = GNUNET_new (struct GNUNET_CADET_ConnectionBroken);
-  msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
-  msg->cid = *connection_id;
-  msg->peer1 = *id1;
-  if (NULL != id2)
-    msg->peer2 = *id2;
-  else
-    memset (&msg->peer2, 0, sizeof (msg->peer2));
-  neighbor = GMP_get (peer_id);
-  GMP_queue_add (neighbor, msg,
-                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
-                 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 2,
-                 sizeof (struct GNUNET_CADET_ConnectionBroken),
-                 NULL, GNUNET_SYSERR, /* connection, fwd */
-                 NULL, NULL); /* continuation */
-}
-
-
-/**
- * Send keepalive packets for a connection.
- *
- * @param c Connection to keep alive..
- * @param fwd Is this a FWD keepalive? (owner -> dest).
- */
-static void
-send_connection_keepalive (struct CadetConnection *c, int fwd)
-{
-  struct GNUNET_MessageHeader msg;
-  struct CadetFlowControl *fc;
-
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "keepalive %s for connection %s\n",
-       GM_f2s (fwd), GMC_2s (c));
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  if (0 < fc->queue_n)
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n");
-  }
-
-  GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
-
-  GNUNET_assert (NULL != c->t);
-  msg.size = htons (sizeof (msg));
-  msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE);
-
-  GNUNET_assert (NULL ==
-                 GMT_send_prebuilt_message (&msg, c->t, c,
-                                            GNUNET_NO, NULL, NULL));
-}
-
-
-/**
- * Send CONNECTION_{CREATE/ACK} packets for a connection.
- *
- * @param c Connection for which to send the message.
- * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK.
- */
-static void
-connection_recreate (struct CadetConnection *c, int fwd)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
-  if (fwd)
-    GMC_send_create (c);
-  else
-    send_connection_ack (c, GNUNET_NO);
-}
-
-
-/**
- * Generic connection timer management.
- * Depending on the role of the peer in the connection will send the
- * appropriate message (build or keepalive)
- *
- * @param c Conncetion to maintain.
- * @param fwd Is FWD?
- */
-static void
-connection_maintain (struct CadetConnection *c, int fwd)
-{
-  if (GNUNET_NO != c->destroy)
-    return;
-
-  if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (c->t))
-  {
-    /* TODO DHT GET with RO_BART */
-    return;
-  }
-  switch (c->state)
-  {
-    case CADET_CONNECTION_NEW:
-      GNUNET_break (0);
-      /* fall-through */
-    case CADET_CONNECTION_SENT:
-      connection_recreate (c, fwd);
-      break;
-    case CADET_CONNECTION_READY:
-      send_connection_keepalive (c, fwd);
-      break;
-    default:
-      break;
-  }
-}
-
-
-
-/**
- * Keep the connection alive.
- *
- * @param c Connection to keep alive.
- * @param fwd Direction.
- * @param shutdown Are we shutting down? (Don't send traffic)
- *                 Non-zero value for true, not necessarily GNUNET_YES.
- */
-static void
-connection_keepalive (struct CadetConnection *c, int fwd, int shutdown)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s keepalive for %s\n",
-       GM_f2s (fwd), GMC_2s (c));
-
-  if (fwd)
-    c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
-  else
-    c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (GNUNET_NO != shutdown)
-    return;
-
-  connection_maintain (c, fwd);
-
-  /* Next execution will be scheduled by message_sent */
-}
-
-
-/**
- * Keep the connection alive in the FWD direction.
- *
- * @param cls Closure (connection to keepalive).
- * @param tc TaskContext.
- */
-static void
-connection_fwd_keepalive (void *cls,
-                          const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  connection_keepalive ((struct CadetConnection *) cls,
-                        GNUNET_YES,
-                        tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN);
-}
-
-
-/**
- * Keep the connection alive in the BCK direction.
- *
- * @param cls Closure (connection to keepalive).
- * @param tc TaskContext.
- */
-static void
-connection_bck_keepalive (void *cls,
-                          const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  connection_keepalive ((struct CadetConnection *) cls,
-                        GNUNET_NO,
-                        tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN);
-}
-
-
-/**
- * Schedule next keepalive task, taking in consideration
- * the connection state and number of retries.
- *
- * If the peer is not the origin, do nothing.
- *
- * @param c Connection for which to schedule the next keepalive.
- * @param fwd Direction for the next keepalive.
- */
-static void
-schedule_next_keepalive (struct CadetConnection *c, int fwd)
-{
-  struct GNUNET_TIME_Relative delay;
-  GNUNET_SCHEDULER_TaskIdentifier *task_id;
-  GNUNET_SCHEDULER_Task keepalive_task;
-
-  if (GNUNET_NO == GMC_is_origin (c, fwd))
-    return;
-
-  /* Calculate delay to use, depending on the state of the connection */
-  if (CADET_CONNECTION_READY == c->state)
-  {
-    delay = refresh_connection_time;
-  }
-  else
-  {
-    if (1 > c->create_retry)
-      c->create_retry = 1;
-    delay = GNUNET_TIME_relative_multiply (create_connection_time,
-                                           c->create_retry);
-    if (c->create_retry < 64)
-      c->create_retry *= 2;
-  }
-
-  /* Select direction-dependent parameters */
-  if (GNUNET_YES == fwd)
-  {
-    task_id = &c->fwd_maintenance_task;
-    keepalive_task = &connection_fwd_keepalive;
-  }
-  else
-  {
-    task_id = &c->bck_maintenance_task;
-    keepalive_task = &connection_bck_keepalive;
-  }
-
-  /* Check that no one scheduled it before us */
-  if (GNUNET_SCHEDULER_NO_TASK != *task_id)
-  {
-    /* No need for a _break. It can happen for instance when sending a SYNACK
-     * for a duplicate SYN: the first SYNACK scheduled the task. */
-    GNUNET_SCHEDULER_cancel (*task_id);
-  }
-
-  /* Schedule the task */
-  *task_id = GNUNET_SCHEDULER_add_delayed (delay, keepalive_task, c);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "next keepalive in %s\n",
-       GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
-}
-
-
-/**
- * @brief Re-initiate traffic on this connection if necessary.
- *
- * Check if there is traffic queued towards this peer
- * and the core transmit handle is NULL (traffic was stalled).
- * If so, call core tmt rdy.
- *
- * @param c Connection on which initiate traffic.
- * @param fwd Is this about fwd traffic?
- */
-static void
-connection_unlock_queue (struct CadetConnection *c, int fwd)
-{
-  struct CadetPeer *peer;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-              "connection_unlock_queue %s on %s\n",
-              GM_f2s (fwd), GMC_2s (c));
-
-  if (GMC_is_terminal (c, fwd))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
-    return;
-  }
-
-  peer = get_hop (c, fwd);
-  GMP_queue_unlock (peer, c);
-}
-
-
-/**
- * Cancel all transmissions that belong to a certain connection.
- *
- * If the connection is scheduled for destruction and no more messages are 
left,
- * the connection will be destroyed by the continuation call.
- *
- * @param c Connection which to cancel. Might be destroyed during this call.
- * @param fwd Cancel fwd traffic?
- */
-static void
-connection_cancel_queues (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-  struct CadetPeer *peer;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " *** Cancel %s queues for connection %s\n",
-       GM_f2s (fwd), GMC_2s (c));
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
-  {
-    GNUNET_SCHEDULER_cancel (fc->poll_task);
-    fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc);
-  }
-  peer = get_hop (c, fwd);
-  GMP_queue_cancel (peer, c);
-}
-
-
-/**
- * Function called if a connection has been stalled for a while,
- * possibly due to a missed ACK. Poll the neighbor about its ACK status.
- *
- * @param cls Closure (poll ctx).
- * @param tc TaskContext.
- */
-static void
-connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Callback called when a queued POLL message is sent.
- *
- * @param cls Closure (FC).
- * @param c Connection this message was on.
- * @param q Queue handler this call invalidates.
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-static void
-poll_sent (void *cls,
-           struct CadetConnection *c,
-           struct CadetConnectionQueue *q,
-           uint16_t type, int fwd, size_t size)
-{
-  struct CadetFlowControl *fc = cls;
-
-  if (2 == c->destroy)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n");
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " *** POLL sent for , scheduling new one!\n");
-  fc->poll_msg = NULL;
-  fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
-  fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
-                                                &connection_poll, fc);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
-
-}
-
-/**
- * Function called if a connection has been stalled for a while,
- * possibly due to a missed ACK. Poll the neighbor about its ACK status.
- *
- * @param cls Closure (poll ctx).
- * @param tc TaskContext.
- */
-static void
-connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetFlowControl *fc = cls;
-  struct GNUNET_CADET_Poll msg;
-  struct CadetConnection *c;
-
-  fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    return;
-  }
-
-  c = fc->c;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling connection %s %s\n",
-       GMC_2s (c), fc == &c->fwd_fc ? "FWD" : "BCK");
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_POLL);
-  msg.header.size = htons (sizeof (msg));
-  msg.pid = htonl (fc->last_pid_sent);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", 
fc->last_pid_sent);
-  fc->poll_msg =
-      GMC_send_prebuilt_message (&msg.header,
-                                 GNUNET_MESSAGE_TYPE_CADET_POLL,
-                                 fc->last_pid_sent,
-                                 c, fc == &c->fwd_fc, GNUNET_YES,
-                                 &poll_sent, fc);
-}
-
-
-/**
- * Timeout function due to lack of keepalive/traffic from the owner.
- * Destroys connection if called.
- *
- * @param cls Closure (connection to destroy).
- * @param tc TaskContext.
- */
-static void
-connection_fwd_timeout (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetConnection *c = cls;
-
-  c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s FWD timed out. Destroying.\n",
-       GMC_2s (c));
-  if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  GMC_destroy (c);
-}
-
-
-/**
- * Timeout function due to lack of keepalive/traffic from the destination.
- * Destroys connection if called.
- *
- * @param cls Closure (connection to destroy).
- * @param tc TaskContext
- */
-static void
-connection_bck_timeout (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetConnection *c = cls;
-
-  c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s BCK timed out. Destroying.\n",
-       GMC_2s (c));
-
-  if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  GMC_destroy (c);
-}
-
-
-/**
- * Resets the connection timeout task, some other message has done the
- * task's job.
- * - For the first peer on the direction this means to send
- *   a keepalive or a path confirmation message (either create or ACK).
- * - For all other peers, this means to destroy the connection,
- *   due to lack of activity.
- * Starts the timeout if no timeout was running (connection just created).
- *
- * @param c Connection whose timeout to reset.
- * @param fwd Is this forward?
- *
- * TODO use heap to improve efficiency of scheduler.
- */
-static void
-connection_reset_timeout (struct CadetConnection *c, int fwd)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd));
-
-  if (GMC_is_origin (c, fwd)) /* Startpoint */
-  {
-    schedule_next_keepalive (c, fwd);
-  }
-  else /* Relay, endpoint. */
-  {
-    struct GNUNET_TIME_Relative delay;
-    GNUNET_SCHEDULER_TaskIdentifier *ti;
-    GNUNET_SCHEDULER_Task f;
-
-    ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
-
-    if (GNUNET_SCHEDULER_NO_TASK != *ti)
-      GNUNET_SCHEDULER_cancel (*ti);
-    delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
-    f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
-    *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
-  }
-}
-
-
-/**
- * Add the connection to the list of both neighbors.
- *
- * @param c Connection.
- *
- * @return #GNUNET_OK if everything went fine
- *         #GNUNET_SYSERR if the was an error and @c c is malformed.
- */
-static int
-register_neighbors (struct CadetConnection *c)
-{
-  struct CadetPeer *next_peer;
-  struct CadetPeer *prev_peer;
-
-  next_peer = get_next_hop (c);
-  prev_peer = get_prev_hop (c);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "register neighbors for connection %s\n",
-       GMC_2s (c));
-  path_debug (c->path);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "own pos %u\n", c->own_pos);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to next peer %p\n",
-       GMC_2s (c), next_peer);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", next_peer, GMP_2s 
(next_peer));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to prev peer %p\n",
-       GMC_2s (c), prev_peer);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "prev peer %p %s\n", prev_peer, GMP_2s 
(prev_peer));
-
-  if (GNUNET_NO == GMP_is_neighbor (next_peer)
-      || GNUNET_NO == GMP_is_neighbor (prev_peer))
-  {
-    if (GMC_is_origin (c, GNUNET_YES))
-      GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO);
-    GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO);
-
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  register neighbors failed\n");
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  prev: %s, neighbor?: %d\n",
-         GMP_2s (prev_peer), GMP_is_neighbor (prev_peer));
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  next: %s, neighbor?: %d\n",
-         GMP_2s (next_peer), GMP_is_neighbor (next_peer));
-    return GNUNET_SYSERR;
-  }
-
-  GMP_add_connection (next_peer, c);
-  GMP_add_connection (prev_peer, c);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Remove the connection from the list of both neighbors.
- *
- * @param c Connection.
- */
-static void
-unregister_neighbors (struct CadetConnection *c)
-{
-  struct CadetPeer *peer;
-
-  peer = get_next_hop (c);
-  if (GNUNET_OK != GMP_remove_connection (peer, c))
-  {
-    GNUNET_assert (CADET_CONNECTION_NEW == c->state
-                  || CADET_CONNECTION_DESTROYED == c->state);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate: %u\n", c->state);
-    if (NULL != c->t) GMT_debug (c->t);
-  }
-
-  peer = get_prev_hop (c);
-  if (GNUNET_OK != GMP_remove_connection (peer, c))
-  {
-    GNUNET_assert (CADET_CONNECTION_NEW == c->state
-                  || CADET_CONNECTION_DESTROYED == c->state);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate: %u\n", c->state);
-    if (NULL != c->t) GMT_debug (c->t);
-  }
-}
-
-
-/**
- * Bind the connection to the peer and the tunnel to that peer.
- *
- * If the peer has no tunnel, create one. Update tunnel and connection
- * data structres to reflect new status.
- *
- * @param c Connection.
- * @param peer Peer.
- */
-static void
-add_to_peer (struct CadetConnection *c, struct CadetPeer *peer)
-{
-  GMP_add_tunnel (peer);
-  c->t = GMP_get_tunnel (peer);
-  GMT_add_connection (c->t, c);
-}
-
-
-/**
- * Builds a path from a PeerIdentity array.
- *
- * @param peers PeerIdentity array.
- * @param size Size of the @c peers array.
- * @param own_pos Output parameter: own position in the path.
- *
- * @return Fixed and shortened path.
- */
-static struct CadetPeerPath *
-build_path_from_peer_ids (struct GNUNET_PeerIdentity *peers,
-                          unsigned int size,
-                          unsigned int *own_pos)
-{
-  struct CadetPeerPath *path;
-  GNUNET_PEER_Id shortid;
-  unsigned int i;
-  unsigned int j;
-  unsigned int offset;
-
-  /* Create path */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
-  path = path_new (size);
-  *own_pos = 0;
-  offset = 0;
-  for (i = 0; i < size; i++)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  - %u: taking %s\n",
-         i, GNUNET_i2s (&peers[i]));
-    shortid = GNUNET_PEER_intern (&peers[i]);
-
-    /* Check for loops / duplicates */
-    for (j = 0; j < i - offset; j++)
-    {
-      if (path->peers[j] == shortid)
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "    already exists at pos %u\n", j);
-        offset = i - j;
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "    offset now %u\n", offset);
-        GNUNET_PEER_change_rc (shortid, -1);
-      }
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "    storing at %u\n", i - offset);
-    path->peers[i - offset] = shortid;
-    if (path->peers[i - offset] == myid)
-      *own_pos = i - offset;
-  }
-  path->length -= offset;
-
-  if (path->peers[*own_pos] != myid)
-  {
-    /* create path: self not found in path through self */
-    GNUNET_break_op (0);
-    path_destroy (path);
-    return NULL;
-  }
-
-  return path;
-}
-
-
-/**
- * Log receipt of message on stderr (INFO level).
- *
- * @param message Message received.
- * @param peer Peer who sent the message.
- * @param hash Connection ID.
- */
-static void
-log_message (const struct GNUNET_MessageHeader *message,
-             const struct GNUNET_PeerIdentity *peer,
-             const struct GNUNET_CADET_Hash *hash)
-{
-  LOG (GNUNET_ERROR_TYPE_INFO, "<-- %s on connection %s from %s\n",
-       GM_m2s (ntohs (message->type)), GNUNET_h2s (GM_h2hc (hash)),
-       GNUNET_i2s (peer));
-}
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * 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)
- */
-int
-GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
-                   const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_ConnectionCreate *msg;
-  struct GNUNET_PeerIdentity *id;
-  struct GNUNET_CADET_Hash *cid;
-  struct CadetPeerPath *path;
-  struct CadetPeer *dest_peer;
-  struct CadetPeer *orig_peer;
-  struct CadetConnection *c;
-  unsigned int own_pos;
-  uint16_t size;
-
-  /* Check size */
-  size = ntohs (message->size);
-  if (size < sizeof (struct GNUNET_CADET_ConnectionCreate))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Calculate hops */
-  size -= sizeof (struct GNUNET_CADET_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;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
-
-  /* Get parameters */
-  msg = (struct GNUNET_CADET_ConnectionCreate *) message;
-  cid = &msg->cid;
-  log_message (message, peer, cid);
-  id = (struct GNUNET_PeerIdentity *) &msg[1];
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "    origin: %s\n", GNUNET_i2s (id));
-
-  /* Create connection */
-  c = connection_get (cid);
-  if (NULL == c)
-  {
-    path = build_path_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1],
-                                     size, &own_pos);
-    if (NULL == path)
-      return GNUNET_OK;
-    if (0 == own_pos)
-    {
-      GNUNET_break_op (0);
-      path_destroy (path);
-      return GNUNET_OK;
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
-    c = GMC_new (cid, NULL, path_duplicate (path), own_pos);
-    if (NULL == c)
-    {
-      if (path->length - 1 == own_pos)
-      {
-        /* If we are destination, why did the creation fail? */
-        GNUNET_break (0);
-        return GNUNET_OK;
-      }
-      send_broken_unknown (cid, &my_full_id,
-                           GNUNET_PEER_resolve2 (path->peers[own_pos + 1]),
-                           peer);
-      path_destroy (path);
-      return GNUNET_OK;
-    }
-    GMP_add_path_to_all (path, GNUNET_NO);
-    connection_reset_timeout (c, GNUNET_YES);
-  }
-  else
-  {
-    path = path_duplicate (c->path);
-  }
-  if (CADET_CONNECTION_NEW == c->state)
-    connection_change_state (c, CADET_CONNECTION_SENT);
-
-  /* Remember peers */
-  dest_peer = GMP_get (&id[size - 1]);
-  orig_peer = GMP_get (&id[0]);
-
-  /* Is it a connection to us? */
-  if (c->own_pos == path->length - 1)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
-    GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES);
-
-    add_to_peer (c, orig_peer);
-    if (CADET_TUNNEL3_NEW == GMT_get_cstate (c->t))
-      GMT_change_cstate (c->t,  CADET_TUNNEL3_WAITING);
-
-    send_connection_ack (c, GNUNET_NO);
-    if (CADET_CONNECTION_SENT == c->state)
-      connection_change_state (c, CADET_CONNECTION_ACK);
-  }
-  else
-  {
-    /* It's for somebody else! Retransmit. */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
-    GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
-    GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
-    GMC_send_prebuilt_message (message,
-                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0,
-                               c, GNUNET_YES, GNUNET_YES,
-                               NULL, NULL);
-  }
-  path_destroy (path);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for path confirmations.
- *
- * @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)
- */
-int
-GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
-                    const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_ConnectionACK *msg;
-  struct CadetConnection *c;
-  struct CadetPeerPath *p;
-  struct CadetPeer *pi;
-  enum CadetConnectionState oldstate;
-  int fwd;
-
-  msg = (struct GNUNET_CADET_ConnectionACK *) message;
-  log_message (message, peer, &msg->cid);
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# control on unknown connection",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
-    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
-    return GNUNET_OK;
-  }
-
-  if (GNUNET_NO != c->destroy)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection being destroyed\n");
-    return GNUNET_OK;
-  }
-
-  oldstate = c->state;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n", GNUNET_i2s (peer));
-  pi = GMP_get (peer);
-  if (get_next_hop (c) == pi)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
-    fwd = GNUNET_NO;
-    if (CADET_CONNECTION_SENT == oldstate)
-      connection_change_state (c, CADET_CONNECTION_ACK);
-  }
-  else if (get_prev_hop (c) == pi)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
-    fwd = GNUNET_YES;
-    connection_change_state (c, CADET_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)
-  {
-    GMP_add_path_to_all (p, GNUNET_YES);
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-
-  /* Message for us as creator? */
-  if (GMC_is_origin (c, GNUNET_YES))
-  {
-    if (GNUNET_NO != fwd)
-    {
-      GNUNET_break_op (0);
-      return GNUNET_OK;
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
-
-    /* If just created, cancel the short timeout and start a long one */
-    if (CADET_CONNECTION_SENT == oldstate)
-      connection_reset_timeout (c, GNUNET_YES);
-
-    /* Change connection state */
-    connection_change_state (c, CADET_CONNECTION_READY);
-    send_connection_ack (c, GNUNET_YES);
-
-    /* Change tunnel state, trigger KX */
-    if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t))
-      GMT_change_cstate (c->t, CADET_TUNNEL3_READY);
-
-    return GNUNET_OK;
-  }
-
-  /* Message for us as destination? */
-  if (GMC_is_terminal (c, GNUNET_YES))
-  {
-    if (GNUNET_YES != fwd)
-    {
-      GNUNET_break_op (0);
-      return GNUNET_OK;
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
-
-    /* If just created, cancel the short timeout and start a long one */
-    if (CADET_CONNECTION_ACK == oldstate)
-      connection_reset_timeout (c, GNUNET_NO);
-
-    /* Change tunnel state */
-    if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t))
-      GMT_change_cstate (c->t, CADET_TUNNEL3_READY);
-
-    return GNUNET_OK;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-  GMC_send_prebuilt_message (message,
-                             GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0,
-                             c, fwd, GNUNET_YES, NULL, NULL);
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for notifications of broken connections.
- *
- * @param cls Closure (unused).
- * @param id Peer identity of sending neighbor.
- * @param message Message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-GMC_handle_broken (void* cls,
-                   const struct GNUNET_PeerIdentity* id,
-                   const struct GNUNET_MessageHeader* message)
-{
-  struct GNUNET_CADET_ConnectionBroken *msg;
-  struct CadetConnection *c;
-  int fwd;
-
-  msg = (struct GNUNET_CADET_ConnectionBroken *) message;
-  log_message (message, id, &msg->cid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
-              GNUNET_i2s (&msg->peer1));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
-              GNUNET_i2s (&msg->peer2));
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  duplicate CONNECTION_BROKEN\n");
-    return GNUNET_OK;
-  }
-
-  fwd = is_fwd (c, id);
-  if (GMC_is_terminal (c, fwd))
-  {
-    struct GNUNET_MessageHeader *out_msg;
-    struct CadetPeer *neighbor;
-    struct CadetPeer *endpoint;
-
-    neighbor = get_hop (c, !fwd);
-    endpoint = GMP_get_short (c->path->peers[c->path->length - 1]);
-    path_invalidate (c->path);
-    GMP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2);
-    c->state = CADET_CONNECTION_DESTROYED;
-    while (NULL != (out_msg = GMP_connection_pop (neighbor, c)))
-    {
-      GNUNET_assert (NULL ==
-                     GMT_send_prebuilt_message (out_msg, c->t, NULL, 
GNUNET_YES,
-                                                NULL, NULL));
-    }
-
-    GMC_destroy (c);
-  }
-  else
-  {
-    GMC_send_prebuilt_message (message,
-                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0,
-                               c, fwd, GNUNET_YES, NULL, NULL);
-    c->destroy = GNUNET_YES;
-    connection_cancel_queues (c, !fwd);
-  }
-
-  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)
- */
-int
-GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
-                    const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_ConnectionDestroy *msg;
-  struct CadetConnection *c;
-  int fwd;
-
-  msg = (struct GNUNET_CADET_ConnectionDestroy *) message;
-  log_message (message, peer, &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 connection",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection unknown: already 
destroyed?\n");
-    return GNUNET_OK;
-  }
-  fwd = is_fwd (c, peer);
-  if (GNUNET_SYSERR == fwd)
-  {
-    GNUNET_break_op (0); /* FIXME */
-    return GNUNET_OK;
-  }
-  if (GNUNET_NO == GMC_is_terminal (c, fwd))
-    GMC_send_prebuilt_message (message,
-                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0,
-                               c, fwd, GNUNET_YES, NULL, NULL);
-  else if (0 == c->pending_messages)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  directly destroying connection!\n");
-    GMC_destroy (c);
-    return GNUNET_OK;
-  }
-  c->destroy = GNUNET_YES;
-  c->state = CADET_CONNECTION_DESTROYED;
-  if (NULL != c->t)
-  {
-    GMT_remove_connection (c->t, c);
-    c->t = NULL;
-  }
-
-  return GNUNET_OK;
-}
-
-/**
- * Generic handler for cadet network encrypted traffic.
- *
- * @param peer Peer identity this notification is about.
- * @param msg Encrypted message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_CADET_Encrypted *msg)
-{
-  struct CadetConnection *c;
-  struct CadetPeer *neighbor;
-  struct CadetFlowControl *fc;
-  GNUNET_PEER_Id peer_id;
-  uint32_t pid;
-  uint32_t ttl;
-  size_t size;
-  int fwd;
-
-  log_message (&msg->header, peer, &msg->cid);
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size <
-      sizeof (struct GNUNET_CADET_Encrypted) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Check connection */
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "enc on unknown connection %s\n",
-         GNUNET_h2s (GM_h2hc (&msg->cid)));
-    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
-    return GNUNET_OK;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection %s\n", GMC_2s (c));
-
-  /* Check if origin is as expected */
-  neighbor = get_prev_hop (c);
-  peer_id = GNUNET_PEER_search (peer);
-  if (peer_id == GMP_get_short_id (neighbor))
-  {
-    fwd = GNUNET_YES;
-  }
-  else
-  {
-    neighbor = get_next_hop (c);
-    if (peer_id == GMP_get_short_id (neighbor))
-    {
-      fwd = GNUNET_NO;
-    }
-    else
-    {
-      /* Unexpected peer sending traffic on a connection. */
-      GNUNET_break_op (0);
-      return GNUNET_OK;
-    }
-  }
-
-  /* Check PID */
-  fc = fwd ? &c->bck_fc : &c->fwd_fc;
-  pid = ntohl (msg->pid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n",
-       pid, fc->last_pid_recv + 1);
-  if (GM_is_pid_bigger (pid, fc->last_ack_sent))
-  {
-    GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
-    GNUNET_break_op (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Received PID %u, (prev %u), ACK %u\n",
-         pid, fc->last_pid_recv, fc->last_ack_sent);
-    return GNUNET_OK;
-  }
-  if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv))
-  {
-    GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-                " PID %u not expected (%u+), dropping!\n",
-                pid, fc->last_pid_recv + 1);
-    return GNUNET_OK;
-  }
-  if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state)
-    connection_change_state (c, CADET_CONNECTION_READY);
-  connection_reset_timeout (c, fwd);
-  fc->last_pid_recv = pid;
-
-  /* Is this message for us? */
-  if (GMC_is_terminal (c, fwd))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
-    GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
-
-    if (NULL == c->t)
-    {
-      GNUNET_break (GNUNET_NO != c->destroy);
-      return GNUNET_OK;
-    }
-    fc->last_pid_recv = pid;
-    GMT_handle_encrypted (c->t, msg);
-    GMC_send_ack (c, fwd, GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  /* Message not for us: forward to next hop */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-  ttl = ntohl (msg->ttl);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
-  if (ttl == 0)
-  {
-    GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
-    GMC_send_ack (c, fwd, GNUNET_NO);
-    return GNUNET_OK;
-  }
-
-  GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-  GMC_send_prebuilt_message (&msg->header,
-                             GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0,
-                             c, fwd, GNUNET_NO, NULL, NULL);
-
-  return GNUNET_OK;
-}
-
-/**
- * Generic handler for cadet network encrypted traffic.
- *
- * @param peer Peer identity this notification is about.
- * @param msg Encrypted message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-handle_cadet_kx (const struct GNUNET_PeerIdentity *peer,
-                const struct GNUNET_CADET_KX *msg)
-{
-  struct CadetConnection *c;
-  struct CadetPeer *neighbor;
-  GNUNET_PEER_Id peer_id;
-  size_t size;
-  int fwd;
-
-  log_message (&msg->header, peer, &msg->cid);
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size <
-      sizeof (struct GNUNET_CADET_KX) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  /* Check connection */
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "kx on unknown connection %s\n",
-         GNUNET_h2s (GM_h2hc (&msg->cid)));
-    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
-    return GNUNET_OK;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", GMC_2s (c));
-
-  /* Check if origin is as expected */
-  neighbor = get_prev_hop (c);
-  peer_id = GNUNET_PEER_search (peer);
-  if (peer_id == GMP_get_short_id (neighbor))
-  {
-    fwd = GNUNET_YES;
-  }
-  else
-  {
-    neighbor = get_next_hop (c);
-    if (peer_id == GMP_get_short_id (neighbor))
-    {
-      fwd = GNUNET_NO;
-    }
-    else
-    {
-      /* Unexpected peer sending traffic on a connection. */
-      GNUNET_break_op (0);
-      return GNUNET_OK;
-    }
-  }
-
-  /* Count as connection confirmation. */
-  if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state)
-  {
-    connection_change_state (c, CADET_CONNECTION_READY);
-    if (NULL != c->t)
-    {
-      if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t))
-        GMT_change_cstate (c->t, CADET_TUNNEL3_READY);
-    }
-  }
-  connection_reset_timeout (c, fwd);
-
-  /* Is this message for us? */
-  if (GMC_is_terminal (c, fwd))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
-    GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
-    if (NULL == c->t)
-    {
-      GNUNET_break (0);
-      return GNUNET_OK;
-    }
-    GMT_handle_kx (c->t, &msg[1].header);
-    return GNUNET_OK;
-  }
-
-  /* Message not for us: forward to next hop */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-  GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-  GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX, 0,
-                             c, fwd, GNUNET_NO, NULL, NULL);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Core handler for encrypted cadet network traffic (channel mgmt, data).
- *
- * @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)
- */
-int
-GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_MessageHeader *message)
-{
-  return handle_cadet_encrypted (peer,
-                                (struct GNUNET_CADET_Encrypted *)message);
-}
-
-
-/**
- * Core handler for key exchange traffic (ephemeral key, ping, pong).
- *
- * @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)
- */
-int
-GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_MessageHeader *message)
-{
-  return handle_cadet_kx (peer,
-                         (struct GNUNET_CADET_KX *) message);
-}
-
-
-/**
- * Core handler for cadet 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)
- */
-int
-GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_ACK *msg;
-  struct CadetConnection *c;
-  struct CadetFlowControl *fc;
-  GNUNET_PEER_Id id;
-  uint32_t ack;
-  int fwd;
-
-  msg = (struct GNUNET_CADET_ACK *) message;
-  log_message (message, peer, &msg->cid);
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
-                              GNUNET_NO);
-    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
-    return GNUNET_OK;
-  }
-
-  /* Is this a forward or backward ACK? */
-  id = GNUNET_PEER_search (peer);
-  if (GMP_get_short_id (get_next_hop (c)) == id)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
-    fc = &c->fwd_fc;
-    fwd = GNUNET_YES;
-  }
-  else if (GMP_get_short_id (get_prev_hop (c)) == id)
-  {
-    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);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
-              ack, fc->last_ack_recv);
-  if (GM_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 &&
-      GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
-  {
-    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;
-}
-
-
-/**
- * Core handler for cadet 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)
- */
-int
-GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
-                 const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_Poll *msg;
-  struct CadetConnection *c;
-  struct CadetFlowControl *fc;
-  GNUNET_PEER_Id id;
-  uint32_t pid;
-  int fwd;
-
-  msg = (struct GNUNET_CADET_Poll *) message;
-  log_message (message, peer, &msg->cid);
-  c = connection_get (&msg->cid);
-  if (NULL == c)
-  {
-    GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
-                              GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL message on unknown connection %s!\n",
-         GNUNET_h2s (GM_h2hc (&msg->cid)));
-    send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
-    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 (GMP_get_short_id (get_next_hop (c)) == id)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
-    fc = &c->fwd_fc;
-  }
-  else if (GMP_get_short_id (get_prev_hop (c)) == id)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
-    fc = &c->bck_fc;
-  }
-  else
-  {
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  }
-
-  pid = ntohl (msg->pid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n", pid, fc->last_pid_recv);
-  fc->last_pid_recv = pid;
-  fwd = fc == &c->bck_fc;
-  GMC_send_ack (c, fwd, GNUNET_YES);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * 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 fwd Is this a fwd ACK? (will go dest->root).
- * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
- */
-void
-GMC_send_ack (struct CadetConnection *c, int fwd, int force)
-{
-  unsigned int buffer;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "GMC send %s ACK on %s\n",
-       GM_f2s (fwd), GMC_2s (c));
-
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if (GNUNET_NO != c->destroy)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  being destroyed, why bother...\n");
-    return;
-  }
-
-  /* Get available buffer space */
-  if (GMC_is_terminal (c, fwd))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all channels\n");
-    buffer = GMT_get_channels_buffer (c->t);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
-    buffer = GMC_get_buffer (c, fwd);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
-  if (0 == buffer && GNUNET_NO == force)
-    return;
-
-  /* Send available buffer space */
-  if (GMC_is_origin (c, fwd))
-  {
-    GNUNET_assert (NULL != c->t);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channels...\n");
-    GMT_unchoke_channels (c->t);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
-    send_ack (c, buffer, fwd, force);
-  }
-}
-
-
-/**
- * Initialize the connections subsystem
- *
- * @param c Configuration handle.
- */
-void
-GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE",
-                                             &max_msgs_queue))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "CADET", "MAX_MSGS_QUEUE", "MISSING");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS",
-                                             &max_connections))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "CADET", "MAX_CONNECTIONS", "MISSING");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "CADET", 
"REFRESH_CONNECTION_TIME",
-                                           &refresh_connection_time))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "CADET", "REFRESH_CONNECTION_TIME", "MISSING");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  create_connection_time = GNUNET_TIME_UNIT_SECONDS;
-  connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO);
-}
-
-
-/**
- * Destroy each connection on shutdown.
- *
- * @param cls Closure (unused).
- * @param key Current key code (CID, unused).
- * @param value Value in the hash map (connection)
- *
- * @return #GNUNET_YES, because we should continue to iterate,
- */
-static int
-shutdown_iterator (void *cls,
-                   const struct GNUNET_HashCode *key,
-                   void *value)
-{
-  struct CadetConnection *c = value;
-
-  GMC_destroy (c);
-  return GNUNET_YES;
-}
-
-
-/**
- * Shut down the connections subsystem.
- */
-void
-GMC_shutdown (void)
-{
-  GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, 
NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (connections);
-  connections = NULL;
-}
-
-
-struct CadetConnection *
-GMC_new (const struct GNUNET_CADET_Hash *cid,
-         struct CadetTunnel3 *t,
-         struct CadetPeerPath *p,
-         unsigned int own_pos)
-{
-  struct CadetConnection *c;
-
-  c = GNUNET_new (struct CadetConnection);
-  c->id = *cid;
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (connections,
-                                                    GMC_get_h (c), c,
-                                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  fc_init (&c->fwd_fc);
-  fc_init (&c->bck_fc);
-  c->fwd_fc.c = c;
-  c->bck_fc.c = c;
-
-  c->t = t;
-  GNUNET_assert (own_pos <= p->length - 1);
-  c->own_pos = own_pos;
-  c->path = p;
-  p->c = c;
-
-  if (GNUNET_OK != register_neighbors (c))
-  {
-    if (0 == own_pos)
-    {
-      path_invalidate (c->path);
-      c->t = NULL;
-      c->path = NULL;
-    }
-    GMC_destroy (c);
-    return NULL;
-  }
-
-  return c;
-}
-
-
-void
-GMC_destroy (struct CadetConnection *c)
-{
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */
-    return;            /* -> message_sent -> GMC_destroy. Don't loop. */
-  c->destroy = 2;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n",
-       &c->fwd_fc, &c->bck_fc);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
-       c->fwd_fc.poll_task, c->bck_fc.poll_task);
-
-  /* Cancel all traffic */
-  if (NULL != c->path)
-  {
-    connection_cancel_queues (c, GNUNET_YES);
-    connection_cancel_queues (c, GNUNET_NO);
-    unregister_neighbors (c);
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
-       c->fwd_fc.poll_task, c->bck_fc.poll_task);
-
-  /* Cancel maintainance task (keepalive/timeout) */
-  if (NULL != c->fwd_fc.poll_msg)
-  {
-    GMC_cancel (c->fwd_fc.poll_msg);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n");
-  }
-  if (NULL != c->bck_fc.poll_msg)
-  {
-    GMC_cancel (c->bck_fc.poll_msg);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n");
-  }
-
-  /* Delete from tunnel */
-  if (NULL != c->t)
-    GMT_remove_connection (c->t, c);
-
-  if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES) && NULL != c->path)
-    path_destroy (c->path);
-  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
-    GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
-  if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
-    GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
-  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task)
-  {
-    GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n");
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task)
-  {
-    GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n");
-  }
-
-  GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (connections,
-                                                      GMC_get_h (c), c));
-
-  GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
-  GNUNET_free (c);
-}
-
-/**
- * Get the connection ID.
- *
- * @param c Connection to get the ID from.
- *
- * @return ID of the connection.
- */
-const struct GNUNET_CADET_Hash *
-GMC_get_id (const struct CadetConnection *c)
-{
-  return &c->id;
-}
-
-
-/**
- * Get the connection ID.
- *
- * @param c Connection to get the ID from.
- *
- * @return ID of the connection.
- */
-const struct GNUNET_HashCode *
-GMC_get_h (const struct CadetConnection *c)
-{
-  return GM_h2hc (&c->id);
-}
-
-
-/**
- * Get the connection path.
- *
- * @param c Connection to get the path from.
- *
- * @return path used by the connection.
- */
-const struct CadetPeerPath *
-GMC_get_path (const struct CadetConnection *c)
-{
-  if (GNUNET_NO == c->destroy)
-    return c->path;
-  return NULL;
-}
-
-
-/**
- * Get the connection state.
- *
- * @param c Connection to get the state from.
- *
- * @return state of the connection.
- */
-enum CadetConnectionState
-GMC_get_state (const struct CadetConnection *c)
-{
-  return c->state;
-}
-
-/**
- * Get the connection tunnel.
- *
- * @param c Connection to get the tunnel from.
- *
- * @return tunnel of the connection.
- */
-struct CadetTunnel3 *
-GMC_get_tunnel (const struct CadetConnection *c)
-{
-  return c->t;
-}
-
-
-/**
- * Get free buffer space in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - max_msgs_queue/max_connections]
- */
-unsigned int
-GMC_get_buffer (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-
-  return (fc->queue_max - fc->queue_n);
-}
-
-/**
- * Get how many messages have we allowed to send to us from a direction.
- *
- * @param c Connection.
- * @param fwd Are we asking about traffic from FWD (BCK messages)?
- *
- * @return last_ack_sent - last_pid_recv
- */
-unsigned int
-GMC_get_allowed (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent))
-  {
-    return 0;
-  }
-  return (fc->last_ack_sent - fc->last_pid_recv);
-}
-
-/**
- * Get messages queued in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Number of messages queued.
- */
-unsigned int
-GMC_get_qn (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-
-  return fc->queue_n;
-}
-
-
-/**
- * Get next PID to use.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Last PID used + 1.
- */
-unsigned int
-GMC_get_pid (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-
-  return fc->last_pid_sent + 1;
-}
-
-
-/**
- * Allow the connection to advertise a buffer of the given size.
- *
- * The connection will send an @c fwd ACK message (so: in direction !fwd)
- * allowing up to last_pid_recv + buffer.
- *
- * @param c Connection.
- * @param buffer How many more messages the connection can accept.
- * @param fwd Is this about FWD traffic? (The ack will go dest->root).
- */
-void
-GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  allowing %s %u messages %s\n",
-       GMC_2s (c), buffer, GM_f2s (fwd));
-  send_ack (c, buffer, fwd, GNUNET_NO);
-}
-
-
-/**
- * Notify other peers on a connection of a broken link. Mark connections
- * to destroy after all traffic has been sent.
- *
- * @param c Connection on which there has been a disconnection.
- * @param peer Peer that disconnected.
- */
-void
-GMC_notify_broken (struct CadetConnection *c,
-                   struct CadetPeer *peer)
-{
-  int fwd;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " notify broken on %s due to %s disconnect\n",
-       GMC_2s (c), GMP_2s (peer));
-
-  fwd = peer == get_prev_hop (c);
-
-  if (GNUNET_YES == GMC_is_terminal (c, fwd))
-  {
-    /* Local shutdown, no one to notify about this. */
-    GMC_destroy (c);
-    return;
-  }
-  if (GNUNET_NO == c->destroy)
-    send_broken (c, &my_full_id, GMP_get_id (peer), fwd);
-
-  /* Connection will have at least one pending message
-   * (the one we just scheduled), so no point in checking whether to
-   * destroy immediately. */
-  c->destroy = GNUNET_YES;
-  c->state = CADET_CONNECTION_DESTROYED;
-
-  /**
-   * Cancel all queues, if no message is left, connection will be destroyed.
-   */
-  connection_cancel_queues (c, !fwd);
-
-  return;
-}
-
-
-/**
- * Is this peer the first one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
- */
-int
-GMC_is_origin (struct CadetConnection *c, int fwd)
-{
-  if (!fwd && c->path->length - 1 == c->own_pos )
-    return GNUNET_YES;
-  if (fwd && 0 == c->own_pos)
-    return GNUNET_YES;
-  return GNUNET_NO;
-}
-
-
-/**
- * Is this peer the last one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *            Note that the ROOT is the terminal for BCK traffic!
- *
- * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
- */
-int
-GMC_is_terminal (struct CadetConnection *c, int fwd)
-{
-  return GMC_is_origin (c, !fwd);
-}
-
-
-/**
- * See if we are allowed to send by the next hop in the given direction.
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES in case it's OK to send.
- */
-int
-GMC_is_sendable (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " checking sendability of %s traffic on %s\n",
-       GM_f2s (fwd), GMC_2s (c));
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return GNUNET_YES;
-  }
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " last ack recv: %u, last pid sent: %u\n",
-       fc->last_ack_recv, fc->last_pid_sent);
-  if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n");
-    return GNUNET_YES;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n");
-  return GNUNET_NO;
-}
-
-
-/**
- * Check if this connection is a direct one (never trim a direct connection).
- *
- * @param c Connection.
- *
- * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
- */
-int
-GMC_is_direct (struct CadetConnection *c)
-{
-  return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO;
-}
-
-/**
- * Sends an already built message on a connection, properly registering
- * all used resources.
- *
- * @param message Message to send. Function makes a copy of it.
- *                If message is not hop-by-hop, decrements TTL of copy.
- * @param payload_type Type of payload, in case the message is encrypted.
- * @param c Connection on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param force Force the connection to accept the message (buffer overfill).
- * @param cont Continuation called once message is sent. Can be NULL.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it's sent.
- *         NULL on error or if @c cont is NULL.
- *         Invalid on @c cont call.
- */
-struct CadetConnectionQueue *
-GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           uint16_t payload_type, uint32_t payload_id,
-                           struct CadetConnection *c, int fwd, int force,
-                           GMC_sent cont, void *cont_cls)
-{
-  struct CadetFlowControl *fc;
-  struct CadetConnectionQueue *q;
-  void *data;
-  size_t size;
-  uint16_t type;
-  int droppable;
-
-  size = ntohs (message->size);
-  data = GNUNET_malloc (size);
-  memcpy (data, message, size);
-  type = ntohs (message->type);
-  LOG (GNUNET_ERROR_TYPE_INFO, "--> %s (%s %u) on connection %s (%u bytes)\n",
-       GM_m2s (type), GM_m2s (payload_type), payload_id, GMC_2s (c), size);
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  droppable = GNUNET_NO == force;
-  switch (type)
-  {
-    struct GNUNET_CADET_Encrypted *emsg;
-    struct GNUNET_CADET_KX        *kmsg;
-    struct GNUNET_CADET_ACK       *amsg;
-    struct GNUNET_CADET_Poll      *pmsg;
-    struct GNUNET_CADET_ConnectionDestroy *dmsg;
-    struct GNUNET_CADET_ConnectionBroken  *bmsg;
-    uint32_t ttl;
-
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-      emsg = (struct GNUNET_CADET_Encrypted *) data;
-      ttl = ntohl (emsg->ttl);
-      if (0 == ttl)
-      {
-        GNUNET_break_op (0);
-        GNUNET_free (data);
-        return NULL;
-      }
-      emsg->cid = c->id;
-      emsg->ttl = htonl (ttl - 1);
-      emsg->pid = htonl (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  Q_N+ %p %u\n", fc, fc->queue_n);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "     ack recv %u\n", fc->last_ack_recv);
-      if (GNUNET_YES == droppable)
-      {
-        fc->queue_n++;
-      }
-      else
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  not droppable, Q_N stays the same\n");
-      }
-      if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
-      {
-        GMC_start_poll (c, fwd);
-      }
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
-      kmsg = (struct GNUNET_CADET_KX *) data;
-      kmsg->cid = c->id;
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
-      amsg = (struct GNUNET_CADET_ACK *) data;
-      amsg->cid = c->id;
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
-      droppable = GNUNET_NO;
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
-      pmsg = (struct GNUNET_CADET_Poll *) data;
-      pmsg->cid = c->id;
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
-      droppable = GNUNET_NO;
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
-      dmsg = (struct GNUNET_CADET_ConnectionDestroy *) data;
-      dmsg->cid = c->id;
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
-      bmsg = (struct GNUNET_CADET_ConnectionBroken *) data;
-      bmsg->cid = c->id;
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
-      GNUNET_break (0);
-      /* falltrough */
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-      break;
-
-    default:
-      GNUNET_break (0);
-      GNUNET_free (data);
-      return NULL;
-  }
-
-  if (fc->queue_n > fc->queue_max && droppable)
-  {
-    GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
-                              1, GNUNET_NO);
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-                "queue full: %u/%u\n",
-                fc->queue_n, fc->queue_max);
-    if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type)
-    {
-      fc->queue_n--;
-    }
-    GNUNET_free (data);
-    return NULL; /* Drop this message */
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u\n", c, c->pending_messages);
-//   c->pending_messages++;
-
-  q = GNUNET_new (struct CadetConnectionQueue);
-  q->forced = !droppable;
-  q->q = GMP_queue_add (get_hop (c, fwd), data, type, payload_type, payload_id,
-                        size, c, fwd, &conn_message_sent, q);
-  if (NULL == q->q)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING dropping msg on %s\n", GMC_2s (c));
-    GNUNET_free (data);
-    GNUNET_free (q);
-    return NULL;
-  }
-  q->cont = cont;
-  q->cont_cls = cont_cls;
-  return (NULL == cont) ? NULL : q;
-}
-
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GMC_cancel (struct CadetConnectionQueue *q)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "!  GMC cancel message\n");
-
-  /* queue destroy calls message_sent, which calls q->cont and frees q */
-  GMP_queue_destroy (q->q, GNUNET_YES, GNUNET_NO, 0);
-}
-
-
-/**
- * Sends a CREATE CONNECTION message for a path to a peer.
- * Changes the connection and tunnel states if necessary.
- *
- * @param connection Connection to create.
- */
-void
-GMC_send_create (struct CadetConnection *connection)
-{
-  enum CadetTunnel3CState state;
-  size_t size;
-
-  size = sizeof (struct GNUNET_CADET_ConnectionCreate);
-  size += connection->path->length * sizeof (struct GNUNET_PeerIdentity);
-
-  LOG (GNUNET_ERROR_TYPE_INFO, "===> %s on connection %s  (%u bytes)\n",
-       GM_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE),
-       GMC_2s (connection), size);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u (create)\n",
-       connection, connection->pending_messages);
-  connection->pending_messages++;
-
-  connection->maintenance_q =
-    GMP_queue_add (get_next_hop (connection), NULL,
-                   GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
-                   GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0,
-                   size, connection, GNUNET_YES, &conn_message_sent, NULL);
-
-  state = GMT_get_cstate (connection->t);
-  if (CADET_TUNNEL3_SEARCHING == state || CADET_TUNNEL3_NEW == state)
-    GMT_change_cstate (connection->t, CADET_TUNNEL3_WAITING);
-  if (CADET_CONNECTION_NEW == connection->state)
-    connection_change_state (connection, CADET_CONNECTION_SENT);
-}
-
-
-/**
- * Send a message to all peers in this connection that the connection
- * is no longer valid.
- *
- * If some peer should not receive the message, it should be zero'ed out
- * before calling this function.
- *
- * @param c The connection whose peers to notify.
- */
-void
-GMC_send_destroy (struct CadetConnection *c)
-{
-  struct GNUNET_CADET_ConnectionDestroy msg;
-
-  if (GNUNET_YES == c->destroy)
-    return;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);;
-  msg.cid = c->id;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-              "  sending connection destroy for connection %s\n",
-              GMC_2s (c));
-
-  if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
-    GMC_send_prebuilt_message (&msg.header,
-                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0,
-                               c, GNUNET_YES, GNUNET_YES, NULL, NULL);
-  if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
-    GMC_send_prebuilt_message (&msg.header,
-                               GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0,
-                               c, GNUNET_NO, GNUNET_YES, NULL, NULL);
-  c->destroy = GNUNET_YES;
-  c->state = CADET_CONNECTION_DESTROYED;
-}
-
-
-/**
- * @brief Start a polling timer for the connection.
- *
- * When a neighbor does not accept more traffic on the connection it could be
- * caused by a simple congestion or by a lost ACK. Polling enables to check
- * for the lastest ACK status for a connection.
- *
- * @param c Connection.
- * @param fwd Should we poll in the FWD direction?
- */
-void
-GMC_start_poll (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL %s requested\n",
-       GM_f2s (fwd));
-  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task || NULL != fc->poll_msg)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   not needed (%u, %p)\n",
-         fc->poll_task, fc->poll_msg);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL started on request\n");
-  fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
-                                                &connection_poll,
-                                                fc);
-}
-
-
-/**
- * @brief Stop polling a connection for ACKs.
- *
- * Once we have enough ACKs for future traffic, polls are no longer necessary.
- *
- * @param c Connection.
- * @param fwd Should we stop the poll in the FWD direction?
- */
-void
-GMC_stop_poll (struct CadetConnection *c, int fwd)
-{
-  struct CadetFlowControl *fc;
-
-  fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
-  {
-    GNUNET_SCHEDULER_cancel (fc->poll_task);
-    fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-}
-
-/**
- * Get a (static) string for a connection.
- *
- * @param c Connection.
- */
-const char *
-GMC_2s (const struct CadetConnection *c)
-{
-  if (NULL == c)
-    return "NULL";
-
-  if (NULL != c->t)
-  {
-    static char buf[128];
-
-    sprintf (buf, "%s (->%s)",
-             GNUNET_h2s (GM_h2hc (GMC_get_id (c))), GMT_2s (c->t));
-    return buf;
-  }
-  return GNUNET_h2s (GM_h2hc (&c->id));
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_connection.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_connection.h   2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_connection.h   2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,566 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_connection.h
- * @brief cadet service; dealing with connections
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMC (Gnunet Cadet 
Connection)
- */
-
-#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
-#define GNUNET_SERVICE_CADET_CONNECTION_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_util_lib.h"
-
-
-/**
- * All the states a connection can be in.
- */
-enum CadetConnectionState
-{
-  /**
-   * Uninitialized status, should never appear in operation.
-   */
-  CADET_CONNECTION_NEW,
-
-  /**
-   * Connection create message sent, waiting for ACK.
-   */
-  CADET_CONNECTION_SENT,
-
-  /**
-   * Connection ACK sent, waiting for ACK.
-   */
-  CADET_CONNECTION_ACK,
-
-  /**
-   * Connection confirmed, ready to carry traffic.
-   */
-  CADET_CONNECTION_READY,
-
-  /**
-   * Connection to be destroyed, just waiting to empty queues.
-   */
-  CADET_CONNECTION_DESTROYED,
-};
-
-
-/**
- * Struct containing all information regarding a connection to a peer.
- */
-struct CadetConnection;
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetConnectionQueue;
-
-#include "cadet_path.h"
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_peer.h"
-
-
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param c Connection this message was on.
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-typedef void (*GMC_sent) (void *cls,
-                          struct CadetConnection *c,
-                          struct CadetConnectionQueue *q,
-                          uint16_t type, int fwd, size_t size);
-
-/**
- * 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)
- */
-int
-GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
-                   const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for path confirmations.
- *
- * @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)
- */
-int
-GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
-                    const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for notifications of broken paths
- *
- * @param cls Closure (unused).
- * @param id Peer identity of sending neighbor.
- * @param message Message.
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-GMC_handle_broken (void* cls,
-                   const struct GNUNET_PeerIdentity* id,
-                   const struct GNUNET_MessageHeader* message);
-
-/**
- * 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)
- */
-int
-GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
-                    const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for encrypted cadet network traffic (channel mgmt, data).
- *
- * @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)
- */
-int
-GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for key exchange traffic (ephemeral key, ping, pong).
- *
- * @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)
- */
-int
-GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for cadet 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)
- */
-int
-GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
-                const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for cadet 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)
- */
-int
-GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
-                 const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for cadet 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.
- */
-int
-GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_MessageHeader *message);
-
-/**
- * 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 fwd Is this a fwd ACK? (will go dest->root).
- * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
- */
-void
-GMC_send_ack (struct CadetConnection *c, int fwd, int force);
-
-/**
- * Initialize the connections subsystem
- *
- * @param c Configuration handle.
- */
-void
-GMC_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the connections subsystem.
- */
-void
-GMC_shutdown (void);
-
-/**
- * Create a connection.
- *
- * @param cid Connection ID (either created locally or imposed remotely).
- * @param t Tunnel this connection belongs to (or NULL);
- * @param p Path this connection has to use.
- * @param own_pos Own position in the @c p path.
- *
- * @return Newly created connection, NULL in case of error (own id not in 
path).
- */
-struct CadetConnection *
-GMC_new (const struct GNUNET_CADET_Hash *cid,
-         struct CadetTunnel3 *t,
-         struct CadetPeerPath *p,
-         unsigned int own_pos);
-
-/**
- * Connection is no longer needed: destroy it.
- *
- * Cancels all pending traffic (including possible DESTROY messages), all
- * maintenance tasks and removes the connection from neighbor peers and tunnel.
- *
- * @param c Connection to destroy.
- */
-void
-GMC_destroy (struct CadetConnection *c);
-
-/**
- * Get the connection ID.
- *
- * @param c Connection to get the ID from.
- *
- * @return ID of the connection.
- */
-const struct GNUNET_CADET_Hash *
-GMC_get_id (const struct CadetConnection *c);
-
-
-/**
- * Get a hash for the connection ID.
- *
- * @param c Connection to get the hash.
- *
- * @return Hash expanded from the ID of the connection.
- */
-const struct GNUNET_HashCode *
-GMC_get_h (const struct CadetConnection *c);
-
-
-/**
- * Get the connection path.
- *
- * @param c Connection to get the path from.
- *
- * @return path used by the connection.
- */
-const struct CadetPeerPath *
-GMC_get_path (const struct CadetConnection *c);
-
-/**
- * Get the connection state.
- *
- * @param c Connection to get the state from.
- *
- * @return state of the connection.
- */
-enum CadetConnectionState
-GMC_get_state (const struct CadetConnection *c);
-
-/**
- * Get the connection tunnel.
- *
- * @param c Connection to get the tunnel from.
- *
- * @return tunnel of the connection.
- */
-struct CadetTunnel3 *
-GMC_get_tunnel (const struct CadetConnection *c);
-
-/**
- * Get free buffer space in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - max_msgs_queue/max_connections]
- */
-unsigned int
-GMC_get_buffer (struct CadetConnection *c, int fwd);
-
-/**
- * Get how many messages have we allowed to send to us from a direction.
- *
- * @param c Connection.
- * @param fwd Are we asking about traffic from FWD (BCK messages)?
- *
- * @return last_ack_sent - last_pid_recv
- */
-unsigned int
-GMC_get_allowed (struct CadetConnection *c, int fwd);
-
-/**
- * Get messages queued in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Number of messages queued.
- */
-unsigned int
-GMC_get_qn (struct CadetConnection *c, int fwd);
-
-/**
- * Get next PID to use.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Last PID used + 1.
- */
-unsigned int
-GMC_get_pid (struct CadetConnection *c, int fwd);
-
-/**
- * Allow the connection to advertise a buffer of the given size.
- *
- * The connection will send an @c fwd ACK message (so: in direction !fwd)
- * allowing up to last_pid_recv + buffer.
- *
- * @param c Connection.
- * @param buffer How many more messages the connection can accept.
- * @param fwd Is this about FWD traffic? (The ack will go dest->root).
- */
-void
-GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd);
-
-/**
- * Send FWD keepalive packets for a connection.
- *
- * @param cls Closure (connection for which to send the keepalive).
- * @param tc Notification context.
- */
-void
-GMC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- * Send BCK keepalive packets for a connection.
- *
- * @param cls Closure (connection for which to send the keepalive).
- * @param tc Notification context.
- */
-void
-GMC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Notify other peers on a connection of a broken link. Mark connections
- * to destroy after all traffic has been sent.
- *
- * @param c Connection on which there has been a disconnection.
- * @param peer Peer that disconnected.
- */
-void
-GMC_notify_broken (struct CadetConnection *c,
-                   struct CadetPeer *peer);
-
-/**
- * Is this peer the first one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
- */
-int
-GMC_is_origin (struct CadetConnection *c, int fwd);
-
-/**
- * Is this peer the last one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *            Note that the ROOT is the terminal for BCK traffic!
- *
- * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
- */
-int
-GMC_is_terminal (struct CadetConnection *c, int fwd);
-
-/**
- * See if we are allowed to send by the next hop in the given direction.
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES in case it's OK to send.
- */
-int
-GMC_is_sendable (struct CadetConnection *c, int fwd);
-
-/**
- * Check if this connection is a direct one (never trim a direct connection).
- *
- * @param c Connection.
- *
- * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
- */
-int
-GMC_is_direct (struct CadetConnection *c);
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GMC_cancel (struct CadetConnectionQueue *q);
-
-/**
- * Sends an already built message on a connection, properly registering
- * all used resources.
- *
- * @param message Message to send. Function makes a copy of it.
- *                If message is not hop-by-hop, decrements TTL of copy.
- * @param payload_type Type of payload, in case the message is encrypted.
- * @param c Connection on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param force Force the connection to accept the message (buffer overfill).
- * @param cont Continuation called once message is sent. Can be NULL.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it's sent.
- *         NULL on error or if @c cont is NULL.
- *         Invalid on @c cont call.
- */
-struct CadetConnectionQueue *
-GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           uint16_t payload_type, uint32_t payload_id,
-                           struct CadetConnection *c, int fwd, int force,
-                           GMC_sent cont, void *cont_cls);
-
-/**
- * Sends a CREATE CONNECTION message for a path to a peer.
- * Changes the connection and tunnel states if necessary.
- *
- * @param connection Connection to create.
- */
-void
-GMC_send_create (struct CadetConnection *connection);
-
-/**
- * Send a message to all peers in this connection that the connection
- * is no longer valid.
- *
- * If some peer should not receive the message, it should be zero'ed out
- * before calling this function.
- *
- * @param c The connection whose peers to notify.
- */
-void
-GMC_send_destroy (struct CadetConnection *c);
-
-/**
- * @brief Start a polling timer for the connection.
- *
- * When a neighbor does not accept more traffic on the connection it could be
- * caused by a simple congestion or by a lost ACK. Polling enables to check
- * for the lastest ACK status for a connection.
- *
- * @param c Connection.
- * @param fwd Should we poll in the FWD direction?
- */
-void
-GMC_start_poll (struct CadetConnection *c, int fwd);
-
-
-/**
- * @brief Stop polling a connection for ACKs.
- *
- * Once we have enough ACKs for future traffic, polls are no longer necessary.
- *
- * @param c Connection.
- * @param fwd Should we stop the poll in the FWD direction?
- */
-void
-GMC_stop_poll (struct CadetConnection *c, int fwd);
-
-/**
- * Get a (static) string for a connection.
- *
- * @param c Connection.
- */
-const char *
-GMC_2s (const struct CadetConnection *c);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_SERVICE_CADET_CONNECTION_H */
-#endif
-/* end of gnunet-service-cadet_connection.h */

Deleted: gnunet/src/mesh/gnunet-service-cadet_dht.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_dht.c  2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/gnunet-service-cadet_dht.c  2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,423 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_dht_service.h"
-#include "gnunet_statistics_service.h"
-
-#include "cadet_path.h"
-#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_hello.h"
-
-#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
-
-
-/******************************************************************************/
-/********************************   STRUCTS  
**********************************/
-/******************************************************************************/
-
-/**
- * Handle for DHT searches.
- */
-struct GMD_search_handle
-{
-  /** DHT_GET handle. */
-  struct GNUNET_DHT_GetHandle *dhtget;
-
-  /** Provided callback to call when a path is found. */
-  GMD_search_callback callback;
-
-  /** Provided closure. */
-  void *cls;
-
-  /** Peer ID searched for */
-  GNUNET_PEER_Id peer_id;
-};
-
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Own ID (short value).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Handle to use DHT.
- */
-static struct GNUNET_DHT_Handle *dht_handle;
-
-/**
- * How often to PUT own ID in the DHT.
- */
-static struct GNUNET_TIME_Relative id_announce_time;
-
-/**
- * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
- */
-static unsigned long long dht_replication_level;
-
-/**
- * Task to periodically announce itself in the network.
- */
-static GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
-
-/**
- * GET requests to stop on shutdown.
- */
-static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests;
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-
-/**
- * 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
- *
- * FIXME refactor and use build_path_from_peer_ids
- */
-static struct CadetPeerPath *
-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 CadetPeerPath *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;
-  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])
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
-      GNUNET_PEER_change_rc (id, -1);
-    }
-    else
-    {
-      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;
-  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])
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
-      GNUNET_PEER_change_rc (id, -1);
-    }
-    else
-    {
-      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 CADET_DEBUG
-  if (get_path_length > 0)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "   (first of GET: %s)\n",
-                GNUNET_i2s (&get_path[0]));
-  if (put_path_length > 0)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "   (first of PUT: %s)\n",
-                GNUNET_i2s (&put_path[0]));
-  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);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "       %u: %s\n", p->peers[i],
-                GNUNET_i2s (&peer_id));
-  }
-#endif
-  return p;
-}
-
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param exp when will this value expire
- * @param key key of the result
- * @param get_path path of the get request
- * @param get_path_length lenght of get_path
- * @param put_path path of the put request
- * @param put_path_length length of the put_path
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- */
-static void
-dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
-                    const struct GNUNET_HashCode * key,
-                    const struct GNUNET_PeerIdentity *get_path,
-                    unsigned int get_path_length,
-                    const struct GNUNET_PeerIdentity *put_path,
-                    unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
-                    size_t size, const void *data)
-{
-  struct GMD_search_handle *h = cls;
-  struct GNUNET_HELLO_Message *hello;
-  struct CadetPeerPath *p;
-  struct CadetPeer *peer;
-  char *s;
-
-  p = path_build_from_dht (get_path, get_path_length,
-                           put_path, put_path_length);
-  s = path_2s (p);
-  LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s);
-  GNUNET_free_non_null (s);
-  peer = GMP_get_short (p->peers[p->length - 1]);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GMP_2s (peer));
-  h->callback (h->cls, p);
-  path_destroy (p);
-  hello = (struct GNUNET_HELLO_Message *) data;
-  GMP_set_hello (peer, hello);
-  GMP_try_connect (peer);
-  return;
-}
-
-
-/**
- * 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 GNUNET_HashCode phash;
-  const struct GNUNET_HELLO_Message *hello;
-  size_t size;
-  struct GNUNET_TIME_Absolute expiration;
-  struct GNUNET_TIME_Relative retry_time;
-
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-  {
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
-
-  /* TODO
-   * - Set data expiration in function of X
-   * - Adapt X to churn
-   */
-  hello = GMH_get_mine ();
-  if (NULL == hello || (size = GNUNET_HELLO_size (hello)) == 0)
-  {
-    /* Peerinfo gave us no hello yet, try again in a second. */
-    announce_id_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                     &announce_id, cls);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  no hello, waiting!\n");
-    return;
-  }
-  expiration = GNUNET_HELLO_get_last_expiration (hello);
-  retry_time = GNUNET_TIME_absolute_get_remaining (expiration);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size);
-  memset (&phash, 0, sizeof (phash));
-  memcpy (&phash, &my_full_id, sizeof (my_full_id));
-  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_DHT_HELLO,       /* Block type */
-                  size,  /* Size of the data */
-                  (const char *) hello, /* Data itself */
-                  expiration,  /* Data expiration */
-                  retry_time, /* Retry time */
-                  NULL,         /* Continuation */
-                  NULL);        /* Continuation closure */
-  announce_id_task =
-      GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
-}
-
-/**
- * Iterator over hash map entries and stop GET requests before disconnecting
- * from the DHT.
- *
- * @param cls Closure (unused)
- * @param key Current peer ID.
- * @param value Value in the hash map (GMD_search_handle).
- *
- * @return #GNUNET_YES, we should continue to iterate,
- */
-int
-stop_get (void *cls,
-          uint32_t key,
-          void *value)
-{
-  struct GMD_search_handle *h = value;
-
-  GMD_search_stop (h);
-  return GNUNET_YES;
-}
-
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize the DHT subsystem.
- *
- * @param c Configuration.
- */
-void
-GMD_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", 
"DHT_REPLICATION_LEVEL",
-                                             &dht_replication_level))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "CADET", "DHT_REPLICATION_LEVEL", "USING 
DEFAULT");
-    dht_replication_level = 3;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME",
-                                           &id_announce_time))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "CADET", "ID_ANNOUNCE_TIME", "MISSING");
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  dht_handle = GNUNET_DHT_connect (c, 64);
-  if (NULL == dht_handle)
-  {
-    GNUNET_break (0);
-  }
-
-  announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL);
-  get_requests = GNUNET_CONTAINER_multihashmap32_create (32);
-}
-
-
-/**
- * Shut down the DHT subsystem.
- */
-void
-GMD_shutdown (void)
-{
-  GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL);
-  GNUNET_CONTAINER_multihashmap32_destroy (get_requests);
-  if (dht_handle != NULL)
-  {
-    GNUNET_DHT_disconnect (dht_handle);
-    dht_handle = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
-  {
-    GNUNET_SCHEDULER_cancel (announce_id_task);
-    announce_id_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-}
-
-struct GMD_search_handle *
-GMD_search (const struct GNUNET_PeerIdentity *peer_id,
-            GMD_search_callback callback, void *cls)
-{
-  struct GNUNET_HashCode phash;
-  struct GMD_search_handle *h;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "  Starting DHT GET for peer %s\n", GNUNET_i2s (peer_id));
-  memset (&phash, 0, sizeof (phash));
-  memcpy (&phash, peer_id, sizeof (*peer_id));
-  h = GNUNET_new (struct GMD_search_handle);
-  h->peer_id = GNUNET_PEER_intern (peer_id);
-  h->callback = callback;
-  h->cls = cls;
-  h->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
-                                    GNUNET_BLOCK_TYPE_DHT_HELLO, /* 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, h);
-  GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-  return h;
-}
-
-void
-GMD_search_stop (struct GMD_search_handle *h)
-{
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONTAINER_multihashmap32_remove (get_requests,
-                                                        h->peer_id, h));
-  GNUNET_DHT_get_stop (h->dhtget);
-  GNUNET_free (h);
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_dht.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_dht.h  2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/gnunet-service-cadet_dht.h  2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,92 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_dht.h
- * @brief cadet service; dealing with DHT requests and results
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMD (Gnunet Cadet Dht)
- */
-
-#ifndef GNUNET_SERVICE_CADET_DHT_H
-#define GNUNET_SERVICE_CADET_DHT_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-struct GMD_search_handle;
-
-
-/**
- * Callback called on each path found over the DHT.
- *
- * @param cls Closure.
- * @param path An unchecked, unoptimized path to the target node.
- *             After callback will no longer be valid!
- */
-typedef void (*GMD_search_callback) (void *cls,
-                                     const struct CadetPeerPath *path);
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize the DHT subsystem.
- *
- * @param c Configuration.
- */
-void
-GMD_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the DHT subsystem.
- */
-void
-GMD_shutdown (void);
-
-
-struct GMD_search_handle *
-GMD_search (const struct GNUNET_PeerIdentity *peer_id,
-            GMD_search_callback callback, void *cls);
-
-
-void
-GMD_search_stop (struct GMD_search_handle *h);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
-#endif
-/* end of gnunet-cadet-service_LOCAL.h */
\ No newline at end of file

Deleted: gnunet/src/mesh/gnunet-service-cadet_hello.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_hello.c        2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_hello.c        2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,198 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2014 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-#include "gnunet_peerinfo_service.h"
-
-#include "cadet_protocol.h"
-#include "cadet_path.h"
-
-#include "gnunet-service-cadet_hello.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
-
-
-/******************************************************************************/
-/********************************   STRUCTS  
**********************************/
-/******************************************************************************/
-
-
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-
-/**
- * Don't try to recover tunnels if shutting down.
- */
-extern int shutting_down;
-
-
-/**
- * Hello message of local peer.
- */
-const struct GNUNET_HELLO_Message *mine;
-
-/**
- * Handle to peerinfo service.
- */
-static struct GNUNET_PEERINFO_Handle *peerinfo;
-
-/**
- * Iterator context.
- */
-struct GNUNET_PEERINFO_NotifyContext* nc;
-
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-/**
- * Process each hello message received from peerinfo.
- *
- * @param cls Closure (unused).
- * @param peer Identity of the peer.
- * @param hello Hello of the peer.
- * @param err_msg Error message.
- */
-static void
-got_hello (void *cls, const struct GNUNET_PeerIdentity *id,
-           const struct GNUNET_HELLO_Message *hello,
-           const char *err_msg)
-{
-  struct CadetPeer *peer;
-
-  if (NULL == id || NULL == hello)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n",
-       GNUNET_i2s (id), GNUNET_HELLO_size (hello),
-       GNUNET_STRINGS_absolute_time_to_string 
(GNUNET_HELLO_get_last_expiration(hello)));
-  peer = GMP_get (id);
-  GMP_set_hello (peer, hello);
-
-  if (GMP_get_short_id (peer) == myid)
-  {
-    mine = GMP_get_hello (peer);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " updated mine to %p\n", mine);
-  }
-}
-
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize the hello subsystem.
- *
- * @param c Configuration.
- */
-void
-GMH_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-  GNUNET_assert (NULL == nc);
-  peerinfo = GNUNET_PEERINFO_connect (c);
-  nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL);
-}
-
-
-/**
- * Shut down the hello subsystem.
- */
-void
-GMH_shutdown ()
-{
-  if (NULL != nc)
-  {
-    GNUNET_PEERINFO_notify_cancel (nc);
-    nc = NULL;
-  }
-  if (NULL != peerinfo)
-  {
-    GNUNET_PEERINFO_disconnect (peerinfo);
-    peerinfo = NULL;
-  }
-}
-
-
-/**
- * Get own hello message.
- *
- * @return Own hello message.
- */
-const struct GNUNET_HELLO_Message *
-GMH_get_mine (void)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " mine is %p\n", mine);
-  return mine;
-}
-
-
-/**
- * Get another peer's hello message.
- *
- * @param id ID of the peer whose hello message is requested.
- *
- * @return Hello message, if any (NULL possible).
- */
-const struct GNUNET_HELLO_Message *
-GMH_get (const struct GNUNET_PeerIdentity *id)
-{
-  return GMP_get_hello (GMP_get (id));
-}
-
-
-/**
- * Convert a hello message to a string.
- *
- * @param h Hello message.
- */
-char *
-GMH_2s (const struct GNUNET_HELLO_Message *h)
-{
-  return "hello (TODO)";
-}
-
-

Deleted: gnunet/src/mesh/gnunet-service-cadet_hello.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_hello.h        2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_hello.h        2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,76 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2014 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_hello.h
- * @brief cadet service; dealing with hello messages
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMH (Gnunet Cadet Hello)
- */
-
-#ifndef GNUNET_SERVICE_CADET_HELLO_H
-#define GNUNET_SERVICE_CADET_HELLO_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_hello_lib.h"
-
-
-/**
- * Initialize the hello subsystem.
- *
- * @param c Configuration.
- */
-void
-GMH_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the hello subsystem.
- */
-void
-GMH_shutdown ();
-
-/**
- * Get own hello message.
- *
- * @return Own hello message.
- */
-const struct GNUNET_HELLO_Message *
-GMH_get_mine (void);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
-#endif
-/* end of gnunet-cadet-service_hello.h */

Deleted: gnunet/src/mesh/gnunet-service-cadet_local.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_local.c        2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_local.c        2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,1242 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-
-#include "cadet.h"
-#include "cadet_protocol.h" /* GNUNET_CADET_Data is shared */
-
-#include "gnunet-service-cadet_local.h"
-#include "gnunet-service-cadet_channel.h"
-
-/* INFO DEBUG */
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-loc",__VA_ARGS__)
-
-/******************************************************************************/
-/********************************   STRUCTS  
**********************************/
-/******************************************************************************/
-
-/**
- * Struct containing information about a client of the service
- *
- * TODO: add a list of 'waiting' ports
- */
-struct CadetClient
-{
-    /**
-     * Linked list next
-     */
-  struct CadetClient *next;
-
-    /**
-     * Linked list prev
-     */
-  struct CadetClient *prev;
-
-    /**
-     * Tunnels that belong to this client, indexed by local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
-
-    /**
-     * Tunnels this client has accepted, indexed by incoming local id
-     */
-  struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
-
-    /**
-     * Channel ID for the next incoming channel.
-     */
-  CADET_ChannelNumber next_chid;
-
-    /**
-     * Handle to communicate with the client
-     */
-  struct GNUNET_SERVER_Client *handle;
-
-    /**
-     * Ports that this client has declared interest in.
-     * Indexed by port, contains *Client.
-     */
-  struct GNUNET_CONTAINER_MultiHashMap32 *ports;
-
-    /**
-     * Whether the client is active or shutting down (don't send confirmations
-     * to a client that is shutting down.
-     */
-  int shutting_down;
-
-    /**
-     * ID of the client, mainly for debug messages
-     */
-  unsigned int id;
-};
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Handle to server lib.
- */
-static struct GNUNET_SERVER_Handle *server_handle;
-
-/**
- * DLL with all the clients, head.
- */
-static struct CadetClient *clients_head;
-
-/**
- * DLL with all the clients, tail.
- */
-static struct CadetClient *clients_tail;
-
-/**
- * Next ID to assign to a client.
- */
-unsigned int next_client_id;
-
-/**
- * All ports clients of this peer have opened.
- */
-static struct GNUNET_CONTAINER_MultiHashMap32 *ports;
-
-/**
- * Notification context, to send messages to local clients.
- */
-static struct GNUNET_SERVER_NotificationContext *nc;
-
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-/**
- * Remove client's ports from the global hashmap on disconnect.
- *
- * @param cls Closure (unused).
- * @param key Port.
- * @param value Client structure.
- *
- * @return GNUNET_OK, keep iterating.
- */
-static int
-client_release_ports (void *cls,
-                      uint32_t key,
-                      void *value)
-{
-  int res;
-
-  res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value);
-  if (GNUNET_YES != res)
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-                "Port %u by client %p was not registered.\n",
-                key, value);
-  }
-  return GNUNET_OK;
-}
-
-
-
-/******************************************************************************/
-/********************************  HANDLES  
***********************************/
-/******************************************************************************/
-
-
-/**
- * Handler for client connection.
- *
- * @param cls Closure (unused).
- * @param client Client handler.
- */
-static void
-handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  struct CadetClient *c;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "client connected: %p\n", client);
-  if (NULL == client)
-    return;
-  c = GNUNET_new (struct CadetClient);
-  c->handle = client;
-  c->id = next_client_id++; /* overflow not important: just for debug */
-  c->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-  GNUNET_SERVER_client_keep (client);
-  GNUNET_SERVER_client_set_user_context (client, c);
-  GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
-}
-
-
-/**
- * Iterator for deleting each channel whose client endpoint disconnected.
- *
- * @param cls Closure (client that has disconnected).
- * @param key The local channel id (used to access the hashmap).
- * @param value The value stored at the key (channel to destroy).
- *
- * @return GNUNET_OK, keep iterating.
- */
-static int
-channel_destroy_iterator (void *cls,
-                          uint32_t key,
-                          void *value)
-{
-  struct CadetChannel *ch = value;
-  struct CadetClient *c = cls;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-              " Channel %s destroy, due to client %s shutdown.\n",
-              GMCH_2s (ch), GML_2s (c));
-
-  GMCH_handle_local_destroy (ch, c, key < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV);
-  return GNUNET_OK;
-}
-
-/**
- * Handler for client disconnection
- *
- * @param cls closure
- * @param client identification of the client; NULL
- *        for the last call when the server is destroyed
- */
-static void
-handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  struct CadetClient *c;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
-  if (client == NULL)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
-    return;
-  }
-
-  c = GML_client_get (client);
-  if (NULL != c)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n",
-                c->id, c);
-    GNUNET_SERVER_client_drop (c->handle);
-    c->shutting_down = GNUNET_YES;
-    if (NULL != c->own_channels)
-    {
-      GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
-                                               &channel_destroy_iterator, c);
-      GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
-    }
-
-    if (NULL != c->incoming_channels)
-    {
-      GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
-                                               &channel_destroy_iterator, c);
-      GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
-    }
-
-    if (NULL != c->ports)
-    {
-      GNUNET_CONTAINER_multihashmap32_iterate (c->ports,
-                                               &client_release_ports, c);
-      GNUNET_CONTAINER_multihashmap32_destroy (c->ports);
-    }
-    GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
-    GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  client free (%p)\n", c);
-    GNUNET_free (c);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n");
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
-  return;
-}
-
-
-/**
- * Handler for new clients
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message, which includes messages the client wants
- */
-static void
-handle_new_client (void *cls, struct GNUNET_SERVER_Client *client,
-                   const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_ClientConnect *cc_msg;
-  struct CadetClient *c;
-  unsigned int size;
-  uint32_t *p;
-  unsigned int i;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
-
-  /* Check data sanity */
-  size = ntohs (message->size) - sizeof (struct GNUNET_CADET_ClientConnect);
-  cc_msg = (struct GNUNET_CADET_ClientConnect *) message;
-  if (0 != (size % sizeof (uint32_t)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  size /= sizeof (uint32_t);
-
-  /* Initialize new client structure */
-  c = GNUNET_SERVER_client_get_user_context (client, struct CadetClient);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  client id %u\n", c->id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  client has %u ports\n", size);
-  if (size > 0)
-  {
-    uint32_t u32;
-
-    p = (uint32_t *) &cc_msg[1];
-    c->ports = GNUNET_CONTAINER_multihashmap32_create (size);
-    for (i = 0; i < size; i++)
-    {
-      u32 = ntohl (p[i]);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "    port: %u\n", u32);
-
-      /* store in client's hashmap */
-      GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c,
-                                           
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-      /* store in global hashmap */
-      /* FIXME only allow one client to have the port open,
-       *       have a backup hashmap with waiting clients */
-      GNUNET_CONTAINER_multihashmap32_put (ports, u32, c,
-                                           
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    }
-  }
-
-  c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
-  c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
-  GNUNET_SERVER_notification_context_add (nc, client);
-  GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
-}
-
-
-/**
- * Handler for requests of new tunnels
- *
- * @param cls Closure.
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
-{
-  struct CadetClient *c;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message size sanity check */
-  if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GMCH_handle_local_create (c,
-                                (struct GNUNET_CADET_ChannelMessage *) 
message))
-  {
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for requests of deleting tunnels
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_ChannelMessage *msg;
-  struct CadetClient *c;
-  struct CadetChannel *ch;
-  CADET_ChannelNumber chid;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  /* Message sanity check */
-  if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  msg = (struct GNUNET_CADET_ChannelMessage *) message;
-
-  /* Retrieve tunnel */
-  chid = ntohl (msg->channel_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  for channel %X\n", chid);
-  ch = GML_channel_get (c, chid);
-  if (NULL == ch)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  channel %X not found\n", chid);
-    GNUNET_STATISTICS_update (stats,
-                              "# client destroy messages on unknown channel",
-                              1, GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  GMCH_handle_local_destroy (ch, c, chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  return;
-}
-
-
-/**
- * Handler for client traffic
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_data (void *cls, struct GNUNET_SERVER_Client *client,
-             const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalData *msg;
-  struct CadetClient *c;
-  struct CadetChannel *ch;
-  CADET_ChannelNumber chid;
-  size_t size;
-  int fwd;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client!\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  msg = (struct GNUNET_CADET_LocalData *) message;
-
-  /* Sanity check for message size */
-  size = ntohs (message->size) - sizeof (struct GNUNET_CADET_LocalData);
-  if (size < sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  /* Channel exists? */
-  chid = ntohl (msg->id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
-  fwd = chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-  ch = GML_channel_get (c, chid);
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              "# client data messages on unknown channel",
-                              1, GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GMCH_handle_local_data (ch, c,
-                              (struct GNUNET_MessageHeader *)&msg[1], fwd))
-  {
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-/**
- * Handler for client's ACKs for payload traffic.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
-            const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_CADET_LocalAck *msg;
-  struct CadetChannel *ch;
-  struct CadetClient *c;
-  CADET_ChannelNumber chid;
-  int fwd;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
-
-  msg = (struct GNUNET_CADET_LocalAck *) message;
-
-  /* Channel exists? */
-  chid = ntohl (msg->channel_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
-  ch = GML_channel_get (c, chid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "   -- ch %p\n", ch);
-  if (NULL == ch)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  for client %u.\n", c->id);
-    GNUNET_STATISTICS_update (stats,
-                              "# client ack messages on unknown channel",
-                              1, GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
-  /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
-  fwd = chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-
-  GMCH_handle_local_ack (ch, fwd);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  return;
-}
-
-
-
-/**
- * Iterator over all peers to send a monitoring client info about each peer.
- *
- * @param cls Closure ().
- * @param peer Peer ID (tunnel remote peer).
- * @param value Peer info.
- *
- * @return #GNUNET_YES, to keep iterating.
- */
-static int
-get_all_peers_iterator (void *cls,
-                        const struct GNUNET_PeerIdentity * peer,
-                        void *value)
-{
-  struct GNUNET_SERVER_Client *client = cls;
-  struct CadetPeer *p = value;
-  struct GNUNET_CADET_LocalInfoPeer msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
-  msg.destination = *peer;
-  msg.paths = htons (GMP_count_paths (p));
-  msg.tunnel = htons (NULL != GMP_get_tunnel (p));
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n",
-       GNUNET_i2s (peer));
-
-  GNUNET_SERVER_notification_context_unicast (nc, client,
-                                              &msg.header, GNUNET_NO);
-  return GNUNET_YES;
-}
-
-
-/**
- * Handler for client's INFO PEERS request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
-{
-  struct CadetClient *c;
-  struct GNUNET_MessageHeader reply;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received get peers request from client %u (%p)\n",
-       c->id, client);
-
-  GMP_iterate_all (get_all_peers_iterator, client);
-  reply.size = htons (sizeof (reply));
-  reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
-  GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Get peers request from client %u completed\n", c->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Iterator over all tunnels to send a monitoring client info about each 
tunnel.
- *
- * @param cls Closure ().
- * @param peer Peer ID (tunnel remote peer).
- * @param value Tunnel info.
- *
- * @return #GNUNET_YES, to keep iterating.
- */
-static int
-get_all_tunnels_iterator (void *cls,
-                          const struct GNUNET_PeerIdentity * peer,
-                          void *value)
-{
-  struct GNUNET_SERVER_Client *client = cls;
-  struct CadetTunnel3 *t = value;
-  struct GNUNET_CADET_LocalInfoTunnel msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
-  msg.destination = *peer;
-  msg.channels = htonl (GMT_count_channels (t));
-  msg.connections = htonl (GMT_count_connections (t));
-  msg.cstate = htons ((uint16_t) GMT_get_cstate (t));
-  msg.estate = htons ((uint16_t) GMT_get_estate (t));
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n",
-       GNUNET_i2s (peer));
-
-  GNUNET_SERVER_notification_context_unicast (nc, client,
-                                              &msg.header, GNUNET_NO);
-  return GNUNET_YES;
-}
-
-
-/**
- * Handler for client's INFO TUNNELS request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
-{
-  struct CadetClient *c;
-  struct GNUNET_MessageHeader reply;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received get tunnels request from client %u (%p)\n",
-       c->id, client);
-
-  GMT_iterate_all (get_all_tunnels_iterator, client);
-  reply.size = htons (sizeof (reply));
-  reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
-  GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Get tunnels request from client %u completed\n", c->id);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-static void
-iter_connection (void *cls, struct CadetConnection *c)
-{
-  struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
-  struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1];
-
-  h[msg->connections] = *(GMC_get_id (c));
-  msg->connections++;
-}
-
-static void
-iter_channel (void *cls, struct CadetChannel *ch)
-{
-  struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
-  struct GNUNET_HashCode *h = (struct GNUNET_HashCode *) &msg[1];
-  CADET_ChannelNumber *chn = (CADET_ChannelNumber *) &h[msg->connections];
-
-  chn[msg->channels] = GMCH_get_id (ch);
-  msg->channels++;
-}
-
-
-/**
- * Handler for client's SHOW_TUNNEL request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-void
-handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_CADET_LocalInfo *msg;
-  struct GNUNET_CADET_LocalInfoTunnel *resp;
-  struct CadetClient *c;
-  struct CadetTunnel3 *t;
-  unsigned int ch_n;
-  unsigned int c_n;
-  size_t size;
-
-  /* Sanity check for client registration */
-  if (NULL == (c = GML_client_get (client)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-
-  msg = (struct GNUNET_CADET_LocalInfo *) message;
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "Received tunnel info request from client %u for tunnel %s\n",
-       c->id, GNUNET_i2s_full(&msg->peer));
-
-  t = GMP_get_tunnel (GMP_get (&msg->peer));
-  if (NULL == t)
-  {
-    /* We don't know the tunnel */
-    struct GNUNET_CADET_LocalInfoTunnel warn;
-
-    LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n",
-         GNUNET_i2s_full(&msg->peer), sizeof (warn));
-    warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
-    warn.header.size = htons (sizeof (warn));
-    warn.destination = msg->peer;
-    warn.channels = htonl (0);
-    warn.connections = htonl (0);
-    warn.cstate = htons (0);
-    warn.estate = htons (0);
-
-    GNUNET_SERVER_notification_context_unicast (nc, client,
-                                                &warn.header,
-                                                GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  /* Initialize context */
-  ch_n = GMT_count_channels (t);
-  c_n = GMT_count_connections (t);
-
-  size = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
-  size += c_n * sizeof (struct GNUNET_CADET_Hash);
-  size += ch_n * sizeof (CADET_ChannelNumber);
-
-  resp = GNUNET_malloc (size);
-  resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
-  resp->header.size = htons (size);
-  GMT_iterate_connections (t, &iter_connection, resp);
-  GMT_iterate_channels (t, &iter_channel, resp);
-  /* Do not interleave with iterators, iter_channel needs conn in HBO */
-  resp->destination = msg->peer;
-  resp->connections = htonl (resp->connections);
-  resp->channels = htonl (resp->channels);
-  resp->cstate = htons (GMT_get_cstate (t));
-  resp->estate = htons (GMT_get_estate (t));
-  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                              &resp->header, GNUNET_NO);
-  GNUNET_free (resp);
-
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "Show tunnel request from client %u completed. %u conn, %u ch\n",
-       c->id, c_n, ch_n);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Functions to handle messages from clients
- */
-static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
-  {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT, 0},
-  {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE,
-   sizeof (struct GNUNET_CADET_ChannelMessage)},
-  {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
-   sizeof (struct GNUNET_CADET_ChannelMessage)},
-  {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
-  {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
-   sizeof (struct GNUNET_CADET_LocalAck)},
-  {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
-   sizeof (struct GNUNET_MessageHeader)},
-  {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
-   sizeof (struct GNUNET_MessageHeader)},
-  {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
-   sizeof (struct GNUNET_CADET_LocalInfo)},
-  {NULL, NULL, 0, 0}
-};
-
-
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize server subsystem.
- *
- * @param handle Server handle.
- */
-void
-GML_init (struct GNUNET_SERVER_Handle *handle)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-  server_handle = handle;
-  GNUNET_SERVER_suspend (server_handle);
-  ports = GNUNET_CONTAINER_multihashmap32_create (32);
-}
-
-
-/**
- * Install server (service) handlers and start listening to clients.
- */
-void
-GML_start (void)
-{
-  GNUNET_SERVER_add_handlers (server_handle, client_handlers);
-  GNUNET_SERVER_connect_notify (server_handle,  &handle_client_connect, NULL);
-  GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
-                                   NULL);
-  nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
-
-  clients_head = NULL;
-  clients_tail = NULL;
-  next_client_id = 0;
-  GNUNET_SERVER_resume (server_handle);
-}
-
-
-/**
- * Shutdown server.
- */
-void
-GML_shutdown (void)
-{
-  if (nc != NULL)
-  {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
-  }
-}
-
-
-/**
- * Get a channel from a client.
- *
- * @param c Client to check.
- * @param chid Channel ID, must be local (> 0x800...).
- *
- * @return non-NULL if channel exists in the clients lists
- */
-struct CadetChannel *
-GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid)
-{
-  struct GNUNET_CONTAINER_MultiHashMap32 *map;
-
-  if (0 == (chid & GNUNET_CADET_LOCAL_CHANNEL_ID_CLI))
-  {
-    GNUNET_break_op (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
-    return NULL;
-  }
-
-  if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-    map = c->incoming_channels;
-  else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
-    map = c->own_channels;
-  else
-  {
-    GNUNET_break (0);
-    map = NULL;
-  }
-  if (NULL == map)
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Client %s does no t have a valid map for CHID %X\n",
-         GML_2s (c), chid);
-    return NULL;
-  }
-  return GNUNET_CONTAINER_multihashmap32_get (map, chid);
-}
-
-
-/**
- * Add a channel to a client
- *
- * @param client Client.
- * @param chid Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_add (struct CadetClient *client,
-                 uint32_t chid,
-                 struct CadetChannel *ch)
-{
-  if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV)
-    GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
-    GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  else
-    GNUNET_break (0);
-}
-
-
-/**
- * Remove a channel from a client.
- *
- * @param client Client.
- * @param chid Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_remove (struct CadetClient *client,
-                    uint32_t chid,
-                    struct CadetChannel *ch)
-{
-  if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= chid)
-    GNUNET_break (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap32_remove 
(client->incoming_channels,
-                                                          chid, ch));
-  else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= chid)
-    GNUNET_break (GNUNET_YES ==
-                  GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
-                                                          chid, ch));
-  else
-    GNUNET_break (0);
-}
-
-
-/**
- * Get the tunnel's next free local channel ID.
- *
- * @param c Client.
- *
- * @return LID of a channel free to use.
- */
-CADET_ChannelNumber
-GML_get_next_chid (struct CadetClient *c)
-{
-  CADET_ChannelNumber chid;
-
-  while (NULL != GML_channel_get (c, c->next_chid))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid);
-    c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-  }
-  chid = c->next_chid;
-  c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV;
-
-  return chid;
-}
-
-
-/**
- * Check if client has registered with the service and has not disconnected
- *
- * @param client the client to check
- *
- * @return non-NULL if client exists in the global DLL
- */
-struct CadetClient *
-GML_client_get (struct GNUNET_SERVER_Client *client)
-{
-  return GNUNET_SERVER_client_get_user_context (client, struct CadetClient);
-}
-
-/**
- * Find a client that has opened a port
- *
- * @param port Port to check.
- *
- * @return non-NULL if a client has the port.
- */
-struct CadetClient *
-GML_client_get_by_port (uint32_t port)
-{
-  return GNUNET_CONTAINER_multihashmap32_get (ports, port);
-}
-
-
-/**
- * Deletes a channel from a client (either owner or destination).
- *
- * @param c Client whose tunnel to delete.
- * @param ch Channel which should be deleted.
- * @param id Channel ID.
- */
-void
-GML_client_delete_channel (struct CadetClient *c,
-                           struct CadetChannel *ch,
-                           CADET_ChannelNumber id)
-{
-  int res;
-
-  if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= id)
-  {
-    res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
-                                                  id, ch);
-    if (GNUNET_YES != res)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
-  }
-  else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= id)
-  {
-    res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
-                                                  id, ch);
-    if (GNUNET_YES != res)
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-}
-
-/**
- * Build a local ACK message and send it to a local client, if needed.
- *
- * If the client was already allowed to send data, do nothing.
- *
- * @param c Client to whom send the ACK.
- * @param id Channel ID to use
- */
-void
-GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id)
-{
-  struct GNUNET_CADET_LocalAck msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-              "send local %s ack on %X towards %p\n",
-              id < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c);
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
-  msg.channel_id = htonl (id);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              c->handle,
-                                              &msg.header,
-                                              GNUNET_NO);
-
-}
-
-
-
-/**
- * Notify the client that a new incoming channel was created.
- *
- * @param c Client to notify.
- * @param id Channel ID.
- * @param port Channel's destination port.
- * @param opt Options (bit array).
- * @param peer Origin peer.
- */
-void
-GML_send_channel_create (struct CadetClient *c,
-                         uint32_t id, uint32_t port, uint32_t opt,
-                         const struct GNUNET_PeerIdentity *peer)
-{
-  struct GNUNET_CADET_ChannelMessage msg;
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
-  msg.channel_id = htonl (id);
-  msg.port = htonl (port);
-  msg.opt = htonl (opt);
-  msg.peer = *peer;
-  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                              &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Build a local channel NACK message and send it to a local client.
- *
- * @param c Client to whom send the NACK.
- * @param id Channel ID to use
- */
-void
-GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id)
-{
-  struct GNUNET_CADET_LocalAck msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "send local nack on %X towards %p\n",
-       id, c);
-
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK);
-  msg.channel_id = htonl (id);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              c->handle,
-                                              &msg.header,
-                                              GNUNET_NO);
-
-}
-
-/**
- * Notify a client that a channel is no longer valid.
- *
- * @param c Client.
- * @param id ID of the channel that is destroyed.
- */
-void
-GML_send_channel_destroy (struct CadetClient *c, uint32_t id)
-{
-  struct GNUNET_CADET_ChannelMessage msg;
-
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (GNUNET_YES == c->shutting_down)
-    return;
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-  msg.channel_id = htonl (id);
-  msg.port = htonl (0);
-  memset (&msg.peer, 0, sizeof (msg.peer));
-  msg.opt = htonl (0);
-  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                              &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Modify the cadet message ID from global to local and send to client.
- *
- * @param c Client to send to.
- * @param msg Message to modify and send.
- * @param id Channel ID to use (c can be both owner and client).
- */
-void
-GML_send_data (struct CadetClient *c,
-               const struct GNUNET_CADET_Data *msg,
-               CADET_ChannelNumber id)
-{
-  struct GNUNET_CADET_LocalData *copy;
-  uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_Data);
-  char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)];
-
-  if (size < sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-  if (NULL == c)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  copy = (struct GNUNET_CADET_LocalData *) cbuf;
-  memcpy (&copy[1], &msg[1], size);
-  copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size);
-  copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
-  copy->id = htonl (id);
-  GNUNET_SERVER_notification_context_unicast (nc, c->handle,
-                                              &copy->header, GNUNET_NO);
-}
-
-
-/**
- * Get the static string to represent a client.
- *
- * @param c Client.
- *
- * @return Static string for the client.
- */
-const char *
-GML_2s (const struct CadetClient *c)
-{
-  static char buf[32];
-
-  sprintf (buf, "%u", c->id);
-  return buf;
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_local.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_local.h        2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_local.h        2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,226 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_local.h
- * @brief cadet service; dealing with local clients
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GML (Gnunet Cadet Local)
- */
-
-#ifndef GNUNET_SERVICE_CADET_LOCAL_H
-#define GNUNET_SERVICE_CADET_LOCAL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-/**
- * Struct containing information about a client of the service
- */
-struct CadetClient;
-
-#include "gnunet-service-cadet_channel.h"
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize server subsystem.
- *
- * @param handle Server handle.
- */
-void
-GML_init (struct GNUNET_SERVER_Handle *handle);
-
-/**
- * Install server (service) handlers and start listening to clients.
- */
-void
-GML_start (void);
-
-/**
- * Shutdown server.
- */
-void
-GML_shutdown (void);
-
-/**
- * Get a channel from a client.
- *
- * @param c Client to check.
- * @param chid Channel ID, must be local (> 0x800...).
- *
- * @return non-NULL if channel exists in the clients lists
- */
-struct CadetChannel *
-GML_channel_get (struct CadetClient *c, uint32_t chid);
-
-/**
- * Add a channel to a client
- *
- * @param client Client.
- * @param chid Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_add (struct CadetClient *client,
-                 uint32_t chid,
-                 struct CadetChannel *ch);
-
-/**
- * Remove a channel from a client
- *
- * @param client Client.
- * @param chid Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_remove (struct CadetClient *client,
-                    uint32_t chid,
-                    struct CadetChannel *ch);
-
-/**
- * Get the tunnel's next free local channel ID.
- *
- * @param c Client.
- *
- * @return LID of a channel free to use.
- */
-CADET_ChannelNumber
-GML_get_next_chid (struct CadetClient *c);
-
-/**
- * Check if client has registered with the service and has not disconnected
- *
- * @param client the client to check
- *
- * @return non-NULL if client exists in the global DLL
- */
-struct CadetClient *
-GML_client_get (struct GNUNET_SERVER_Client *client);
-
-/**
- * Find a client that has opened a port
- *
- * @param port Port to check.
- *
- * @return non-NULL if a client has the port.
- */
-struct CadetClient *
-GML_client_get_by_port (uint32_t port);
-
-/**
- * Deletes a tunnel from a client (either owner or destination).
- *
- * @param c Client whose tunnel to delete.
- * @param ch Channel which should be deleted.
- * @param id Channel ID.
- */
-void
-GML_client_delete_channel (struct CadetClient *c,
-                           struct CadetChannel *ch,
-                           CADET_ChannelNumber id);
-
-/**
- * Build a local ACK message and send it to a local client, if needed.
- *
- * If the client was already allowed to send data, do nothing.
- *
- * @param c Client to whom send the ACK.
- * @param id Channel ID to use
- */
-void
-GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id);
-
-/**
- * Notify the appropriate client that a new incoming channel was created.
- *
- * @param c Client to notify.
- * @param id Channel ID.
- * @param port Channel's destination port.
- * @param opt Options (bit array).
- * @param peer Origin peer.
- */
-void
-GML_send_channel_create (struct CadetClient *c,
-                         uint32_t id, uint32_t port, uint32_t opt,
-                         const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Build a local channel NACK message and send it to a local client.
- *
- * @param c Client to whom send the NACK.
- * @param id Channel ID to use
- */
-void
-GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id);
-
-/**
- * Notify a client that a channel is no longer valid.
- *
- * @param c Client.
- * @param id ID of the channel that is destroyed.
- */
-void
-GML_send_channel_destroy (struct CadetClient *c, uint32_t id);
-
-/**
- * Modify the cadet message ID from global to local and send to client.
- *
- * @param c Client to send to.
- * @param msg Message to modify and send.
- * @param id Channel ID to use (c can be both owner and client).
- */
-void
-GML_send_data (struct CadetClient *c,
-               const struct GNUNET_CADET_Data *msg,
-               CADET_ChannelNumber id);
-
-/**
- * Get the static string to represent a client.
- *
- * @param c Client.
- *
- * @return Static string for the client.
- */
-const char *
-GML_2s (const struct CadetClient *c);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
-#endif
-/* end of gnunet-cadet-service_LOCAL.h */

Deleted: gnunet/src/mesh/gnunet-service-cadet_peer.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_peer.c 2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/gnunet-service-cadet_peer.c 2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,2219 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_transport_service.h"
-#include "gnunet_core_service.h"
-#include "gnunet_statistics_service.h"
-
-#include "cadet_protocol.h"
-
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "cadet_path.h"
-
-#define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__)
-
-/******************************************************************************/
-/********************************   STRUCTS  
**********************************/
-/******************************************************************************/
-
-/**
- * Struct containing info about a queued transmission to this peer
- */
-struct CadetPeerQueue
-{
-    /**
-      * DLL next
-      */
-  struct CadetPeerQueue *next;
-
-    /**
-      * DLL previous
-      */
-  struct CadetPeerQueue *prev;
-
-    /**
-     * Peer this transmission is directed to.
-     */
-  struct CadetPeer *peer;
-
-    /**
-     * Connection this message belongs to.
-     */
-  struct CadetConnection *c;
-
-    /**
-     * Is FWD in c?
-     */
-  int fwd;
-
-    /**
-     * Pointer to info stucture used as cls.
-     */
-  void *cls;
-
-  /**
-   * Type of message
-   */
-  uint16_t type;
-
-  /**
-   * Type of message
-   */
-  uint16_t payload_type;
-
-  /**
-   * Type of message
-   */
-  uint32_t payload_id;
-
-  /**
-     * Size of the message
-     */
-  size_t size;
-
-    /**
-     * Set when this message starts waiting for CORE.
-     */
-  struct GNUNET_TIME_Absolute start_waiting;
-
-    /**
-     * Function to call on sending.
-     */
-  GMP_sent callback;
-
-    /**
-     * Closure for callback.
-     */
-  void *callback_cls;
-};
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct CadetPeer
-{
-    /**
-     * 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 CadetPeerPath *path_head;
-
-    /**
-     * Paths to reach the peer, ordered by ascending hop count
-     */
-  struct CadetPeerPath *path_tail;
-
-    /**
-     * Handle to stop the DHT search for paths to this peer
-     */
-  struct GMD_search_handle *search_h;
-
-    /**
-     * Tunnel to this peer, if any.
-     */
-  struct CadetTunnel3 *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 CadetPeerQueue *queue_head;
-
-  /**
-   * Transmission queue to core DLL tail
-   */
-  struct CadetPeerQueue *queue_tail;
-
-  /**
-   * How many messages are in the queue to this peer.
-   */
-  unsigned int queue_n;
-
-  /**
-   * Hello message.
-   */
-  struct GNUNET_HELLO_Message* hello;
-};
-
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Local peer own ID (short)
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Peers known, indexed by PeerIdentity (CadetPeer).
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *peers;
-
-/**
- * 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;
-
-/**
- * Handle to communicate with core.
- */
-static struct GNUNET_CORE_Handle *core_handle;
-
-/**
- * Handle to try to start new connections.
- */
-static struct GNUNET_TRANSPORT_Handle *transport_handle;
-
-
-/******************************************************************************/
-/*****************************     DEBUG      
*********************************/
-/******************************************************************************/
-
-static void
-queue_debug (struct CadetPeer *peer)
-{
-  struct CadetPeerQueue *q;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ Messages queued towards %s\n", GMP_2s 
(peer));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ  core tmt rdy: %p\n", 
peer->core_transmit);
-
-  for (q = peer->queue_head; NULL != q; q = q->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ  - %s %s on %s\n",
-         GM_m2s (q->type), GM_f2s (q->fwd), GMC_2s (q->c));
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ End queued towards %s\n", GMP_2s (peer));
-}
-
-
-/******************************************************************************/
-/*****************************  CORE HELPERS  
*********************************/
-/******************************************************************************/
-
-
-/**
- * Iterator to notify all connections of a broken link. Mark connections
- * to destroy after all traffic has been sent.
- *
- * @param cls Closure (peer disconnected).
- * @param key Current key code (peer id).
- * @param value Value in the hash map (connection).
- *
- * @return #GNUNET_YES to continue to iterate.
- */
-static int
-notify_broken (void *cls,
-               const struct GNUNET_HashCode *key,
-               void *value)
-{
-  struct CadetPeer *peer = cls;
-  struct CadetConnection *c = value;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  notifying %s due to %s\n",
-       GMC_2s (c), GMP_2s (peer));
-  GMC_notify_broken (c, peer);
-
-  return GNUNET_YES;
-}
-
-
-/**
- * Remove the direct path to the peer.
- *
- * @param peer Peer to remove the direct path from.
- *
- */
-static struct CadetPeerPath *
-pop_direct_path (struct CadetPeer *peer)
-{
-  struct CadetPeerPath *iter;
-
-  for (iter = peer->path_head; NULL != iter; iter = iter->next)
-  {
-    if (2 <= iter->length)
-    {
-      GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter);
-      return iter;
-    }
-  }
-  return NULL;
-}
-
-
-/******************************************************************************/
-/***************************** CORE CALLBACKS 
*********************************/
-/******************************************************************************/
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct CadetPeer *mp;
-  struct CadetPeerPath *path;
-  char own_id[16];
-
-  strncpy (own_id, GNUNET_i2s (&my_full_id), 15);
-  mp = GMP_get (peer);
-  if (myid == mp->id)
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s (self)\n", own_id);
-    path = path_new (1);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s <= %s\n",
-         own_id, GNUNET_i2s (peer));
-    path = path_new (2);
-    path->peers[1] = mp->id;
-    GNUNET_PEER_change_rc (mp->id, 1);
-    GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
-  }
-  path->peers[0] = myid;
-  GNUNET_PEER_change_rc (myid, 1);
-  GMP_add_path (mp, path, GNUNET_YES);
-
-  mp->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
-
-  if (NULL != GMP_get_tunnel (mp) &&
-      0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer))
-  {
-    GMP_connect (mp);
-  }
-
-  return;
-}
-
-
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- */
-static void
-core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
-{
-  struct CadetPeer *p;
-  struct CadetPeerPath *direct_path;
-  char own_id[16];
-
-  strncpy (own_id, GNUNET_i2s (&my_full_id), 15);
-  p = GNUNET_CONTAINER_multipeermap_get (peers, peer);
-  if (NULL == p)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (myid == p->id)
-    LOG (GNUNET_ERROR_TYPE_INFO, "DISCONNECTED %s (self)\n", own_id);
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "DISCONNECTED %s <= %s\n",
-         own_id, GNUNET_i2s (peer));
-  direct_path = pop_direct_path (p);
-  GNUNET_CONTAINER_multihashmap_iterate (p->connections, &notify_broken, p);
-  GNUNET_CONTAINER_multihashmap_destroy (p->connections);
-  p->connections = NULL;
-  if (NULL != p->core_transmit)
-    {
-      GNUNET_CORE_notify_transmit_ready_cancel (p->core_transmit);
-      p->core_transmit = NULL;
-    }
-  GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
-
-  path_destroy (direct_path);
-  return;
-}
-
-
-/**
- * Functions to handle messages from core
- */
-static struct GNUNET_CORE_MessageHandler core_handlers[] = {
-  {&GMC_handle_create, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0},
-  {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK,
-    sizeof (struct GNUNET_CADET_ConnectionACK)},
-  {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
-    sizeof (struct GNUNET_CADET_ConnectionBroken)},
-  {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
-    sizeof (struct GNUNET_CADET_ConnectionDestroy)},
-  {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_CADET_ACK,
-    sizeof (struct GNUNET_CADET_ACK)},
-  {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_CADET_POLL,
-    sizeof (struct GNUNET_CADET_Poll)},
-  {&GMC_handle_encrypted, GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0},
-  {&GMC_handle_kx, GNUNET_MESSAGE_TYPE_CADET_KX, 0},
-  {NULL, 0, 0}
-};
-
-
-/**
- * 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;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
-  if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
-    LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity));
-    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 CADET 
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();
-  }
-  GML_start ();
-  return;
-}
-
-
-/**
-  * Core callback to write a pre-constructed data packet to core buffer
-  *
-  * @param cls Closure (CadetTransmissionDescriptor 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 CadetConnection *c, size_t size, void *buf)
-{
-  struct GNUNET_CADET_ConnectionCreate *msg;
-  struct GNUNET_PeerIdentity *peer_ptr;
-  const struct CadetPeerPath *p = GMC_get_path (c);
-  size_t size_needed;
-  int i;
-
-  if (NULL == p)
-    return 0;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
-  size_needed =
-      sizeof (struct GNUNET_CADET_ConnectionCreate) +
-      p->length * sizeof (struct GNUNET_PeerIdentity);
-
-  if (size < size_needed || NULL == buf)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg = (struct GNUNET_CADET_ConnectionCreate *) buf;
-  msg->header.size = htons (size_needed);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
-  msg->cid = *GMC_get_id (c);
-
-  peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
-  for (i = 0; i < p->length; i++)
-  {
-    GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
-  }
-
-  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 CadetConnection *c, size_t size, void *buf)
-{
-  struct GNUNET_CADET_ConnectionACK *msg = buf;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
-  if (sizeof (struct GNUNET_CADET_ConnectionACK) > size)
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionACK));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK);
-  msg->cid = *GMC_get_id (c);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
-  return sizeof (struct GNUNET_CADET_ConnectionACK);
-}
-
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-
-/**
- * Get priority for a queued message.
- *
- * @param q Queued message
- *
- * @return CORE priority to use.
- */
-static enum GNUNET_CORE_Priority
-get_priority (struct CadetPeerQueue *q)
-{
-  enum GNUNET_CORE_Priority low;
-  enum GNUNET_CORE_Priority high;
-
-  if (NULL == q)
-  {
-    GNUNET_break (0);
-    return GNUNET_CORE_PRIO_BACKGROUND;
-  }
-
-  /* Relayed traffic has lower priority, our own traffic has higher */
-  if (NULL == q->c || GNUNET_NO == GMC_is_origin (q->c, q->fwd))
-  {
-    low = GNUNET_CORE_PRIO_BEST_EFFORT;
-    high = GNUNET_CORE_PRIO_URGENT;
-  }
-  else
-  {
-    low = GNUNET_CORE_PRIO_URGENT;
-    high = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
-  }
-
-  /* Bulky payload has lower priority, control traffic has higher. */
-  if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == q->type)
-    return low;
-  else
-    return high;
-}
-
-
-/**
- * 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 CadetPeer *p = value;
-  struct CadetTunnel3 *t = p->tunnel;
-
-  if (NULL != t)
-    GMT_destroy (t);
-  return GNUNET_YES;
-}
-
-
-/**
- * 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 CadetPeer *peer)
-{
-  struct GNUNET_PeerIdentity id;
-  struct CadetPeerPath *p;
-  struct CadetPeerPath *nextp;
-
-  GNUNET_PEER_resolve (peer->id, &id);
-  GNUNET_PEER_change_rc (peer->id, -1);
-
-  LOG (GNUNET_ERROR_TYPE_WARNING, "destroying peer %s\n", GNUNET_i2s (&id));
-
-  if (GNUNET_YES !=
-    GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING, " not in peermap!!\n");
-  }
-  if (NULL != peer->search_h)
-  {
-    GMD_search_stop (peer->search_h);
-  }
-  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;
-  }
-  GMT_destroy_empty (peer->tunnel);
-  GNUNET_free (peer);
-  return GNUNET_OK;
-}
-
-
-/**
- * Returns if peer is used (has a tunnel or is neighbor).
- *
- * @param peer Peer to check.
- *
- * @return #GNUNET_YES if peer is in use.
- */
-static int
-peer_is_used (struct CadetPeer *peer)
-{
-  struct CadetPeerPath *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 CadetPeer *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 CadetPeer *p = value;
-  struct GNUNET_TIME_Absolute *abs = cls;
-
-  LOG (GNUNET_ERROR_TYPE_WARNING,
-       "peer %s timeout\n", GNUNET_i2s (key));
-
-  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);
-}
-
-
-/**
- * Choose the best (yet unused) 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 CadetPeerPath *
-peer_get_best_path (const struct CadetPeer *peer)
-{
-  struct CadetPeerPath *best_p;
-  struct CadetPeerPath *p;
-  unsigned int best_cost;
-  unsigned int cost;
-
-  best_cost = UINT_MAX;
-  best_p = NULL;
-  for (p = peer->path_head; NULL != p; p = p->next)
-  {
-    if (GNUNET_NO == path_is_valid (p))
-      continue; /* Don't use invalid paths. */
-    if (GNUNET_YES == GMT_is_path_used (peer->tunnel, p))
-      continue; /* If path is already in use, skip it. */
-
-    if ((cost = GMT_get_path_cost (peer->tunnel, p)) < best_cost)
-    {
-      best_cost = cost;
-      best_p = p;
-    }
-  }
-  return best_p;
-}
-
-
-/**
- * Is this queue element sendable?
- *
- * - All management traffic is always sendable.
- * - For payload traffic, check the connection flow control.
- *
- * @param q Queue element to inspect.
- *
- * @return #GNUNET_YES if it is sendable, #GNUNET_NO otherwise.
- */
-static int
-queue_is_sendable (struct CadetPeerQueue *q)
-{
-  /* Is PID-independent? */
-  switch (q->type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
-      return GNUNET_YES;
-
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-      break;
-
-    default:
-      GNUNET_break (0);
-  }
-
-  return GMC_is_sendable (q->c, q->fwd);
-}
-
-
-/**
- * Get first sendable message.
- *
- * @param peer The destination peer.
- *
- * @return First transmittable message, if any. Otherwise, NULL.
- */
-static struct CadetPeerQueue *
-peer_get_first_message (const struct CadetPeer *peer)
-{
-  struct CadetPeerQueue *q;
-
-  for (q = peer->queue_head; NULL != q; q = q->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking %p towards %s\n", q, GMC_2s 
(q->c));
-    if (queue_is_sendable (q))
-      return q;
-  }
-
-  return NULL;
-}
-
-
-/**
- * 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 path
- */
-static void
-search_handler (void *cls, const struct CadetPeerPath *path)
-{
-  struct CadetPeer *peer = cls;
-  unsigned int connection_count;
-
-  GMP_add_path_to_all (path, GNUNET_NO);
-
-  /* Count connections */
-  connection_count = GMT_count_connections (peer->tunnel);
-
-  /* If we already have 3 (or more (?!)) connections, it's enough */
-  if (3 <= connection_count)
-    return;
-
-  if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
-    GMP_connect (peer);
-  }
-  return;
-}
-
-
-
-/**
- * Core callback to write a queued packet to core buffer
- *
- * @param cls Closure (peer info).
- * @param size Number of bytes available in buf.
- * @param buf Where the to write the message.
- *
- * @return number of bytes written to buf
- */
-static size_t
-queue_send (void *cls, size_t size, void *buf)
-{
-  struct CadetPeer *peer = cls;
-  struct CadetConnection *c;
-  struct CadetPeerQueue *queue;
-  const struct GNUNET_PeerIdentity *dst_id;
-  size_t data_size;
-  uint32_t pid;
-
-  pid = 0;
-  peer->core_transmit = NULL;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue send towards %s (max %u)\n",
-       GMP_2s (peer), size);
-
-  if (NULL == buf || 0 == size)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Buffer size 0.\n");
-    return 0;
-  }
-
-  /* Initialize */
-  queue = peer_get_first_message (peer);
-  if (NULL == queue)
-  {
-    GNUNET_assert (0); /* Core tmt_rdy should've been canceled */
-    return 0;
-  }
-  c = queue->c;
-
-  dst_id = GNUNET_PEER_resolve2 (peer->id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s %s\n",
-       GMC_2s (c), GM_f2s(queue->fwd));
-  /* Check if buffer size is enough for the message */
-  if (queue->size > size)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "not enough room (%u vs %u), reissue\n",
-         queue->size, size);
-    peer->core_transmit =
-      GNUNET_CORE_notify_transmit_ready (core_handle,
-                                         GNUNET_NO, get_priority (queue),
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         dst_id,
-                                         queue->size,
-                                         &queue_send,
-                                         peer);
-    return 0;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  size %u ok\n", queue->size);
-
-  /* Fill buf */
-  switch (queue->type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-      pid = GMC_get_pid (queue->c, queue->fwd);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  payload ID %u\n", pid);
-      data_size = send_core_data_raw (queue->cls, size, buf);
-      ((struct GNUNET_CADET_Encrypted *) buf)->pid = htonl (pid);
-      break;
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
-    case GNUNET_MESSAGE_TYPE_CADET_KX:
-    case GNUNET_MESSAGE_TYPE_CADET_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_POLL:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  raw %s\n", GM_m2s (queue->type));
-      data_size = send_core_data_raw (queue->cls, size, buf);
-      break;
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  path create\n");
-      if (GMC_is_origin (c, GNUNET_YES))
-        data_size = send_core_connection_create (queue->c, size, buf);
-      else
-        data_size = send_core_data_raw (queue->cls, size, buf);
-      break;
-    case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  path ack\n");
-      if (GMC_is_origin (c, GNUNET_NO) ||
-          GMC_is_origin (c, GNUNET_YES))
-        data_size = send_core_connection_ack (queue->c, size, buf);
-      else
-        data_size = send_core_data_raw (queue->cls, size, buf);
-      break;
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-      /* This should be encapsulted */
-      GNUNET_break (0);
-      data_size = 0;
-      break;
-    default:
-      GNUNET_break (0);
-      LOG (GNUNET_ERROR_TYPE_WARNING, "  type unknown: %u\n", queue->type);
-      data_size = 0;
-  }
-
-  if (0 < drop_percent &&
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < 
drop_percent)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s on connection %s\n",
-         GM_m2s (queue->type), GMC_2s (c));
-    data_size = 0;
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-         "snd %s (%s %u) on connection %s (%p) %s (size %u)\n",
-         GM_m2s (queue->type), GM_m2s (queue->payload_type),
-         queue->payload_type, GMC_2s (c), c, GM_f2s (queue->fwd), data_size);
-  }
-
-  /* Free queue, but cls was freed by send_core_* */
-  GMP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid);
-
-  /* If more data in queue, send next */
-  queue = peer_get_first_message (peer);
-  if (NULL != queue)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  more data!\n");
-    if (NULL == peer->core_transmit)
-    {
-      peer->core_transmit =
-          GNUNET_CORE_notify_transmit_ready (core_handle,
-                                             GNUNET_NO, get_priority (queue),
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             dst_id,
-                                             queue->size,
-                                             &queue_send,
-                                             peer);
-      queue->start_waiting = GNUNET_TIME_absolute_get ();
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-                  "*   tmt rdy called somewhere else\n");
-    }
-//     GMC_start_poll (); FIXME needed?
-  }
-  else
-  {
-//     GMC_stop_poll(); FIXME needed?
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  return %d\n", data_size);
-  queue_debug (peer);
-  return data_size;
-}
-
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- * @param sent Was it really sent? (Could have been canceled)
- * @param pid PID, if relevant (was sent and was a payload message).
- */
-void
-GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
-                   int sent, uint32_t pid)
-{
-  struct CadetPeer *peer;
-
-  peer = queue->peer;
-
-  if (GNUNET_YES == clear_cls)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy type %s\n",
-         GM_m2s (queue->type));
-    switch (queue->type)
-    {
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
-        LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
-        /* fall through */
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
-      case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
-      case GNUNET_MESSAGE_TYPE_CADET_KX:
-      case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-      case GNUNET_MESSAGE_TYPE_CADET_ACK:
-      case GNUNET_MESSAGE_TYPE_CADET_POLL:
-        GNUNET_free_non_null (queue->cls);
-        break;
-
-      default:
-        GNUNET_break (0);
-        LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n",
-             GM_m2s (queue->type));
-    }
-  }
-  GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
-
-  if (queue->type != GNUNET_MESSAGE_TYPE_CADET_ACK &&
-      queue->type != GNUNET_MESSAGE_TYPE_CADET_POLL)
-  {
-    peer->queue_n--;
-  }
-
-  if (NULL != queue->callback)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n");
-    queue->callback (queue->callback_cls,
-                     queue->c, sent, queue->type, pid,
-                     queue->fwd, queue->size,
-                     GNUNET_TIME_absolute_get_duration (queue->start_waiting));
-  }
-
-  if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit)
-  {
-    GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
-    peer->core_transmit = NULL;
-  }
-
-  GNUNET_free (queue);
-}
-
-
-/**
- * @brief Queue and pass message to core when possible.
- *
- * @param peer Peer towards which to queue the message.
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- *            build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @param c Connection this message belongs to (can be NULL).
- * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
- * @param cont Continuation to be called once CORE has taken the message.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it is sent. Once cont is called
- *         message has been sent and therefore the handle is no longer valid.
- */
-struct CadetPeerQueue *
-GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
-               uint16_t payload_type, uint32_t payload_id, size_t size,
-               struct CadetConnection *c, int fwd,
-               GMP_sent cont, void *cont_cls)
-{
-  struct CadetPeerQueue *queue;
-  int priority;
-  int call_core;
-
-  LOG (GNUNET_ERROR_TYPE_INFO,
-       "que %s (%s %u) on connection %s (%p) %s towards %s (size %u)\n",
-       GM_m2s (type), GM_m2s (payload_type), payload_id,
-       GMC_2s (c), c, GM_f2s (fwd), GMP_2s (peer), size);
-
-  if (NULL == peer->connections)
-  {
-    /* We are not connected to this peer, ignore request. */
-    LOG (GNUNET_ERROR_TYPE_WARNING, "%s not a neighbor\n", GMP_2s (peer));
-    GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
-                              GNUNET_NO);
-    return NULL;
-  }
-
-  priority = 0;
-
-  if (GNUNET_MESSAGE_TYPE_CADET_POLL == type ||
-      GNUNET_MESSAGE_TYPE_CADET_ACK == type)
-  {
-    priority = 100;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
-
-  call_core = NULL == c ? GNUNET_YES : GMC_is_sendable (c, fwd);
-  queue = GNUNET_new (struct CadetPeerQueue);
-  queue->cls = cls;
-  queue->type = type;
-  queue->payload_type = payload_type;
-  queue->payload_id = payload_id;
-  queue->size = size;
-  queue->peer = peer;
-  queue->c = c;
-  queue->fwd = fwd;
-  queue->callback = cont;
-  queue->callback_cls = cont_cls;
-  if (100 > priority)
-  {
-    GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, 
queue);
-    peer->queue_n++;
-  }
-  else
-  {
-    GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
-    call_core = GNUNET_YES;
-  }
-
-  if (NULL == peer->core_transmit && GNUNET_YES == call_core)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "calling core tmt rdy towards %s for %u bytes\n",
-         GMP_2s (peer), size);
-    peer->core_transmit =
-        GNUNET_CORE_notify_transmit_ready (core_handle,
-                                           GNUNET_NO, get_priority (queue),
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_PEER_resolve2 (peer->id),
-                                           size,
-                                           &queue_send,
-                                           peer);
-    queue->start_waiting = GNUNET_TIME_absolute_get ();
-  }
-  else if (GNUNET_NO == call_core)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s not needed\n",
-         GMP_2s (peer));
-
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s already called\n",
-         GMP_2s (peer));
-
-  }
-  queue_debug (peer);
-  return queue;
-}
-
-
-/**
- * Cancel all queued messages to a peer that belong to a certain connection.
- *
- * @param peer Peer towards whom to cancel.
- * @param c Connection whose queued messages to cancel. Might be destroyed by
- *          the sent continuation call.
- */
-void
-GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
-{
-  struct CadetPeerQueue *q;
-  struct CadetPeerQueue *next;
-  struct CadetPeerQueue *prev;
-
-  for (q = peer->queue_head; NULL != q; q = next)
-  {
-    prev = q->prev;
-    if (q->c == c)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GM_m2s (q->type));
-      if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY != q->type)
-      {
-        q->c = NULL;
-      }
-      else
-      {
-        GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
-      }
-
-      /* Get next from prev, q->next might be already freed:
-       * queue destroy -> callback -> GMC_destroy -> cancel_queues -> here
-       */
-      if (NULL == prev)
-        next = peer->queue_head;
-      else
-        next = prev->next;
-    }
-    else
-    {
-      next = q->next;
-    }
-  }
-  if (NULL == peer->queue_head)
-  {
-    if (NULL != peer->core_transmit)
-    {
-      GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
-      peer->core_transmit = NULL;
-    }
-  }
-}
-
-
-/**
- * Get the first transmittable message for a connection.
- *
- * @param peer Neighboring peer.
- * @param c Connection.
- *
- * @return First transmittable message.
- */
-static struct CadetPeerQueue *
-connection_get_first_message (struct CadetPeer *peer, struct CadetConnection 
*c)
-{
-  struct CadetPeerQueue *q;
-
-  for (q = peer->queue_head; NULL != q; q = q->next)
-  {
-    if (q->c != c)
-      continue;
-    if (queue_is_sendable (q))
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  sendable!!\n");
-      return q;
-    }
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  not sendable\n");
-  }
-
-  return NULL;
-}
-
-
-/**
- * Get the first message for a connection and unqueue it.
- *
- * @param peer Neighboring peer.
- * @param c Connection.
- *
- * @return First message for this connection.
- */
-struct GNUNET_MessageHeader *
-GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c)
-{
-  struct CadetPeerQueue *q;
-  struct CadetPeerQueue *next;
-  struct GNUNET_MessageHeader *msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on %s\n", GMC_2s (c));
-  for (q = peer->queue_head; NULL != q; q = next)
-  {
-    next = q->next;
-    if (q->c != c)
-      continue;
-    switch (q->type)
-    {
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
-      case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
-      case GNUNET_MESSAGE_TYPE_CADET_ACK:
-      case GNUNET_MESSAGE_TYPE_CADET_POLL:
-        GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
-        continue;
-
-      case GNUNET_MESSAGE_TYPE_CADET_KX:
-      case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
-        msg = (struct GNUNET_MessageHeader *) q->cls;
-        GMP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0);
-        return msg;
-
-      default:
-        GNUNET_break (0);
-    }
-  }
-
-  return NULL;
-}
-
-
-void
-GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c)
-{
-  struct CadetPeerQueue *q;
-  size_t size;
-
-  if (NULL != peer->core_transmit)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  already unlocked!\n");
-    return; /* Already unlocked */
-  }
-
-  q = connection_get_first_message (peer, c);
-  if (NULL == q)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  queue empty!\n");
-    return; /* Nothing to transmit */
-  }
-
-  size = q->size;
-  peer->core_transmit =
-      GNUNET_CORE_notify_transmit_ready (core_handle,
-                                         GNUNET_NO, get_priority (q),
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         GNUNET_PEER_resolve2 (peer->id),
-                                         size,
-                                         &queue_send,
-                                         peer);
-}
-
-
-/**
- * Initialize the peer subsystem.
- *
- * @param c Configuration.
- */
-void
-GMP_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-  peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS",
-                                             &max_peers))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "CADET", "MAX_PEERS", "USING DEFAULT");
-    max_peers = 1000;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT",
-                                             &drop_percent))
-  {
-    drop_percent = 0;
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
-  }
-
-  core_handle = GNUNET_CORE_connect (c, /* Main configuration */
-                                     NULL,      /* Closure passed to CADET 
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 (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_yesno (c, "CADET", "DISABLE_TRY_CONNECT"))
-  {
-    transport_handle = GNUNET_TRANSPORT_connect (c, &my_full_id, NULL, /* cls 
*/
-                                                 /* Notify callbacks */
-                                                 NULL, NULL, NULL);
-  }
-  else
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, "*  DISABLE TRYING CONNECT in config  
*\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, "*  Use this only for test purposes.  
*\n");
-    LOG (GNUNET_ERROR_TYPE_WARNING, 
"**************************************\n");
-    transport_handle = NULL;
-  }
-
-
-
-  if (NULL == core_handle)
-  {
-    GNUNET_break (0);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-}
-
-/**
- * Shut down the peer subsystem.
- */
-void
-GMP_shutdown (void)
-{
-  GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
-
-  if (core_handle != NULL)
-  {
-    GNUNET_CORE_disconnect (core_handle);
-    core_handle = NULL;
-  }
-  if (transport_handle != NULL)
-  {
-    GNUNET_TRANSPORT_disconnect (transport_handle);
-    transport_handle = NULL;
-  }
-  GNUNET_PEER_change_rc (myid, -1);
-}
-
-/**
- * Retrieve the CadetPeer stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer_id Full identity of the peer.
- *
- * @return Existing or newly created peer structure.
- */
-struct CadetPeer *
-GMP_get (const struct GNUNET_PeerIdentity *peer_id)
-{
-  struct CadetPeer *peer;
-
-  peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
-  if (NULL == peer)
-  {
-    peer = GNUNET_new (struct CadetPeer);
-    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 CadetPeer 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 structure.
- */
-struct CadetPeer *
-GMP_get_short (const GNUNET_PEER_Id peer)
-{
-  return GMP_get (GNUNET_PEER_resolve2 (peer));
-}
-
-
-/**
- * Try to connect to a peer on transport level.
- *
- * @param cls Closure (peer).
- * @param tc TaskContext.
- */
-static void
-try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetPeer *peer = cls;
-
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-    return;
-
-  GNUNET_TRANSPORT_try_connect (transport_handle,
-                                GNUNET_PEER_resolve2 (peer->id), NULL, NULL);
-}
-
-
-/**
- * Try to establish a new connection to this peer (in its 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 Peer to connect to.
- */
-void
-GMP_connect (struct CadetPeer *peer)
-{
-  struct CadetTunnel3 *t;
-  struct CadetPeerPath *p;
-  struct CadetConnection *c;
-  int rerun_search;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "peer_connect towards %s\n", GMP_2s (peer));
-
-  /* If we have a current hello, try to connect using it. */
-  GMP_try_connect (peer);
-
-  t = peer->tunnel;
-  c = NULL;
-  rerun_search = GNUNET_NO;
-
-  if (NULL != peer->path_head)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  some path exists\n");
-    p = peer_get_best_path (peer);
-    if (NULL != p)
-    {
-      char *s;
-
-      s = path_2s (p);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  path to use: %s\n", s);
-      GNUNET_free (s);
-
-      c = GMT_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 cadet
-         * 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.
-         *
-         * GMT_use_path -> GMC_new -> register_neighbors takes care of
-         * updating statistics about this issue.
-         */
-        rerun_search = GNUNET_YES;
-      }
-      else
-      {
-        GMC_send_create (c);
-        return;
-      }
-    }
-    else
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  but is NULL, all paths are in use\n");
-    }
-  }
-
-  if (NULL != peer->search_h && GNUNET_YES == rerun_search)
-  {
-    GMD_search_stop (peer->search_h);
-    peer->search_h = NULL;
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "  Stopping DHT GET for peer %s\n",
-         GMP_2s (peer));
-  }
-
-  if (NULL == peer->search_h)
-  {
-    const struct GNUNET_PeerIdentity *id;
-
-    id = GNUNET_PEER_resolve2 (peer->id);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-                "  Starting DHT GET for peer %s\n", GMP_2s (peer));
-    peer->search_h = GMD_search (id, &search_handler, peer);
-    if (CADET_TUNNEL3_NEW == GMT_get_cstate (t))
-      GMT_change_cstate (t, CADET_TUNNEL3_SEARCHING);
-  }
-}
-
-
-/**
- * Chech whether there is a direct (core level)  connection to peer.
- *
- * @param peer Peer to check.
- *
- * @return #GNUNET_YES if there is a direct connection.
- */
-int
-GMP_is_neighbor (const struct CadetPeer *peer)
-{
-  struct CadetPeerPath *path;
-
-  if (NULL == peer->connections)
-    return GNUNET_NO;
-
-  for (path = peer->path_head; NULL != path; path = path->next)
-  {
-    if (3 > path->length)
-      return GNUNET_YES;
-  }
-
-  /* Is not a neighbor but connections is not NULL, probably disconnecting */
-  return GNUNET_NO;
-}
-
-
-/**
- * Create and initialize a new tunnel towards a peer, in case it has none.
- * In case the peer already has a tunnel, nothing is done.
- *
- * Does not generate any traffic, just creates the local data structures.
- *
- * @param peer Peer towards which to create the tunnel.
- */
-void
-GMP_add_tunnel (struct CadetPeer *peer)
-{
-  if (NULL != peer->tunnel)
-    return;
-  peer->tunnel = GMT_new (peer);
-}
-
-
-/**
- * Add a connection to a neighboring peer.
- *
- * Store that the peer is the first hop of the connection in one
- * direction and that on peer disconnect the connection must be
- * notified and destroyed, for it will no longer be valid.
- *
- * @param peer Peer to add connection to.
- * @param c Connection to add.
- *
- * @return GNUNET_OK on success.
- */
-int
-GMP_add_connection (struct CadetPeer *peer,
-                    struct CadetConnection *c)
-{
-  int result;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "adding connection %s\n", GMC_2s (c));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "to peer %s\n", GMP_2s (peer));
-
-  if (NULL == peer->connections)
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Peer %s is not a neighbor!\n",
-         GMP_2s (peer));
-    return GNUNET_SYSERR;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "peer %s ok, has %u connections.\n",
-       GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections));
-  result = GNUNET_CONTAINER_multihashmap_put (peer->connections,
-                                              GMC_get_h (c),
-                                              c,
-                                              
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       " now has %u connections.\n",
-       GNUNET_CONTAINER_multihashmap_size (peer->connections));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "result %u\n", result);
-
-  return result;
-}
-
-
-/**
- * Add the path to the peer and update the path used to reach it in case this
- * is the shortest.
- *
- * @param peer 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?
- *
- * @return path if path was taken, pointer to existing duplicate if exists
- *         NULL on error.
- */
-struct CadetPeerPath *
-GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *path,
-              int trusted)
-{
-  struct CadetPeerPath *aux;
-  unsigned int l;
-  unsigned int l2;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
-       path->length, GMP_2s (peer));
-
-  if ((NULL == peer) || (NULL == path))
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return NULL;
-  }
-  if (path->peers[path->length - 1] != peer->id)
-  {
-    GNUNET_break (0);
-    path_destroy (path);
-    return NULL;
-  }
-
-  for (l = 1; l < path->length; l++)
-  {
-    if (path->peers[l] == myid)
-    {
-      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));
-    }
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length);
-
-  if (2 >= path->length && GNUNET_NO == trusted)
-  {
-    /* Only allow CORE to tell us about direct paths */
-    path_destroy (path);
-    return NULL;
-  }
-
-  l = path_get_length (path);
-  if (0 == l)
-  {
-    path_destroy (path);
-    return NULL;
-  }
-
-  GNUNET_assert (peer->id == path->peers[path->length - 1]);
-  for (aux = peer->path_head; aux != NULL; aux = aux->next)
-  {
-    l2 = path_get_length (aux);
-    if (l2 > l)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  added\n");
-      GNUNET_CONTAINER_DLL_insert_before (peer->path_head,
-                                          peer->path_tail, aux, path);
-      if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel))
-      {
-        GMP_connect (peer);
-      }
-      return path;
-    }
-    else
-    {
-      if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
-      {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "  already known\n");
-        path_destroy (path);
-        return aux;
-      }
-    }
-  }
-  GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, peer->path_tail,
-                                    path);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  added last\n");
-  if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel))
-  {
-    GMP_connect (peer);
-  }
-  return path;
-}
-
-
-/**
- * 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 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?
- *
- * @return path if path was taken, pointer to existing duplicate if exists
- *         NULL on error.
- */
-struct CadetPeerPath *
-GMP_add_path_to_origin (struct CadetPeer *peer,
-                        struct CadetPeerPath *path,
-                        int trusted)
-{
-  if (NULL == path)
-    return NULL;
-  path_invert (path);
-  return GMP_add_path (peer, path, trusted);
-}
-
-
-/**
- * Adds a path to the info of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-void
-GMP_add_path_to_all (const struct CadetPeerPath *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 CadetPeer *aux;
-    struct CadetPeerPath *copy;
-
-    aux = GMP_get_short (p->peers[i]);
-    copy = path_duplicate (p);
-    copy->length = i + 1;
-    GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
-  }
-}
-
-
-/**
- * Remove any path to the peer that has the extact same peers as the one given.
- *
- * @param peer Peer to remove the path from.
- * @param path Path to remove. Is always destroyed .
- */
-void
-GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path)
-{
-  struct CadetPeerPath *iter;
-  struct CadetPeerPath *next;
-
-  GNUNET_assert (myid == path->peers[0]);
-  GNUNET_assert (peer->id == path->peers[path->length - 1]);
-
-  for (iter = peer->path_head; NULL != iter; iter = next)
-  {
-    next = iter->next;
-    if (0 == memcmp (path->peers, iter->peers,
-                     sizeof (GNUNET_PEER_Id) * path->length))
-    {
-      GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter);
-      if (iter != path)
-        path_destroy (iter);
-    }
-  }
-  path_destroy (path);
-}
-
-
-/**
- * Remove a connection from a neighboring peer.
- *
- * @param peer Peer to remove connection from.
- * @param c Connection to remove.
- *
- * @return GNUNET_OK on success.
- */
-int
-GMP_remove_connection (struct CadetPeer *peer,
-                       const struct CadetConnection *c)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "removing connection %s\n", GMC_2s (c));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "from peer %s\n", GMP_2s (peer));
-
-  if (NULL == peer || NULL == peer->connections)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Peer %s is not a neighbor!\n",
-         GMP_2s (peer));
-    return GNUNET_SYSERR;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "peer %s ok, has %u connections.\n",
-       GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections));
-
-  return GNUNET_CONTAINER_multihashmap_remove (peer->connections,
-                                               GMC_get_h (c),
-                                               c);
-}
-
-/**
- * Start the DHT search for new paths towards the peer: we don't have
- * enough good connections.
- *
- * @param peer Destination peer.
- */
-void
-GMP_start_search (struct CadetPeer *peer)
-{
-  if (NULL != peer->search_h)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  peer->search_h = GMD_search (GMP_get_id (peer), &search_handler, peer);
-}
-
-
-/**
- * Stop the DHT search for new paths towards the peer: we already have
- * enough good connections.
- *
- * @param peer Destination peer.
- */
-void
-GMP_stop_search (struct CadetPeer *peer)
-{
-  if (NULL == peer->search_h)
-  {
-    return;
-  }
-
-  GMD_search_stop (peer->search_h);
-  peer->search_h = NULL;
-}
-
-
-/**
- * Get the Full ID of a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Full ID of peer.
- */
-const struct GNUNET_PeerIdentity *
-GMP_get_id (const struct CadetPeer *peer)
-{
-  return GNUNET_PEER_resolve2 (peer->id);
-}
-
-
-/**
- * Get the Short ID of a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Short ID of peer.
- */
-GNUNET_PEER_Id
-GMP_get_short_id (const struct CadetPeer *peer)
-{
-  return peer->id;
-}
-
-
-/**
- * Set tunnel.
- *
- * @param peer Peer.
- * @param t Tunnel.
- */
-void
-GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t)
-{
-  peer->tunnel = t;
-  if (NULL == t && NULL != peer->search_h)
-  {
-    GMP_stop_search (peer);
-  }
-}
-
-
-/**
- * Get the tunnel towards a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Tunnel towards peer.
- */
-struct CadetTunnel3 *
-GMP_get_tunnel (const struct CadetPeer *peer)
-{
-  return peer->tunnel;
-}
-
-
-/**
- * Set the hello message.
- *
- * @param peer Peer whose message to set.
- * @param hello Hello message.
- */
-void
-GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message 
*hello)
-{
-  struct GNUNET_HELLO_Message *old;
-  size_t size;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GMP_2s (peer));
-  if (NULL == hello)
-    return;
-
-  old = GMP_get_hello (peer);
-  if (NULL == old)
-  {
-    size = GNUNET_HELLO_size (hello);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " new (%u bytes)\n", size);
-    peer->hello = GNUNET_malloc (size);
-    memcpy (peer->hello, hello, size);
-  }
-  else
-  {
-    peer->hello = GNUNET_HELLO_merge (old, hello);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " merge into %p (%u bytes)\n",
-         peer->hello, GNUNET_HELLO_size (hello));
-    GNUNET_free (old);
-  }
-}
-
-
-/**
- * Get the hello message.
- *
- * @param peer Peer whose message to get.
- *
- * @return Hello message.
- */
-struct GNUNET_HELLO_Message *
-GMP_get_hello (struct CadetPeer *peer)
-{
-  struct GNUNET_TIME_Absolute expiration;
-  struct GNUNET_TIME_Relative remaining;
-
-  if (NULL == peer->hello)
-    return NULL;
-
-  expiration = GNUNET_HELLO_get_last_expiration (peer->hello);
-  remaining = GNUNET_TIME_absolute_get_remaining (expiration);
-  if (0 == remaining.rel_value_us)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n",
-         GNUNET_STRINGS_absolute_time_to_string (expiration));
-    GNUNET_free (peer->hello);
-    peer->hello = NULL;
-  }
-  return peer->hello;
-}
-
-
-/**
- * Try to connect to a peer on TRANSPORT level.
- *
- * @param peer Peer to whom to connect.
- */
-void
-GMP_try_connect (struct CadetPeer *peer)
-{
-  struct GNUNET_HELLO_Message *hello;
-  struct GNUNET_MessageHeader *mh;
-
-  if (NULL == transport_handle)
-    return;
-
-  hello = GMP_get_hello (peer);
-  if (NULL == hello)
-    return;
-
-  mh = GNUNET_HELLO_get_header (hello);
-  GNUNET_TRANSPORT_offer_hello (transport_handle, mh, try_connect, peer);
-}
-
-
-/**
- * Notify a peer that a link between two other peers is broken. If any path
- * used that link, eliminate it.
- *
- * @param peer Peer affected by the change.
- * @param peer1 Peer whose link is broken.
- * @param peer2 Peer whose link is broken.
- */
-void
-GMP_notify_broken_link (struct CadetPeer *peer,
-                        struct GNUNET_PeerIdentity *peer1,
-                        struct GNUNET_PeerIdentity *peer2)
-{
-  struct CadetPeerPath *iter;
-  struct CadetPeerPath *next;
-  unsigned int i;
-  GNUNET_PEER_Id p1;
-  GNUNET_PEER_Id p2;
-
-  p1 = GNUNET_PEER_search (peer1);
-  p2 = GNUNET_PEER_search (peer2);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2);
-  if (0 == p1 || 0 == p2)
-  {
-    /* We don't even know them */
-    return;
-  }
-
-  for (iter = peer->path_head; NULL != iter; iter = next)
-  {
-    next = iter->next;
-    for (i = 0; i < iter->length - 1; i++)
-    {
-      if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2)
-          || (iter->peers[i] == p2 && iter->peers[i + 1] == p1))
-      {
-        char *s;
-
-        s = path_2s (iter);
-        LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s);
-        GNUNET_free (s);
-
-        path_invalidate (iter);
-      }
-    }
-  }
-}
-
-
-/**
- * Count the number of known paths toward the peer.
- *
- * @param peer Peer to get path info.
- *
- * @return Number of known paths.
- */
-unsigned int
-GMP_count_paths (const struct CadetPeer *peer)
-{
-  struct CadetPeerPath *iter;
-  unsigned int i;
-
-  for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next)
-    i++;
-
-  return i;
-}
-
-
-/**
- * Iterate all known peers.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
-{
-  GNUNET_CONTAINER_multipeermap_iterate (peers, iter, cls);
-}
-
-
-/**
- * Get the static string for a peer ID.
- *
- * @param peer Peer.
- *
- * @return Static string for it's ID.
- */
-const char *
-GMP_2s (const struct CadetPeer *peer)
-{
-  if (NULL == peer)
-    return "(NULL)";
-  return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_peer.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_peer.h 2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/gnunet-service-cadet_peer.h 2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,418 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_peer.h
- * @brief cadet service; dealing with remote peers
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMP (Gnunet Cadet Peer)
- */
-
-#ifndef GNUNET_SERVICE_CADET_PEER_H
-#define GNUNET_SERVICE_CADET_PEER_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct CadetPeer;
-
-/**
- * Struct containing info about a queued transmission to this peer
- */
-struct CadetPeerQueue;
-
-#include "gnunet-service-cadet_connection.h"
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param c Connection this message was on.
- * @param sent Was it really sent? (Could have been canceled)
- * @param type Type of message sent.
- * @param pid Packet ID, or 0 if not applicable (create, destroy, etc).
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- * @param wait Time spent waiting for core (only the time for THIS message)
- */
-typedef void (*GMP_sent) (void *cls,
-                          struct CadetConnection *c, int sent,
-                          uint16_t type, uint32_t pid, int fwd, size_t size,
-                          struct GNUNET_TIME_Relative wait);
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize peer subsystem.
- *
- * @param c Configuration.
- */
-void
-GMP_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the peer subsystem.
- */
-void
-GMP_shutdown (void);
-
-
-/**
- * Retrieve the CadetPeer stucture associated with the peer, create one
- * and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer_id Full identity of the peer.
- *
- * @return Existing or newly created peer structure.
- */
-struct CadetPeer *
-GMP_get (const struct GNUNET_PeerIdentity *peer_id);
-
-
-/**
- * Retrieve the CadetPeer 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 structure.
- */
-struct CadetPeer *
-GMP_get_short (const GNUNET_PEER_Id peer);
-
-/**
- * Try to establish a new connection to this peer (in its 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 Peer to connect to.
- */
-void
-GMP_connect (struct CadetPeer *peer);
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- * @param sent Was it really sent? (Could have been canceled)
- * @param pid PID, if relevant (was sent and was a payload message).
- */
-void
-GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
-                   int sent, uint32_t pid);
-
-/**
- * @brief Queue and pass message to core when possible.
- *
- * @param peer Peer towards which to queue the message.
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- *            build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @param c Connection this message belongs to (cannot be NULL).
- * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
- * @param cont Continuation to be called once CORE has taken the message.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it is sent. Once cont is called
- *         message has been sent and therefore the handle is no longer valid.
- */
-struct CadetPeerQueue *
-GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
-               uint16_t payload_type, uint32_t payload_id,
-               size_t size, struct CadetConnection *c, int fwd,
-               GMP_sent cont, void *cont_cls);
-
-/**
- * Cancel all queued messages to a peer that belong to a certain connection.
- *
- * @param peer Peer towards whom to cancel.
- * @param c Connection whose queued messages to cancel. Might be destroyed by
- *          the sent continuation call.
- */
-void
-GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c);
-
-/**
- * Get the first message for a connection and unqueue it.
- *
- * @param peer Neighboring peer.
- * @param c Connection.
- *
- * @return First message for this connection.
- */
-struct GNUNET_MessageHeader *
-GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c);
-
-void
-GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c);
-
-/**
- * Set tunnel.
- *
- * @param peer Peer.
- * @param t Tunnel.
- */
-void
-GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t);
-
-/**
- * Check whether there is a direct (core level)  connection to peer.
- *
- * @param peer Peer to check.
- *
- * @return #GNUNET_YES if there is a direct connection.
- */
-int
-GMP_is_neighbor (const struct CadetPeer *peer);
-
-/**
- * Create and initialize a new tunnel towards a peer, in case it has none.
- *
- * Does not generate any traffic, just creates the local data structures.
- *
- * @param peer Peer towards which to create the tunnel.
- */
-void
-GMP_add_tunnel (struct CadetPeer *peer);
-
-/**
- * Add a connection to a neighboring peer.
- *
- * Store that the peer is the first hop of the connection in one
- * direction and that on peer disconnect the connection must be
- * notified and destroyed, for it will no longer be valid.
- *
- * @param peer Peer to add connection to.
- * @param c Connection to add.
- *
- * @return GNUNET_OK on success.
- */
-int
-GMP_add_connection (struct CadetPeer *peer, struct CadetConnection *c);
-
-/**
- * Add the path to the peer and update the path used to reach it in case this
- * is the shortest.
- *
- * @param peer 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?
- *
- * @return path if path was taken, pointer to existing duplicate if exists
- *         NULL on error.
- */
-struct CadetPeerPath *
-GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *p, int trusted);
-
-/**
- * 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 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?
- *
- * @return path if path was taken, pointer to existing duplicate if exists
- *         NULL on error.
- */
-struct CadetPeerPath *
-GMP_add_path_to_origin (struct CadetPeer *peer,
-                        struct CadetPeerPath *path,
-                        int trusted);
-
-/**
- * Adds a path to the info of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-void
-GMP_add_path_to_all (const struct CadetPeerPath *p, int confirmed);
-
-/**
- * Remove any path to the peer that has the extact same peers as the one given.
- *
- * @param peer Peer to remove the path from.
- * @param path Path to remove. Is always destroyed .
- */
-void
-GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path);
-
-/**
- * Remove a connection from a neighboring peer.
- *
- * @param peer Peer to remove connection from.
- * @param c Connection to remove.
- *
- * @return GNUNET_OK on success.
- */
-int
-GMP_remove_connection (struct CadetPeer *peer, const struct CadetConnection 
*c);
-
-/**
- * Start the DHT search for new paths towards the peer: we don't have
- * enough good connections.
- *
- * @param peer Destination peer.
- */
-void
-GMP_start_search (struct CadetPeer *peer);
-
-/**
- * Stop the DHT search for new paths towards the peer: we already have
- * enough good connections.
- *
- * @param peer Destination peer.
- */
-void
-GMP_stop_search (struct CadetPeer *peer);
-
-/**
- * Get the Full ID of a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Full ID of peer.
- */
-const struct GNUNET_PeerIdentity *
-GMP_get_id (const struct CadetPeer *peer);
-
-/**
- * Get the Short ID of a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Short ID of peer.
- */
-GNUNET_PEER_Id
-GMP_get_short_id (const struct CadetPeer *peer);
-
-/**
- * Get the tunnel towards a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Tunnel towards peer.
- */
-struct CadetTunnel3 *
-GMP_get_tunnel (const struct CadetPeer *peer);
-
-/**
- * Set the hello message.
- *
- * @param peer Peer whose message to set.
- * @param hello Hello message.
- */
-void
-GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message 
*hello);
-
-/**
- * Get the hello message.
- *
- * @param peer Peer whose message to get.
- *
- * @return Hello message.
- */
-struct GNUNET_HELLO_Message *
-GMP_get_hello (struct CadetPeer *peer);
-
-
-/**
- * Try to connect to a peer on TRANSPORT level.
- *
- * @param peer Peer to whom to connect.
- */
-void
-GMP_try_connect (struct CadetPeer *peer);
-
-/**
- * Notify a peer that a link between two other peers is broken. If any path
- * used that link, eliminate it.
- *
- * @param peer Peer affected by the change.
- * @param peer1 Peer whose link is broken.
- * @param peer2 Peer whose link is broken.
- */
-void
-GMP_notify_broken_link (struct CadetPeer *peer,
-                        struct GNUNET_PeerIdentity *peer1,
-                        struct GNUNET_PeerIdentity *peer2);
-
-/**
- * Count the number of known paths toward the peer.
- *
- * @param peer Peer to get path info.
- *
- * @return Number of known paths.
- */
-unsigned int
-GMP_count_paths (const struct CadetPeer *peer);
-
-/**
- * Iterate all known peers.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
-
-/**
- * Get the static string for a peer ID.
- *
- * @param peer Peer.
- *
- * @return Static string for it's ID.
- */
-const char *
-GMP_2s (const struct CadetPeer *peer);
-
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_PEER_H */
-#endif
-/* end of gnunet-cadet-service_peer.h */

Deleted: gnunet/src/mesh/gnunet-service-cadet_tunnel.c
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_tunnel.c       2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_tunnel.c       2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,2887 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_signatures.h"
-#include "gnunet_statistics_service.h"
-
-#include "cadet_protocol.h"
-#include "cadet_path.h"
-
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
-
-#define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
-
-#define CONNECTIONS_PER_TUNNEL 3
-
-/******************************************************************************/
-/********************************   STRUCTS  
**********************************/
-/******************************************************************************/
-
-struct CadetTChannel
-{
-  struct CadetTChannel *next;
-  struct CadetTChannel *prev;
-  struct CadetChannel *ch;
-};
-
-
-/**
- * Connection list and metadata.
- */
-struct CadetTConnection
-{
-  /**
-   * Next in DLL.
-   */
-  struct CadetTConnection *next;
-
-  /**
-   * Prev in DLL.
-   */
-  struct CadetTConnection *prev;
-
-  /**
-   * Connection handle.
-   */
-  struct CadetConnection *c;
-
-  /**
-   * Creation time, to keep oldest connection alive.
-   */
-  struct GNUNET_TIME_Absolute created;
-
-  /**
-   * Connection throughput, to keep fastest connection alive.
-   */
-  uint32_t throughput;
-};
-
-/**
- * Structure used during a Key eXchange.
- */
-struct CadetTunnelKXCtx
-{
-  /**
-   * Decryption ("their") old key, for decrypting traffic sent by the
-   * other end before the key exchange started.
-   */
-  struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old;
-
-  /**
-   * Challenge to send in a ping and expect in the pong.
-   */
-  uint32_t challenge;
-};
-
-/**
- * Struct containing all information regarding a tunnel to a peer.
- */
-struct CadetTunnel3
-{
-    /**
-     * Endpoint of the tunnel.
-     */
-  struct CadetPeer *peer;
-
-    /**
-     * State of the tunnel connectivity.
-     */
-  enum CadetTunnel3CState cstate;
-
-  /**
-   * State of the tunnel encryption.
-   */
-  enum CadetTunnel3EState estate;
-
-  /**
-   * Key eXchange context.
-   */
-  struct CadetTunnelKXCtx *kx_ctx;
-
-  /**
-   * Encryption ("our") key.
-   */
-  struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
-
-  /**
-   * Decryption ("their") key.
-   */
-  struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
-
-  /**
-   * Task to start the rekey process.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier rekey_task;
-
-  /**
-   * Paths that are actively used to reach the destination peer.
-   */
-  struct CadetTConnection *connection_head;
-  struct CadetTConnection *connection_tail;
-
-  /**
-   * Next connection number.
-   */
-  uint32_t next_cid;
-
-  /**
-   * Channels inside this tunnel.
-   */
-  struct CadetTChannel *channel_head;
-  struct CadetTChannel *channel_tail;
-
-  /**
-   * Channel ID for the next created channel.
-   */
-  CADET_ChannelNumber next_chid;
-
-  /**
-   * Destroy flag: if true, destroy on last message.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier destroy_task;
-
-  /**
-   * Queued messages, to transmit once tunnel gets connected.
-   */
-  struct CadetTunnelDelayed *tq_head;
-  struct CadetTunnelDelayed *tq_tail;
-};
-
-
-/**
- * Struct used to save messages in a non-ready tunnel to send once connected.
- */
-struct CadetTunnelDelayed
-{
-  /**
-   * DLL
-   */
-  struct CadetTunnelDelayed *next;
-  struct CadetTunnelDelayed *prev;
-
-  /**
-   * Tunnel.
-   */
-  struct CadetTunnel3 *t;
-
-  /**
-   * Tunnel queue given to the channel to cancel request. Update on 
send_queued.
-   */
-  struct CadetTunnel3Queue *tq;
-
-  /**
-   * Message to send.
-   */
-  /* struct GNUNET_MessageHeader *msg; */
-};
-
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetTunnel3Queue
-{
-  /**
-   * Connection queue handle, to cancel if necessary.
-   */
-  struct CadetConnectionQueue *cq;
-
-  /**
-   * Handle in case message hasn't been given to a connection yet.
-   */
-  struct CadetTunnelDelayed *tqd;
-
-  /**
-   * Continuation to call once sent.
-   */
-  GMT_sent cont;
-
-  /**
-   * Closure for @c cont.
-   */
-  void *cont_cls;
-};
-
-
-/******************************************************************************/
-/*******************************   GLOBALS  
***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-
-/**
- * Don't try to recover tunnels if shutting down.
- */
-extern int shutting_down;
-
-
-/**
- * Set of all tunnels, in order to trigger a new exchange on rekey.
- * Indexed by peer's ID.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
-
-/**
- * Default TTL for payload packets.
- */
-static unsigned long long default_ttl;
-
-/**
- * Own private key.
- */
-const static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
-
-/**
- * Own ephemeral private key.
- */
-static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
-
-/**
- * Cached message used to perform a key exchange.
- */
-static struct GNUNET_CADET_KX_Ephemeral kx_msg;
-
-/**
- * Task to generate a new ephemeral key.
- */
-static GNUNET_SCHEDULER_TaskIdentifier rekey_task;
-
-/**
- * Rekey period.
- */
-static struct GNUNET_TIME_Relative rekey_period;
-
-/******************************************************************************/
-/********************************   STATIC  
***********************************/
-/******************************************************************************/
-
-/**
- * Get string description for tunnel connectivity state.
- *
- * @param cs Tunnel state.
- *
- * @return String representation.
- */
-static const char *
-cstate2s (enum CadetTunnel3CState cs)
-{
-  static char buf[128];
-
-  switch (cs)
-  {
-    case CADET_TUNNEL3_NEW:
-      return "CADET_TUNNEL3_NEW";
-    case CADET_TUNNEL3_SEARCHING:
-      return "CADET_TUNNEL3_SEARCHING";
-    case CADET_TUNNEL3_WAITING:
-      return "CADET_TUNNEL3_WAITING";
-    case CADET_TUNNEL3_READY:
-      return "CADET_TUNNEL3_READY";
-
-    default:
-      sprintf (buf, "%u (UNKNOWN STATE)", cs);
-      return buf;
-  }
-  return "";
-}
-
-
-/**
- * Get string description for tunnel encryption state.
- *
- * @param es Tunnel state.
- *
- * @return String representation.
- */
-static const char *
-estate2s (enum CadetTunnel3EState es)
-{
-  static char buf[128];
-
-  switch (es)
-  {
-    case CADET_TUNNEL3_KEY_UNINITIALIZED:
-      return "CADET_TUNNEL3_KEY_UNINITIALIZED";
-    case CADET_TUNNEL3_KEY_SENT:
-      return "CADET_TUNNEL3_KEY_SENT";
-    case CADET_TUNNEL3_KEY_PING:
-      return "CADET_TUNNEL3_KEY_PING";
-    case CADET_TUNNEL3_KEY_OK:
-      return "CADET_TUNNEL3_KEY_OK";
-
-    default:
-      sprintf (buf, "%u (UNKNOWN STATE)", es);
-      return buf;
-  }
-  return "";
-}
-
-
-/**
- * @brief Check if tunnel is ready to send traffic.
- *
- * Tunnel must be connected and with encryption correctly set up.
- *
- * @param t Tunnel to check.
- *
- * @return #GNUNET_YES if ready, #GNUNET_NO otherwise
- */
-static int
-is_ready (struct CadetTunnel3 *t)
-{
-  int ready;
-
-  GMT_debug (t);
-  ready = (CADET_TUNNEL3_READY == t->cstate && CADET_TUNNEL3_KEY_OK == 
t->estate);
-  ready = ready || GMT_is_loopback (t);
-  return ready;
-}
-
-
-/**
- * Ephemeral key message purpose size.
- *
- * @return Size of the part of the ephemeral key message that must be signed.
- */
-size_t
-ephemeral_purpose_size (void)
-{
-  return sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-         sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-         sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-         sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
-         sizeof (struct GNUNET_PeerIdentity);
-}
-
-
-/**
- * Size of the encrypted part of a ping message.
- *
- * @return Size of the encrypted part of a ping message.
- */
-size_t
-ping_encryption_size (void)
-{
-  return sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t);
-}
-
-
-/**
- * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!!
- *
- * @param tch Tunnel's channel handle.
- *
- * @return Amount of messages the channel can still buffer towards the client.
- */
-static unsigned int
-get_channel_buffer (const struct CadetTChannel *tch)
-{
-  int fwd;
-
-  /* If channel is outgoing, is origin in the FWD direction and fwd is YES */
-  fwd = GMCH_is_origin (tch->ch, GNUNET_YES);
-
-  return GMCH_get_buffer (tch->ch, fwd);
-}
-
-
-/**
- * Get the channel's allowance status.
- *
- * @param tch Tunnel's channel handle.
- *
- * @return #GNUNET_YES if we allowed the client to send data to us.
- */
-static int
-get_channel_allowed (const struct CadetTChannel *tch)
-{
-  int fwd;
-
-  /* If channel is outgoing, is origin in the FWD direction and fwd is YES */
-  fwd = GMCH_is_origin (tch->ch, GNUNET_YES);
-
-  return GMCH_get_allowed (tch->ch, fwd);
-}
-
-
-/**
- * Get the connection's buffer.
- *
- * @param tc Tunnel's connection handle.
- *
- * @return Amount of messages the connection can still buffer.
- */
-static unsigned int
-get_connection_buffer (const struct CadetTConnection *tc)
-{
-  int fwd;
-
-  /* If connection is outgoing, is origin in the FWD direction and fwd is YES 
*/
-  fwd = GMC_is_origin (tc->c, GNUNET_YES);
-
-  return GMC_get_buffer (tc->c, fwd);
-}
-
-
-/**
- * Get the connection's allowance.
- *
- * @param tc Tunnel's connection handle.
- *
- * @return Amount of messages we have allowed the next peer to send us.
- */
-static unsigned int
-get_connection_allowed (const struct CadetTConnection *tc)
-{
-  int fwd;
-
-  /* If connection is outgoing, is origin in the FWD direction and fwd is YES 
*/
-  fwd = GMC_is_origin (tc->c, GNUNET_YES);
-
-  return GMC_get_allowed (tc->c, fwd);
-}
-
-
-/**
- * Check that a ephemeral key message s well formed and correctly signed.
- *
- * @param t Tunnel on which the message came.
- * @param msg The ephemeral key message.
- *
- * @return GNUNET_OK if message is fine, GNUNET_SYSERR otherwise.
- */
-int
-check_ephemeral (struct CadetTunnel3 *t,
-                 const struct GNUNET_CADET_KX_Ephemeral *msg)
-{
-  /* Check message size */
-  if (ntohs (msg->header.size) != sizeof (struct GNUNET_CADET_KX_Ephemeral))
-    return GNUNET_SYSERR;
-
-  /* Check signature size */
-  if (ntohl (msg->purpose.size) != ephemeral_purpose_size ())
-    return GNUNET_SYSERR;
-
-  /* Check origin */
-  if (0 != memcmp (&msg->origin_identity,
-                   GMP_get_id (t->peer),
-                   sizeof (struct GNUNET_PeerIdentity)))
-    return GNUNET_SYSERR;
-
-  /* Check signature */
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_CADET_KX,
-                                  &msg->purpose,
-                                  &msg->signature,
-                                  &msg->origin_identity.public_key))
-    return GNUNET_SYSERR;
-
-  return GNUNET_OK;
-}
-
-
-/**
- * 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. Can overlap with @c dst.
- * @param size Size of the plaintext.
- * @param iv Initialization Vector to use.
- */
-static int
-t_encrypt (struct CadetTunnel3 *t,
-           void *dst, const void *src,
-           size_t size, uint32_t iv)
-{
-  struct GNUNET_CRYPTO_SymmetricInitializationVector siv;
-  size_t out_size;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_encrypt start\n");
-  GNUNET_CRYPTO_symmetric_derive_iv (&siv, &t->e_key, &iv, sizeof (iv), NULL);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_encrypt IV derived\n");
-  out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &t->e_key, &siv, dst);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_encrypt end\n");
-
-  return out_size;
-}
-
-
-/**
- * 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. Can overlap with @c dst.
- * @param size Size of the encrypted data.
- * @param iv Initialization Vector to use.
- */
-static int
-t_decrypt (struct CadetTunnel3 *t,
-           void *dst, const void *src,
-           size_t size, uint32_t iv)
-{
-  struct GNUNET_CRYPTO_SymmetricInitializationVector siv;
-  struct GNUNET_CRYPTO_SymmetricSessionKey *key;
-  size_t out_size;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt start\n");
-  if (t->estate == CADET_TUNNEL3_KEY_OK || t->estate == CADET_TUNNEL3_KEY_PING)
-  {
-    key = &t->d_key;
-  }
-  else if (NULL != t->kx_ctx)
-  {
-    key = &t->kx_ctx->d_key_old;
-  }
-  else
-  {
-    GNUNET_STATISTICS_update (stats, "# non decryptable data", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "WARNING got data on %s without a valid key\n",
-         GMT_2s (t));
-    GMT_debug (t);
-    return 0;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt iv\n");
-  GNUNET_CRYPTO_symmetric_derive_iv (&siv, key, &iv, sizeof (iv), NULL);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt iv done\n");
-  out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, key, &siv, dst);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  t_decrypt end\n");
-
-  return out_size;
-}
-
-
-/**
- * Create key material by doing ECDH on the local and remote ephemeral keys.
- *
- * @param key_material Where to store the key material.
- * @param ephemeral_key Peer's public ephemeral key.
- */
-void
-derive_key_material (struct GNUNET_HashCode *key_material,
-                     const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key)
-{
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
-                              ephemeral_key,
-                              key_material))
-  {
-    GNUNET_break (0);
-  }
-}
-
-/**
- * Create a symmetic key from the identities of both ends and the key material
- * from ECDH.
- *
- * @param key Destination for the generated key.
- * @param sender ID of the peer that will encrypt with @c key.
- * @param receiver ID of the peer that will decrypt with @c key.
- * @param key_material Hash created with ECDH with the ephemeral keys.
- */
-void
-derive_symmertic (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
-                  const struct GNUNET_PeerIdentity *sender,
-                  const struct GNUNET_PeerIdentity *receiver,
-                  const struct GNUNET_HashCode *key_material)
-{
-  const char salt[] = "CADET kx salt";
-
-  GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
-                     salt, sizeof (salt),
-                     key_material, sizeof (struct GNUNET_HashCode),
-                     sender, sizeof (struct GNUNET_PeerIdentity),
-                     receiver, sizeof (struct GNUNET_PeerIdentity),
-                     NULL);
-}
-
-/**
- * Pick a connection on which send the next data message.
- *
- * @param t Tunnel on which to send the message.
- *
- * @return The connection on which to send the next message.
- */
-static struct CadetConnection *
-tunnel_get_connection (struct CadetTunnel3 *t)
-{
-  struct CadetTConnection *iter;
-  struct CadetConnection *best;
-  unsigned int qn;
-  unsigned int lowest_q;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GMT_2s (t));
-  best = NULL;
-  lowest_q = UINT_MAX;
-  for (iter = t->connection_head; NULL != iter; iter = iter->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection %s: %u\n",
-         GMC_2s (iter->c), GMC_get_state (iter->c));
-    if (CADET_CONNECTION_READY == GMC_get_state (iter->c))
-    {
-      qn = GMC_get_qn (iter->c, GMC_is_origin (iter->c, GNUNET_YES));
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "    q_n %u, \n", qn);
-      if (qn < lowest_q)
-      {
-        best = iter->c;
-        lowest_q = qn;
-      }
-    }
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GMC_2s (best));
-  return best;
-}
-
-
-/**
- * Callback called when a queued message is sent.
- *
- * Calculates the average time and connection packet tracking.
- *
- * @param cls Closure (TunnelQueue handle).
- * @param c Connection this message was on.
- * @param q Connection queue handle (unused).
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-static void
-tun_message_sent (void *cls,
-              struct CadetConnection *c,
-              struct CadetConnectionQueue *q,
-              uint16_t type, int fwd, size_t size)
-{
-  struct CadetTunnel3Queue *qt = cls;
-  struct CadetTunnel3 *t;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n");
-
-  GNUNET_assert (NULL != qt->cont);
-  t = NULL == c ? NULL : GMC_get_tunnel (c);
-  qt->cont (qt->cont_cls, t, qt, type, size);
-  GNUNET_free (qt);
-}
-
-
-/**
- * Delete a queued message: either was sent or the channel was destroyed
- * before the tunnel's key exchange had a chance to finish.
- *
- * @param tqd Delayed queue handle.
- */
-static void
-unqueue_data (struct CadetTunnelDelayed *tqd)
-{
-  GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd);
-  GNUNET_free (tqd);
-}
-
-
-/**
- * Cache a message to be sent once tunnel is online.
- *
- * @param t Tunnel to hold the message.
- * @param msg Message itself (copy will be made).
- */
-static struct CadetTunnelDelayed *
-queue_data (struct CadetTunnel3 *t, const struct GNUNET_MessageHeader *msg)
-{
-  struct CadetTunnelDelayed *tqd;
-  uint16_t size = ntohs (msg->size);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t));
-
-  if (GNUNET_YES == is_ready (t))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  tqd = GNUNET_malloc (sizeof (struct CadetTunnelDelayed) + size);
-
-  tqd->t = t;
-  memcpy (&tqd[1], msg, size);
-  GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd);
-  return tqd;
-}
-
-
-/**
- * Calculate HMAC.
- *
- * @param t Tunnel to get keys from.
- * @param plaintext Content to HMAC.
- * @param size Size of @c plaintext.
- * @param iv Initialization vector for the message.
- * @param outgoing Is this an outgoing message that we encrypted?
- * @param hmac Destination to store the HMAC.
- */
-static void
-t_hmac (struct CadetTunnel3 *t, const void *plaintext, size_t size, uint32_t 
iv,
-        int outgoing, struct GNUNET_CADET_Hash *hmac)
-{
-  struct GNUNET_CRYPTO_AuthKey auth_key;
-  static const char ctx[] = "cadet authentication key";
-  struct GNUNET_CRYPTO_SymmetricSessionKey *key;
-  struct GNUNET_HashCode hash;
-
-  key = outgoing ? &t->e_key : &t->d_key;
-  GNUNET_CRYPTO_hmac_derive_key (&auth_key, key,
-                                 &iv, sizeof (iv),
-                                 key, sizeof (*key),
-                                 ctx, sizeof (ctx),
-                                 NULL);
-  GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash);
-  memcpy (hmac, &hash, sizeof (*hmac));
-}
-
-
-/**
- * Sends an already built message on a tunnel, encrypting it and
- * choosing the best connection.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param c Connection to use (autoselect if NULL).
- * @param force Force the tunnel to take the message (buffer overfill).
- * @param cont Continuation to call once message is really sent.
- * @param cont_cls Closure for @c cont.
- * @param existing_q In case this a transmission of previously queued data,
- *                   this should be TunnelQueue given to the client.
- *                   Otherwise, NULL.
- *
- * @return Handle to cancel message. NULL if @c cont is NULL.
- */
-static struct CadetTunnel3Queue *
-send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                       struct CadetTunnel3 *t, struct CadetConnection *c,
-                       int force, GMT_sent cont, void *cont_cls,
-                       struct CadetTunnel3Queue *existing_q)
-{
-  struct CadetTunnel3Queue *tq;
-  struct GNUNET_CADET_Encrypted *msg;
-  size_t size = ntohs (message->size);
-  char cbuf[sizeof (struct GNUNET_CADET_Encrypted) + size];
-  uint32_t mid;
-  uint32_t iv;
-  uint16_t type;
-  int fwd;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t));
-
-  if (GNUNET_NO == is_ready (t))
-  {
-    struct CadetTunnelDelayed *tqd;
-    /* A non null existing_q indicates sending of queued data.
-     * Should only happen after tunnel becomes ready.
-     */
-    GNUNET_assert (NULL == existing_q);
-    tqd = queue_data (t, message);
-    if (NULL == cont)
-      return NULL;
-    tq = GNUNET_new (struct CadetTunnel3Queue);
-    tq->tqd = tqd;
-    tqd->tq = tq;
-    tq->cont = cont;
-    tq->cont_cls = cont_cls;
-    return tq;
-  }
-
-  GNUNET_assert (GNUNET_NO == GMT_is_loopback (t));
-
-  iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
-  msg = (struct GNUNET_CADET_Encrypted *) cbuf;
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED);
-  msg->iv = iv;
-  GNUNET_assert (t_encrypt (t, &msg[1], message, size, iv) == size);
-  t_hmac (t, &msg[1], size, iv, GNUNET_YES, &msg->hmac);
-  msg->header.size = htons (sizeof (struct GNUNET_CADET_Encrypted) + size);
-
-  if (NULL == c)
-    c = tunnel_get_connection (t);
-  if (NULL == c)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task
-        || CADET_TUNNEL3_SEARCHING != t->cstate)
-    {
-      GNUNET_break (0);
-      GMT_debug (t);
-    }
-    return NULL;
-  }
-
-  mid = 0;
-  type = ntohs (message->type);
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      if (GNUNET_MESSAGE_TYPE_CADET_DATA == type)
-        mid = ntohl (((struct GNUNET_CADET_Data *) message)->mid);
-      else
-        mid = ntohl (((struct GNUNET_CADET_DataACK *) message)->mid);
-      /* Fall thru */
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      msg->cid = *GMC_get_id (c);
-      msg->ttl = htonl (default_ttl);
-      break;
-    default:
-      GNUNET_break (0);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s\n", GM_m2s (type));
-
-  fwd = GMC_is_origin (c, GNUNET_YES);
-
-  if (NULL == cont)
-  {
-    GNUNET_break (NULL ==
-                  GMC_send_prebuilt_message (&msg->header, type, mid,
-                                             c, fwd, force, NULL, NULL));
-    return NULL;
-  }
-  if (NULL == existing_q)
-  {
-    tq = GNUNET_new (struct CadetTunnel3Queue); /* FIXME valgrind: leak*/
-  }
-  else
-  {
-    tq = existing_q;
-    tq->tqd = NULL;
-  }
-  tq->cq = GMC_send_prebuilt_message (&msg->header, type, mid, c, fwd, force,
-                                      &tun_message_sent, tq);
-  tq->cont = cont;
-  tq->cont_cls = cont_cls;
-
-  return tq;
-}
-
-
-/**
- * Send all cached messages that we can, tunnel is online.
- *
- * @param t Tunnel that holds the messages. Cannot be loopback.
- */
-static void
-send_queued_data (struct CadetTunnel3 *t)
-{
-  struct CadetTunnelDelayed *tqd;
-  struct CadetTunnelDelayed *next;
-  unsigned int room;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "GMT_send_queued_data on tunnel %s\n",
-       GMT_2s (t));
-
-  if (GMT_is_loopback (t))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if (GNUNET_NO == is_ready (t))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  not ready yet: %s/%s\n",
-         estate2s (t->estate), cstate2s (t->cstate));
-    return;
-  }
-
-  room = GMT_get_connections_buffer (t);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer space: %u\n", room);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  tq head: %p\n", t->tq_head);
-  for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n");
-    next = tqd->next;
-    room--;
-    send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1],
-                           tqd->t, NULL, GNUNET_YES,
-                           NULL != tqd->tq ? tqd->tq->cont : NULL,
-                           NULL != tqd->tq ? tqd->tq->cont_cls : NULL,
-                           tqd->tq);
-    unqueue_data (tqd);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data end\n", GMP_2s 
(t->peer));
-}
-
-
-/**
- * Sends key exchange message on a tunnel, choosing the best connection.
- * Should not be called on loopback tunnels.
- *
- * @param t Tunnel on which this message is transmitted.
- * @param message Message to send. Function modifies it.
- */
-static void
-send_kx (struct CadetTunnel3 *t,
-         const struct GNUNET_MessageHeader *message)
-{
-  struct CadetConnection *c;
-  struct GNUNET_CADET_KX *msg;
-  size_t size = ntohs (message->size);
-  char cbuf[sizeof (struct GNUNET_CADET_KX) + size];
-  uint16_t type;
-  int fwd;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT KX on Tunnel %s\n", GMT_2s (t));
-
-  /* Avoid loopback. */
-  if (GMT_is_loopback (t))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  loopback!\n");
-    GNUNET_break (0);
-    return;
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  being destroyed, why bother\n");
-    return;
-  }
-
-  /* Must have a connection. */
-  if (NULL == t->connection_head)
-  {
-    GNUNET_break (CADET_TUNNEL3_SEARCHING == t->cstate);
-    GMT_debug (t);
-    return;
-  }
-
-  msg = (struct GNUNET_CADET_KX *) cbuf;
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX);
-  msg->header.size = htons (sizeof (struct GNUNET_CADET_KX) + size);
-  c = tunnel_get_connection (t);
-  if (NULL == c)
-  {
-    GNUNET_break (GNUNET_SCHEDULER_NO_TASK != t->destroy_task
-                  || CADET_TUNNEL3_READY != t->cstate);
-    GMT_debug (t);
-    return;
-  }
-  type = ntohs (message->type);
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL:
-    case GNUNET_MESSAGE_TYPE_CADET_KX_PING:
-    case GNUNET_MESSAGE_TYPE_CADET_KX_PONG:
-      memcpy (&msg[1], message, size);
-      break;
-    default:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
-           GM_m2s (type));
-      GNUNET_break (0);
-  }
-
-  fwd = GMC_is_origin (t->connection_head->c, GNUNET_YES);
-  /* TODO save handle and cancel in case of a unneeded retransmission */
-  GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX,
-                             message->type, c, fwd, GNUNET_YES, NULL, NULL);
-}
-
-
-/**
- * Send the ephemeral key on a tunnel.
- *
- * @param t Tunnel on which to send the key.
- */
-static void
-send_ephemeral (struct CadetTunnel3 *t)
-{
-  LOG (GNUNET_ERROR_TYPE_INFO, "=> EPHM for %s\n", GMT_2s (t));
-
-  kx_msg.sender_status = htonl (t->estate);
-  send_kx (t, &kx_msg.header);
-}
-
-/**
- * Send a ping message on a tunnel.
- *
- * @param t Tunnel on which to send the ping.
- */
-static void
-send_ping (struct CadetTunnel3 *t)
-{
-  struct GNUNET_CADET_KX_Ping msg;
-
-  LOG (GNUNET_ERROR_TYPE_INFO, "=> PING for %s\n", GMT_2s (t));
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_PING);
-  msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
-  msg.target = *GMP_get_id (t->peer);
-  msg.nonce = t->kx_ctx->challenge;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending %u\n", msg.nonce);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s\n", GNUNET_i2s (&msg.target));
-  t_encrypt (t, &msg.target, &msg.target, ping_encryption_size(), msg.iv);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  e sending %u\n", msg.nonce);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  e towards %s\n", GNUNET_i2s (&msg.target));
-
-  send_kx (t, &msg.header);
-}
-
-
-/**
- * Send a pong message on a tunnel.
- *
- * @param t Tunnel on which to send the pong.
- * @param challenge Value sent in the ping that we have to send back.
- */
-static void
-send_pong (struct CadetTunnel3 *t, uint32_t challenge)
-{
-  struct GNUNET_CADET_KX_Pong msg;
-
-  LOG (GNUNET_ERROR_TYPE_INFO, "=> PONG for %s\n", GMT_2s (t));
-  msg.header.size = htons (sizeof (msg));
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_PONG);
-  msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
-  msg.nonce = challenge;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending %u\n", msg.nonce);
-  t_encrypt (t, &msg.nonce, &msg.nonce, sizeof (msg.nonce), msg.iv);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  e sending %u\n", msg.nonce);
-
-  send_kx (t, &msg.header);
-}
-
-
-/**
- * Initiate a rekey with the remote peer.
- *
- * @param cls Closure (tunnel).
- * @param tc TaskContext.
- */
-static void
-rekey_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetTunnel3 *t = cls;
-
-  t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-key Tunnel %s\n", GMT_2s (t));
-  if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-    return;
-
-  if (NULL == t->kx_ctx)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  new kx ctx\n");
-    t->kx_ctx = GNUNET_new (struct CadetTunnelKXCtx);
-    t->kx_ctx->challenge =
-        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
-    t->kx_ctx->d_key_old = t->d_key;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  new challenge for %s: %u\n",
-         GMT_2s (t), t->kx_ctx->challenge);
-  }
-  send_ephemeral (t);
-  switch (t->estate)
-  {
-    case CADET_TUNNEL3_KEY_UNINITIALIZED:
-      t->estate = CADET_TUNNEL3_KEY_SENT;
-      break;
-    case CADET_TUNNEL3_KEY_SENT:
-      break;
-    case CADET_TUNNEL3_KEY_PING:
-    case CADET_TUNNEL3_KEY_OK:
-      send_ping (t);
-      t->estate = CADET_TUNNEL3_KEY_PING;
-      break;
-    default:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected state %u\n", t->estate);
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  next call in %s\n",
-       GNUNET_STRINGS_relative_time_to_string (REKEY_WAIT, GNUNET_YES));
-  t->rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_WAIT, &rekey_tunnel, t);
-}
-
-
-/**
- * Out ephemeral key has changed, create new session key on all tunnels.
- *
- * @param cls Closure (size of the hashmap).
- * @param key Current public key.
- * @param value Value in the hash map (tunnel).
- *
- * @return #GNUNET_YES, so we should continue to iterate,
- */
-static int
-rekey_iterator (void *cls,
-                const struct GNUNET_PeerIdentity *key,
-                void *value)
-{
-  struct CadetTunnel3 *t = value;
-  struct GNUNET_TIME_Relative delay;
-  long n = (long) cls;
-  uint32_t r;
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task)
-    return GNUNET_YES;
-
-  if (GNUNET_YES == GMT_is_loopback (t))
-    return GNUNET_YES;
-
-  r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t) n * 
100);
-  delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, r);
-  t->rekey_task = GNUNET_SCHEDULER_add_delayed (delay, &rekey_tunnel, t);
-
-  return GNUNET_YES;
-}
-
-
-/**
- * Create a new ephemeral key and key message, schedule next rekeying.
- *
- * @param cls Closure (unused).
- * @param tc TaskContext.
- */
-static void
-rekey (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TIME_Absolute time;
-  long n;
-
-  rekey_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-    return;
-
-  GNUNET_free_non_null (my_ephemeral_key);
-  my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
-
-  time = GNUNET_TIME_absolute_get ();
-  kx_msg.creation_time = GNUNET_TIME_absolute_hton (time);
-  time = GNUNET_TIME_absolute_add (time, rekey_period);
-  time = GNUNET_TIME_absolute_add (time, GNUNET_TIME_UNIT_MINUTES);
-  kx_msg.expiration_time = GNUNET_TIME_absolute_hton (time);
-  GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key, &kx_msg.ephemeral_key);
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CRYPTO_eddsa_sign (my_private_key,
-                                           &kx_msg.purpose,
-                                           &kx_msg.signature));
-
-  n = (long) GNUNET_CONTAINER_multipeermap_size (tunnels);
-  GNUNET_CONTAINER_multipeermap_iterate (tunnels, &rekey_iterator, (void *) n);
-
-  rekey_task = GNUNET_SCHEDULER_add_delayed (rekey_period, &rekey, NULL);
-}
-
-
-/**
- * Called only on shutdown, destroy every tunnel.
- *
- * @param cls Closure (unused).
- * @param key Current public key.
- * @param value Value in the hash map (tunnel).
- *
- * @return #GNUNET_YES, so we should continue to iterate,
- */
-static int
-destroy_iterator (void *cls,
-                const struct GNUNET_PeerIdentity *key,
-                void *value)
-{
-  struct CadetTunnel3 *t = value;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_shutdown destroying tunnel at %p\n", t);
-  GMT_destroy (t);
-  return GNUNET_YES;
-}
-
-
-/**
- * Notify remote peer that we don't know a channel he is talking about,
- * probably CHANNEL_DESTROY was missed.
- *
- * @param t Tunnel on which to notify.
- * @param gid ID of the channel.
- */
-static void
-send_channel_destroy (struct CadetTunnel3 *t, unsigned int gid)
-{
-  struct GNUNET_CADET_ChannelManage msg;
-
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
-  msg.header.size = htons (sizeof (msg));
-  msg.chid = htonl (gid);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "WARNING destroying unknown channel %u on tunnel %s\n",
-       gid, GMT_2s (t));
-  send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL);
-}
-
-
-/**
- * Demultiplex data per channel and call appropriate channel handler.
- *
- * @param t Tunnel on which the data came.
- * @param msg Data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_data (struct CadetTunnel3 *t,
-             const struct GNUNET_CADET_Data *msg,
-             int fwd)
-{
-  struct CadetChannel *ch;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size <
-      sizeof (struct GNUNET_CADET_Data) +
-      sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n",
-              GM_m2s (ntohs (msg[1].header.type)));
-
-  /* Check channel */
-  ch = GMT_get_channel (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats, "# data on unknown channel",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel 0x%X unknown\n",
-         ntohl (msg->chid));
-    send_channel_destroy (t, ntohl (msg->chid));
-    return;
-  }
-
-  GMCH_handle_data (ch, msg, fwd);
-}
-
-
-/**
- * Demultiplex data ACKs per channel and update appropriate channel buffer 
info.
- *
- * @param t Tunnel on which the DATA ACK came.
- * @param msg DATA ACK message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_data_ack (struct CadetTunnel3 *t,
-                 const struct GNUNET_CADET_DataACK *msg,
-                 int fwd)
-{
-  struct CadetChannel *ch;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_DataACK))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* Check channel */
-  ch = GMT_get_channel (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-         ntohl (msg->chid));
-    return;
-  }
-
-  GMCH_handle_data_ack (ch, msg, fwd);
-}
-
-
-/**
- * Handle channel create.
- *
- * @param t Tunnel on which the data came.
- * @param msg Data message.
- */
-static void
-handle_ch_create (struct CadetTunnel3 *t,
-                  const struct GNUNET_CADET_ChannelCreate *msg)
-{
-  struct CadetChannel *ch;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelCreate))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* Check channel */
-  ch = GMT_get_channel (t, ntohl (msg->chid));
-  if (NULL != ch && ! GMT_is_loopback (t))
-  {
-    /* Probably a retransmission, safe to ignore */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "   already exists...\n");
-  }
-  ch = GMCH_handle_create (t, msg);
-  if (NULL != ch)
-    GMT_add_channel (t, ch);
-}
-
-
-
-/**
- * Handle channel NACK: check correctness and call channel handler for NACKs.
- *
- * @param t Tunnel on which the NACK came.
- * @param msg NACK message.
- */
-static void
-handle_ch_nack (struct CadetTunnel3 *t,
-                const struct GNUNET_CADET_ChannelManage *msg)
-{
-  struct CadetChannel *ch;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* Check channel */
-  ch = GMT_get_channel (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-         ntohl (msg->chid));
-    return;
-  }
-
-  GMCH_handle_nack (ch);
-}
-
-
-/**
- * Handle a CHANNEL ACK (SYNACK/ACK).
- *
- * @param t Tunnel on which the CHANNEL ACK came.
- * @param msg CHANNEL ACK message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_ch_ack (struct CadetTunnel3 *t,
-               const struct GNUNET_CADET_ChannelManage *msg,
-               int fwd)
-{
-  struct CadetChannel *ch;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* Check channel */
-  ch = GMT_get_channel (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel",
-                              1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
-         ntohl (msg->chid));
-    return;
-  }
-
-  GMCH_handle_ack (ch, msg, fwd);
-}
-
-
-
-/**
- * Handle a channel destruction message.
- *
- * @param t Tunnel on which the message came.
- * @param msg Channel destroy message.
- * @param fwd Is this message fwd? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_ch_destroy (struct CadetTunnel3 *t,
-                   const struct GNUNET_CADET_ChannelManage *msg,
-                   int fwd)
-{
-  struct CadetChannel *ch;
-  size_t size;
-
-  /* Check size */
-  size = ntohs (msg->header.size);
-  if (size != sizeof (struct GNUNET_CADET_ChannelManage))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  /* Check channel */
-  ch = GMT_get_channel (t, ntohl (msg->chid));
-  if (NULL == ch)
-  {
-    /* Probably a retransmission, safe to ignore */
-    return;
-  }
-
-  GMCH_handle_destroy (ch, msg, fwd);
-}
-
-
-/**
- * The peer's ephemeral key has changed: update the symmetrical keys.
- *
- * @param t Tunnel this message came on.
- * @param msg Key eXchange message.
- */
-static void
-handle_ephemeral (struct CadetTunnel3 *t,
-                  const struct GNUNET_CADET_KX_Ephemeral *msg)
-{
-  struct GNUNET_HashCode km;
-  LOG (GNUNET_ERROR_TYPE_INFO, "<=== EPHM for %s\n", GMT_2s (t));
-
-  if (GNUNET_OK != check_ephemeral (t, msg))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-  derive_key_material (&km, &msg->ephemeral_key);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  km is %s\n", GNUNET_h2s (&km));
-  derive_symmertic (&t->e_key, &my_full_id, GMP_get_id (t->peer), &km);
-  derive_symmertic (&t->d_key, GMP_get_id (t->peer), &my_full_id, &km);
-  if (CADET_TUNNEL3_KEY_SENT == t->estate)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  our key was sent, send ping\n");
-    send_ping (t);
-    t->estate = CADET_TUNNEL3_KEY_PING;
-  }
-}
-
-
-/**
- * Peer wants to check our symmetrical keys by sending an encrypted challenge.
- * Answer with by retransmitting the challenge with the "opposite" key.
- *
- * @param t Tunnel this message came on.
- * @param msg Key eXchange Ping message.
- */
-static void
-handle_ping (struct CadetTunnel3 *t,
-             const struct GNUNET_CADET_KX_Ping *msg)
-{
-  struct GNUNET_CADET_KX_Ping res;
-
-  if (ntohs (msg->header.size) != sizeof (res))
-  {
-    GNUNET_break_op (0);
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_INFO, "<=== PING for %s\n", GMT_2s (t));
-  t_decrypt (t, &res.target, &msg->target, ping_encryption_size (), msg->iv);
-  if (0 != memcmp (&my_full_id, &res.target, sizeof (my_full_id)))
-  {
-    // FIXME: move to debug
-    GNUNET_STATISTICS_update (stats, "# malformed PINGs", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_WARNING, "  malformed PING on %s\n", GMT_2s (t));
-    LOG (GNUNET_ERROR_TYPE_WARNING, "  e got %u\n", msg->nonce);
-    LOG (GNUNET_ERROR_TYPE_WARNING, "  e towards %s\n", GNUNET_i2s 
(&msg->target));
-    LOG (GNUNET_ERROR_TYPE_WARNING, "  got %u\n", res.nonce);
-    LOG (GNUNET_ERROR_TYPE_WARNING, "  towards %s\n", GNUNET_i2s 
(&res.target));
-    return;
-  }
-
-  send_pong (t, res.nonce);
-}
-
-
-/**
- * Peer has answer to our challenge.
- * If answer is successful, consider the key exchange finished and clean
- * up all related state.
- *
- * @param t Tunnel this message came on.
- * @param msg Key eXchange Pong message.
- */
-static void
-handle_pong (struct CadetTunnel3 *t,
-             const struct GNUNET_CADET_KX_Pong *msg)
-{
-  uint32_t challenge;
-
-  LOG (GNUNET_ERROR_TYPE_INFO, "<=== PONG for %s\n", GMT_2s (t));
-  if (GNUNET_SCHEDULER_NO_TASK == t->rekey_task)
-  {
-    GNUNET_STATISTICS_update (stats, "# duplicate PONG messages", 1, 
GNUNET_NO);
-    return;
-  }
-  t_decrypt (t, &challenge, &msg->nonce, sizeof (uint32_t), msg->iv);
-
-  if (challenge != t->kx_ctx->challenge)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong PONG challenge\n");
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "PONG: %u (e: %u). Expected: %u.\n",
-         challenge, msg->nonce, t->kx_ctx->challenge);
-    GNUNET_break_op (0);
-    return;
-  }
-  GNUNET_SCHEDULER_cancel (t->rekey_task);
-  t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_free (t->kx_ctx);
-  t->kx_ctx = NULL;
-  GMT_change_estate (t, CADET_TUNNEL3_KEY_OK);
-}
-
-
-/**
- * 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? This only is meaningful in loopback 
channels.
- *            #GNUNET_YES if message is FWD on the respective channel 
(loopback)
- *            #GNUNET_NO if message is BCK on the respective channel (loopback)
- *            #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_decrypted (struct CadetTunnel3 *t,
-                  const struct GNUNET_MessageHeader *msgh,
-                  int fwd)
-{
-  uint16_t type;
-
-  type = ntohs (msgh->type);
-  LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s on %s\n", GM_m2s (type), GMT_2s (t));
-
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE:
-      /* Do nothing, connection aleady got updated. */
-      GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_DATA:
-      /* Don't send hop ACK, wait for client to ACK */
-      handle_data (t, (struct GNUNET_CADET_Data *) msgh, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK:
-      handle_data_ack (t, (struct GNUNET_CADET_DataACK *) msgh, fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
-      handle_ch_create (t,
-                        (struct GNUNET_CADET_ChannelCreate *) msgh);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK:
-      handle_ch_nack (t,
-                      (struct GNUNET_CADET_ChannelManage *) msgh);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK:
-      handle_ch_ack (t,
-                     (struct GNUNET_CADET_ChannelManage *) msgh,
-                     fwd);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
-      handle_ch_destroy (t,
-                         (struct GNUNET_CADET_ChannelManage *) msgh,
-                         fwd);
-      break;
-
-    default:
-      GNUNET_break_op (0);
-      LOG (GNUNET_ERROR_TYPE_WARNING,
-           "end-to-end message not known (%u)\n",
-           ntohs (msgh->type));
-      GMT_debug (t);
-  }
-}
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Decrypt and demultiplex by message type. Call appropriate handler
- * for every message.
- *
- * @param t Tunnel this message came on.
- * @param msg Encrypted message.
- */
-void
-GMT_handle_encrypted (struct CadetTunnel3 *t,
-                      const struct GNUNET_CADET_Encrypted *msg)
-{
-  size_t size = ntohs (msg->header.size);
-  size_t payload_size = size - sizeof (struct GNUNET_CADET_Encrypted);
-  size_t decrypted_size;
-  char cbuf [payload_size];
-  struct GNUNET_MessageHeader *msgh;
-  unsigned int off;
-  struct GNUNET_CADET_Hash hmac;
-
-  decrypted_size = t_decrypt (t, cbuf, &msg[1], payload_size, msg->iv);
-  t_hmac (t, &msg[1], payload_size, msg->iv, GNUNET_NO, &hmac);
-  if (0 != memcmp (&hmac, &msg->hmac, sizeof (hmac)))
-  {
-    /* checksum failed */
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed checksum validation for a message on tunnel `%s'\n",
-                GMT_2s (t));
-    GNUNET_STATISTICS_update (stats, "# wrong HMAC", 1, GNUNET_NO);
-    return;
-  }
-  off = 0;
-  while (off < decrypted_size)
-  {
-    msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
-    handle_decrypted (t, msgh, GNUNET_SYSERR);
-    off += ntohs (msgh->size);
-  }
-}
-
-
-/**
- * Demultiplex an encapsulated KX message by message type.
- *
- * @param t Tunnel on which the message came.
- * @param message Payload of KX message.
- */
-void
-GMT_handle_kx (struct CadetTunnel3 *t,
-               const struct GNUNET_MessageHeader *message)
-{
-  uint16_t type;
-
-  type = ntohs (message->type);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message received\n", type);
-  switch (type)
-  {
-    case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL:
-      handle_ephemeral (t, (struct GNUNET_CADET_KX_Ephemeral *) message);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_KX_PING:
-      handle_ping (t, (struct GNUNET_CADET_KX_Ping *) message);
-      break;
-
-    case GNUNET_MESSAGE_TYPE_CADET_KX_PONG:
-      handle_pong (t, (struct GNUNET_CADET_KX_Pong *) message);
-      break;
-
-    default:
-      GNUNET_break_op (0);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message not known (%u)\n", type);
-  }
-}
-
-
-/**
- * Initialize the tunnel subsystem.
- *
- * @param c Configuration handle.
- * @param key ECC private key, to derive all other keys and do crypto.
- */
-void
-GMT_init (const struct GNUNET_CONFIGURATION_Handle *c,
-          const struct GNUNET_CRYPTO_EddsaPrivateKey *key)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DEFAULT_TTL",
-                                             &default_ttl))
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
-                               "CADET", "DEFAULT_TTL", "USING DEFAULT");
-    default_ttl = 64;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REKEY_PERIOD",
-                                           &rekey_period))
-  {
-    rekey_period = GNUNET_TIME_UNIT_DAYS;
-  }
-
-  my_private_key = key;
-  kx_msg.header.size = htons (sizeof (kx_msg));
-  kx_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL);
-  kx_msg.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CADET_KX);
-  kx_msg.purpose.size = htonl (ephemeral_purpose_size ());
-  kx_msg.origin_identity = my_full_id;
-  rekey_task = GNUNET_SCHEDULER_add_now (&rekey, NULL);
-
-  tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
-}
-
-
-/**
- * Shut down the tunnel subsystem.
- */
-void
-GMT_shutdown (void)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != rekey_task)
-  {
-    GNUNET_SCHEDULER_cancel (rekey_task);
-    rekey_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL);
-  GNUNET_CONTAINER_multipeermap_destroy (tunnels);
-}
-
-
-/**
- * Create a tunnel.
- *
- * @param destination Peer this tunnel is towards.
- */
-struct CadetTunnel3 *
-GMT_new (struct CadetPeer *destination)
-{
-  struct CadetTunnel3 *t;
-
-  t = GNUNET_new (struct CadetTunnel3);
-  t->next_chid = 0;
-  t->peer = destination;
-
-  if (GNUNET_OK !=
-      GNUNET_CONTAINER_multipeermap_put (tunnels, GMP_get_id (destination), t,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-  {
-    GNUNET_break (0);
-    GNUNET_free (t);
-    return NULL;
-  }
-  return t;
-}
-
-
-/**
- * Change the tunnel's connection state.
- *
- * @param t Tunnel whose connection state to change.
- * @param cstate New connection state.
- */
-void
-GMT_change_cstate (struct CadetTunnel3* t, enum CadetTunnel3CState cstate)
-{
-  if (NULL == t)
-    return;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n",
-       GMP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate));
-  if (myid != GMP_get_short_id (t->peer) &&
-      CADET_TUNNEL3_READY != t->cstate &&
-      CADET_TUNNEL3_READY == cstate)
-  {
-    t->cstate = cstate;
-    if (CADET_TUNNEL3_KEY_OK == t->estate)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate triggered send queued data\n");
-      send_queued_data (t);
-    }
-    else if (CADET_TUNNEL3_KEY_UNINITIALIZED == t->estate)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate triggered rekey\n");
-      rekey_tunnel (t, NULL);
-    }
-  }
-  t->cstate = cstate;
-
-  if (CADET_TUNNEL3_READY == cstate
-      && CONNECTIONS_PER_TUNNEL <= GMT_count_connections (t))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  cstate triggered stop dht\n");
-    GMP_stop_search (t->peer);
-  }
-}
-
-/**
- * Change the tunnel encryption state.
- *
- * @param t Tunnel whose encryption state to change.
- * @param state New encryption state.
- */
-void
-GMT_change_estate (struct CadetTunnel3* t, enum CadetTunnel3EState state)
-{
-  if (NULL == t)
-    return;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Tunnel %s estate was %s\n",
-       GMP_2s (t->peer), estate2s (t->estate));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Tunnel %s estate is now %s\n",
-       GMP_2s (t->peer), estate2s (state));
-  if (myid != GMP_get_short_id (t->peer) &&
-      CADET_TUNNEL3_KEY_OK != t->estate && CADET_TUNNEL3_KEY_OK == state)
-  {
-    t->estate = state;
-    send_queued_data (t);
-    return;
-  }
-  t->estate = state;
-}
-
-
-/**
- * @brief Check if tunnel has too many connections, and remove one if 
necessary.
- *
- * Currently this means the newest connection, unless it is a direct one.
- * Implemented as a task to avoid freeing a connection that is in the middle
- * of being created/processed.
- *
- * @param cls Closure (Tunnel to check).
- * @param tc Task context.
- */
-static void
-trim_connections (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetTunnel3 *t = cls;
-
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  if (GMT_count_connections (t) > 2 * CONNECTIONS_PER_TUNNEL)
-  {
-    struct CadetTConnection *iter;
-    struct CadetTConnection *c;
-
-    for (c = iter = t->connection_head; NULL != iter; iter = iter->next)
-    {
-      if ((NULL == c || iter->created.abs_value_us > c->created.abs_value_us)
-          && GNUNET_NO == GMC_is_direct (iter->c))
-      {
-        c = iter;
-      }
-    }
-    if (NULL != c)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Too many connections on tunnel %s\n",
-           GMT_2s (t));
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying connection %s\n",
-           GMC_2s (c->c));
-      GMC_destroy (c->c);
-    }
-    else
-    {
-      GNUNET_break (0);
-    }
-  }
-}
-
-
-/**
- * Add a connection to a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GMT_add_connection (struct CadetTunnel3 *t, struct CadetConnection *c)
-{
-  struct CadetTConnection *aux;
-
-  GNUNET_assert (NULL != c);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "add connection %s\n", GMC_2s (c));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " to tunnel %s\n", GMT_2s (t));
-  for (aux = t->connection_head; aux != NULL; aux = aux->next)
-    if (aux->c == c)
-      return;
-
-  aux = GNUNET_new (struct CadetTConnection);
-  aux->c = c;
-  aux->created = GNUNET_TIME_absolute_get ();
-
-  GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux);
-
-  GNUNET_SCHEDULER_add_now (&trim_connections, t);
-}
-
-
-/**
- * Mark a path as no longer valid for this tunnel: has been tried and failed.
- *
- * @param t Tunnel to update.
- * @param path Invalid path to remove. Is destroyed after removal.
- */
-void
-GMT_remove_path (struct CadetTunnel3 *t, struct CadetPeerPath *path)
-{
-  GMP_remove_path (t->peer, path);
-}
-
-
-/**
- * Remove a connection from a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GMT_remove_connection (struct CadetTunnel3 *t,
-                       struct CadetConnection *c)
-{
-  struct CadetTConnection *aux;
-  struct CadetTConnection *next;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n",
-       GMC_2s (c), GMT_2s (t));
-  for (aux = t->connection_head; aux != NULL; aux = next)
-  {
-    next = aux->next;
-    if (aux->c == c)
-    {
-      GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, 
aux);
-      GNUNET_free (aux);
-    }
-  }
-
-  /* Start new connections if needed */
-  if (CONNECTIONS_PER_TUNNEL < GMT_count_connections (t)
-      && GNUNET_SCHEDULER_NO_TASK == t->destroy_task
-      && CADET_TUNNEL3_SHUTDOWN != t->cstate
-      && GNUNET_NO == shutting_down)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  no more connections, getting new ones\n");
-    t->cstate = CADET_TUNNEL3_SEARCHING;
-    GMP_connect (t->peer);
-    return;
-  }
-
-  /* If not marked as ready, no change is needed */
-  if (CADET_TUNNEL3_READY != t->cstate)
-    return;
-
-  /* Check if any connection is ready to maintaing cstate */
-  for (aux = t->connection_head; aux != NULL; aux = aux->next)
-    if (CADET_CONNECTION_READY == GMC_get_state (aux->c))
-      return;
-
-  t->cstate = CADET_TUNNEL3_WAITING;
-}
-
-
-/**
- * Add a channel to a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GMT_add_channel (struct CadetTunnel3 *t, struct CadetChannel *ch)
-{
-  struct CadetTChannel *aux;
-
-  GNUNET_assert (NULL != ch);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t);
-
-  for (aux = t->channel_head; aux != NULL; aux = aux->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  already there %p\n", aux->ch);
-    if (aux->ch == ch)
-      return;
-  }
-
-  aux = GNUNET_new (struct CadetTChannel);
-  aux->ch = ch;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " adding %p to %p\n", aux, t->channel_head);
-  GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, t->channel_tail, aux);
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
-  {
-    GNUNET_SCHEDULER_cancel (t->destroy_task);
-    t->destroy_task = GNUNET_SCHEDULER_NO_TASK;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n");
-  }
-}
-
-
-/**
- * Remove a channel from a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GMT_remove_channel (struct CadetTunnel3 *t, struct CadetChannel *ch)
-{
-  struct CadetTChannel *aux;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t);
-  for (aux = t->channel_head; aux != NULL; aux = aux->next)
-  {
-    if (aux->ch == ch)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GMCH_2s (ch));
-      GNUNET_CONTAINER_DLL_remove (t->channel_head, t->channel_tail, aux);
-      GNUNET_free (aux);
-      return;
-    }
-  }
-}
-
-
-/**
- * Search for a channel by global ID.
- *
- * @param t Tunnel containing the channel.
- * @param chid Public channel number.
- *
- * @return channel handler, NULL if doesn't exist
- */
-struct CadetChannel *
-GMT_get_channel (struct CadetTunnel3 *t, CADET_ChannelNumber chid)
-{
-  struct CadetTChannel *iter;
-
-  if (NULL == t)
-    return NULL;
-
-  for (iter = t->channel_head; NULL != iter; iter = iter->next)
-  {
-    if (GMCH_get_id (iter->ch) == chid)
-      break;
-  }
-
-  return NULL == iter ? NULL : iter->ch;
-}
-
-
-/**
- * @brief Destroy a tunnel and free all resources.
- *
- * Should only be called a while after the tunnel has been marked as destroyed,
- * in case there is a new channel added to the same peer shortly after marking
- * the tunnel. This way we avoid a new public key handshake.
- *
- * @param cls Closure (tunnel to destroy).
- * @param tc Task context.
- */
-static void
-delayed_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct CadetTunnel3 *t = cls;
-  struct CadetTConnection *iter;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "delayed destroying tunnel %p\n", t);
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Not destroying tunnel, due to shutdown. "
-         "Tunnel at %p should have been freed by GMT_shutdown\n", t);
-    return;
-  }
-  t->destroy_task = GNUNET_SCHEDULER_NO_TASK;
-  t->cstate = CADET_TUNNEL3_SHUTDOWN;
-
-  for (iter = t->connection_head; NULL != iter; iter = iter->next)
-  {
-    GMC_send_destroy (iter->c);
-  }
-  GMT_destroy (t);
-}
-
-
-/**
- * Tunnel is empty: destroy it.
- *
- * Notifies all connections about the destruction.
- *
- * @param t Tunnel to destroy.
- */
-void
-GMT_destroy_empty (struct CadetTunnel3 *t)
-{
-  if (GNUNET_YES == shutting_down)
-    return; /* Will be destroyed immediately anyway */
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Tunnel %s is already scheduled for destruction\n",
-         GMT_2s (t));
-    GNUNET_break (0);
-    /* should never happen, tunnel can only become empty once, and the
-     * task identifier should be NO_TASK (cleaned when the tunnel was created
-     * or became un-empty)
-     */
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: destroying scheduled\n",
-       GMT_2s (t));
-
-  t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
-                                                  &delayed_destroy, t);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled destroy of %p as %llX\n",
-       t, t->destroy_task);
-}
-
-
-/**
- * Destroy tunnel if empty (no more channels).
- *
- * @param t Tunnel to destroy if empty.
- */
-void
-GMT_destroy_if_empty (struct CadetTunnel3 *t)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s destroy if empty\n", GMT_2s (t));
-  if (1 < GMT_count_channels (t))
-    return;
-
-  GMT_destroy_empty (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.
- */
-void
-GMT_destroy (struct CadetTunnel3 *t)
-{
-  struct CadetTConnection *iter_c;
-  struct CadetTConnection *next_c;
-  struct CadetTChannel *iter_ch;
-  struct CadetTChannel *next_ch;
-
-  if (NULL == t)
-    return;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n", GMP_2s (t->peer));
-
-  GNUNET_break (GNUNET_YES ==
-                GNUNET_CONTAINER_multipeermap_remove (tunnels,
-                                                      GMP_get_id (t->peer), 
t));
-
-  for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c)
-  {
-    next_c = iter_c->next;
-    GMC_destroy (iter_c->c);
-  }
-  for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch)
-  {
-    next_ch = iter_ch->next;
-    GMCH_destroy (iter_ch->ch);
-    /* Should only happen on shutdown, but it's ok. */
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "cancelling %llX\n", t->destroy_task);
-    GNUNET_SCHEDULER_cancel (t->destroy_task);
-    t->destroy_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-
-  GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
-  GMP_set_tunnel (t->peer, NULL);
-
-  if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task)
-  {
-    GNUNET_SCHEDULER_cancel (t->rekey_task);
-    t->rekey_task = GNUNET_SCHEDULER_NO_TASK;
-    if (NULL != t->kx_ctx)
-      GNUNET_free (t->kx_ctx);
-    else
-      GNUNET_break (0);
-  }
-
-  GNUNET_free (t);
-}
-
-
-/**
- * @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.
- */
-struct CadetConnection *
-GMT_use_path (struct CadetTunnel3 *t, struct CadetPeerPath *p)
-{
-  struct CadetConnection *c;
-  struct GNUNET_CADET_Hash cid;
-  unsigned int own_pos;
-
-  if (NULL == t || NULL == p)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  if (CADET_TUNNEL3_SHUTDOWN == t->cstate)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  for (own_pos = 0; own_pos < p->length; own_pos++)
-  {
-    if (p->peers[own_pos] == myid)
-      break;
-  }
-  if (own_pos >= p->length)
-  {
-    GNUNET_break_op (0);
-    return NULL;
-  }
-
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid));
-  c = GMC_new (&cid, t, p, own_pos);
-  if (NULL == c)
-  {
-    /* Path was flawed */
-    return NULL;
-  }
-  GMT_add_connection (t, c);
-  return c;
-}
-
-
-/**
- * Count established (ready) connections of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of connections.
- */
-unsigned int
-GMT_count_connections (struct CadetTunnel3 *t)
-{
-  struct CadetTConnection *iter;
-  unsigned int count;
-
-  if (NULL == t)
-    return 0;
-
-  for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
-    if (CADET_CONNECTION_DESTROYED != GMC_get_state (iter->c))
-      count++;
-
-  return count;
-}
-
-/**
- * Count channels of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of channels.
- */
-unsigned int
-GMT_count_channels (struct CadetTunnel3 *t)
-{
-  struct CadetTChannel *iter;
-  unsigned int count;
-
-  for (count = 0, iter = t->channel_head;
-       NULL != iter;
-       iter = iter->next, count++) /* skip */;
-
-  return count;
-}
-
-
-/**
- * Get the connectivity state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's connectivity state.
- */
-enum CadetTunnel3CState
-GMT_get_cstate (struct CadetTunnel3 *t)
-{
-  if (NULL == t)
-  {
-    GNUNET_assert (0);
-    return (enum CadetTunnel3CState) -1;
-  }
-  return t->cstate;
-}
-
-
-/**
- * Get the encryption state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's encryption state.
- */
-enum CadetTunnel3EState
-GMT_get_estate (struct CadetTunnel3 *t)
-{
-  if (NULL == t)
-  {
-    GNUNET_assert (0);
-    return (enum CadetTunnel3EState) -1;
-  }
-  return t->estate;
-}
-
-/**
- * Get the maximum buffer space for a tunnel towards a local client.
- *
- * @param t Tunnel.
- *
- * @return Biggest buffer space offered by any channel in the tunnel.
- */
-unsigned int
-GMT_get_channels_buffer (struct CadetTunnel3 *t)
-{
-  struct CadetTChannel *iter;
-  unsigned int buffer;
-  unsigned int ch_buf;
-
-  if (NULL == t->channel_head)
-  {
-    /* Probably getting buffer for a channel create/handshake. */
-    return 64;
-  }
-
-  buffer = 0;
-  for (iter = t->channel_head; NULL != iter; iter = iter->next)
-  {
-    ch_buf = get_channel_buffer (iter);
-    if (ch_buf > buffer)
-      buffer = ch_buf;
-  }
-  return buffer;
-}
-
-
-/**
- * Get the total buffer space for a tunnel for P2P traffic.
- *
- * @param t Tunnel.
- *
- * @return Buffer space offered by all connections in the tunnel.
- */
-unsigned int
-GMT_get_connections_buffer (struct CadetTunnel3 *t)
-{
-  struct CadetTConnection *iter;
-  unsigned int buffer;
-
-  buffer = 0;
-  for (iter = t->connection_head; NULL != iter; iter = iter->next)
-  {
-    if (GMC_get_state (iter->c) != CADET_CONNECTION_READY)
-    {
-      continue;
-    }
-    buffer += get_connection_buffer (iter);
-  }
-
-  return buffer;
-}
-
-
-/**
- * Get the tunnel's destination.
- *
- * @param t Tunnel.
- *
- * @return ID of the destination peer.
- */
-const struct GNUNET_PeerIdentity *
-GMT_get_destination (struct CadetTunnel3 *t)
-{
-  return GMP_get_id (t->peer);
-}
-
-
-/**
- * Get the tunnel's next free global channel ID.
- *
- * @param t Tunnel.
- *
- * @return GID of a channel free to use.
- */
-CADET_ChannelNumber
-GMT_get_next_chid (struct CadetTunnel3 *t)
-{
-  CADET_ChannelNumber chid;
-  CADET_ChannelNumber mask;
-  int result;
-
-  /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
-   * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0
-   * If peer's ID is bigger, start at 0x4... bit 30 = 1
-   */
-  result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GMP_get_id (t->peer));
-  if (0 > result)
-    mask = 0x40000000;
-  else
-    mask = 0x0;
-  t->next_chid |= mask;
-
-  while (NULL != GMT_get_channel (t, t->next_chid))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid);
-    t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-    t->next_chid |= mask;
-  }
-  chid = t->next_chid;
-  t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-  t->next_chid |= mask;
-
-  return chid;
-}
-
-
-/**
- * Send ACK on one or more channels due to buffer in connections.
- *
- * @param t Channel which has some free buffer space.
- */
-void
-GMT_unchoke_channels (struct CadetTunnel3 *t)
-{
-  struct CadetTChannel *iter;
-  unsigned int buffer;
-  unsigned int channels = GMT_count_channels (t);
-  unsigned int choked_n;
-  struct CadetChannel *choked[channels];
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head);
-  if (NULL != t->channel_head)
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch);
-
-  /* Get buffer space */
-  buffer = GMT_get_connections_buffer (t);
-  if (0 == buffer)
-  {
-    return;
-  }
-
-  /* Count and remember choked channels */
-  choked_n = 0;
-  for (iter = t->channel_head; NULL != iter; iter = iter->next)
-  {
-    if (GNUNET_NO == get_channel_allowed (iter))
-    {
-      choked[choked_n++] = iter->ch;
-    }
-  }
-
-  /* Unchoke random channels */
-  while (0 < buffer && 0 < choked_n)
-  {
-    unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                               choked_n);
-    GMCH_allow_client (choked[r], GMCH_is_origin (choked[r], GNUNET_YES));
-    choked_n--;
-    buffer--;
-    choked[r] = choked[choked_n];
-  }
-}
-
-
-/**
- * Send ACK on one or more connections due to buffer space to the client.
- *
- * Iterates all connections of the tunnel and sends ACKs appropriately.
- *
- * @param t Tunnel.
- */
-void
-GMT_send_connection_acks (struct CadetTunnel3 *t)
-{
-  struct CadetTConnection *iter;
-  uint32_t allowed;
-  uint32_t to_allow;
-  uint32_t allow_per_connection;
-  unsigned int cs;
-  unsigned int buffer;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n",
-       GMT_2s (t));
-
-  if (NULL == t)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  buffer = GMT_get_channels_buffer (t);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer %u\n", buffer);
-
-  /* Count connections, how many messages are already allowed */
-  cs = GMT_count_connections (t);
-  for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
-  {
-    allowed += get_connection_allowed (iter);
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  allowed %u\n", allowed);
-
-  /* Make sure there is no overflow */
-  if (allowed > buffer)
-  {
-    return;
-  }
-
-  /* Authorize connections to send more data */
-  to_allow = buffer; /* - allowed; */
-
-  for (iter = t->connection_head;
-       NULL != iter && to_allow > 0;
-       iter = iter->next)
-  {
-    allow_per_connection = to_allow/cs;
-    to_allow -= allow_per_connection;
-    cs--;
-    if (get_connection_allowed (iter) > 64 / 3)
-    {
-      continue;
-    }
-    GMC_allow (iter->c, allow_per_connection,
-               GMC_is_origin (iter->c, GNUNET_NO));
-  }
-
-  GNUNET_break (to_allow == 0);
-}
-
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GMT_cancel (struct CadetTunnel3Queue *q)
-{
-  if (NULL != q->cq)
-  {
-    GMC_cancel (q->cq);
-    /* tun_message_sent() will be called and free q */
-  }
-  else if (NULL != q->tqd)
-  {
-    unqueue_data (q->tqd);
-    q->tqd = NULL;
-    if (NULL != q->cont)
-      q->cont (q->cont_cls, NULL, q, 0, 0);
-    GNUNET_free (q);
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-}
-
-
-/**
- * Sends an already built message on a tunnel, encrypting it and
- * choosing the best connection if not provided.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param c Connection to use (autoselect if NULL).
- * @param force Force the tunnel to take the message (buffer overfill).
- * @param cont Continuation to call once message is really sent.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel message. NULL if @c cont is NULL.
- */
-struct CadetTunnel3Queue *
-GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           struct CadetTunnel3 *t, struct CadetConnection *c,
-                           int force, GMT_sent cont, void *cont_cls)
-{
-  return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL);
-}
-
-
-/**
- * Is the tunnel directed towards the local peer?
- *
- * @param t Tunnel.
- *
- * @return #GNUNET_YES if it is loopback.
- */
-int
-GMT_is_loopback (const struct CadetTunnel3 *t)
-{
-  return (myid == GMP_get_short_id (t->peer));
-}
-
-
-/**
- * Is the tunnel this path already?
- *
- * @param t Tunnel.
- * @param p Path.
- *
- * @return #GNUNET_YES a connection uses this path.
- */
-int
-GMT_is_path_used (const struct CadetTunnel3 *t, const struct CadetPeerPath *p)
-{
-  struct CadetTConnection *iter;
-
-  for (iter = t->connection_head; NULL != iter; iter = iter->next)
-    if (GMC_get_path (iter->c) == p)
-      return GNUNET_YES;
-
-  return GNUNET_NO;
-}
-
-
-/**
- * Get a cost of a path for a tunnel considering existing connections.
- *
- * @param t Tunnel.
- * @param path Candidate path.
- *
- * @return Cost of the path (path length + number of overlapping nodes)
- */
-unsigned int
-GMT_get_path_cost (const struct CadetTunnel3 *t,
-                   const struct CadetPeerPath *path)
-{
-  struct CadetTConnection *iter;
-  const struct CadetPeerPath *aux;
-  unsigned int overlap;
-  unsigned int i;
-  unsigned int j;
-
-  if (NULL == path)
-    return 0;
-
-  overlap = 0;
-  GNUNET_assert (NULL != t);
-
-  for (i = 0; i < path->length; i++)
-  {
-    for (iter = t->connection_head; NULL != iter; iter = iter->next)
-    {
-      aux = GMC_get_path (iter->c);
-      if (NULL == aux)
-        continue;
-
-      for (j = 0; j < aux->length; j++)
-      {
-        if (path->peers[i] == aux->peers[j])
-        {
-          overlap++;
-          break;
-        }
-      }
-    }
-  }
-  return path->length + overlap;
-}
-
-
-/**
- * Get the static string for the peer this tunnel is directed.
- *
- * @param t Tunnel.
- *
- * @return Static string the destination peer's ID.
- */
-const char *
-GMT_2s (const struct CadetTunnel3 *t)
-{
-  if (NULL == t)
-    return "(NULL)";
-
-  return GMP_2s (t->peer);
-}
-
-
-/******************************************************************************/
-/*****************************    INFO/DEBUG    
*******************************/
-/******************************************************************************/
-
-
-/**
- * Log all possible info about the tunnel state to stderr.
- *
- * @param t Tunnel to debug.
- */
-void
-GMT_debug (const struct CadetTunnel3 *t)
-{
-  struct CadetTChannel *iterch;
-  struct CadetTConnection *iterc;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT DEBUG TUNNEL TOWARDS %s\n", GMT_2s (t));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  cstate %s, estate %s\n",
-       cstate2s (t->cstate), estate2s (t->estate));
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  kx_ctx %p, rekey_task %u\n",
-       t->kx_ctx, t->rekey_task);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  tq_head %p, tq_tail %p\n",
-       t->tq_head, t->tq_tail);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  destroy %u\n", t->destroy_task);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  channels:\n");
-  for (iterch = t->channel_head; NULL != iterch; iterch = iterch->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  - %s\n", GMCH_2s (iterch->ch));
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  connections:\n");
-  for (iterc = t->connection_head; NULL != iterc; iterc = iterc->next)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT  - %s [%u] buf: %u/%u (qn %u/%u)\n",
-         GMC_2s (iterc->c), GMC_get_state (iterc->c),
-         GMC_get_buffer (iterc->c, GNUNET_YES),
-         GMC_get_buffer (iterc->c, GNUNET_NO),
-         GMC_get_qn (iterc->c, GNUNET_YES),
-         GMC_get_qn (iterc->c, GNUNET_NO));
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT DEBUG TUNNEL END\n");
-}
-
-
-/**
- * Iterate all tunnels.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
-{
-  GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls);
-}
-
-
-/**
- * Count all tunnels.
- *
- * @return Number of tunnels to remote peers kept by this peer.
- */
-unsigned int
-GMT_count_all (void)
-{
-  return GNUNET_CONTAINER_multipeermap_size (tunnels);
-}
-
-
-/**
- * Iterate all connections of a tunnel.
- *
- * @param t Tunnel whose connections to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMT_iterate_connections (struct CadetTunnel3 *t, GMT_conn_iter iter, void *cls)
-{
-  struct CadetTConnection *ct;
-
-  for (ct = t->connection_head; NULL != ct; ct = ct->next)
-    iter (cls, ct->c);
-}
-
-
-/**
- * Iterate all channels of a tunnel.
- *
- * @param t Tunnel whose channels to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMT_iterate_channels (struct CadetTunnel3 *t, GMT_chan_iter iter, void *cls)
-{
-  struct CadetTChannel *cht;
-
-  for (cht = t->channel_head; NULL != cht; cht = cht->next)
-    iter (cls, cht->ch);
-}

Deleted: gnunet/src/mesh/gnunet-service-cadet_tunnel.h
===================================================================
--- gnunet/src/mesh/gnunet-service-cadet_tunnel.h       2014-05-07 12:07:02 UTC 
(rev 33185)
+++ gnunet/src/mesh/gnunet-service-cadet_tunnel.h       2014-05-07 12:07:16 UTC 
(rev 33186)
@@ -1,531 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_tunnel.h
- * @brief cadet service; dealing with tunnels and crypto
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMT (Gnunet Cadet Tunnel)
- */
-
-#ifndef GNUNET_SERVICE_CADET_TUNNEL_H
-#define GNUNET_SERVICE_CADET_TUNNEL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-/**
- * All the connectivity states a tunnel can be in.
- */
-enum CadetTunnel3CState
-{
-    /**
-     * Uninitialized status, should never appear in operation.
-     */
-  CADET_TUNNEL3_NEW,
-
-    /**
-     * Path to the peer not known yet.
-     */
-  CADET_TUNNEL3_SEARCHING,
-
-    /**
-     * Request sent, not yet answered.
-     */
-  CADET_TUNNEL3_WAITING,
-
-    /**
-     * Peer connected and ready to accept data.
-     */
-  CADET_TUNNEL3_READY,
-
-  /**
-   * Tunnel being shut down, don't try to keep it alive.
-   */
-  CADET_TUNNEL3_SHUTDOWN
-};
-
-
-/**
- * All the encryption states a tunnel can be in.
- */
-enum CadetTunnel3EState
-{
-  /**
-   * Uninitialized status, should never appear in operation.
-   */
-  CADET_TUNNEL3_KEY_UNINITIALIZED,
-
-  /**
-   * Ephemeral key sent, waiting for peer's key.
-   */
-  CADET_TUNNEL3_KEY_SENT,
-
-  /**
-   * New ephemeral key and ping sent, waiting for pong.
-   * This means that we DO have the peer's ephemeral key, otherwise the
-   * state would be KEY_SENT.
-   */
-  CADET_TUNNEL3_KEY_PING,
-
-  /**
-   * Handshake completed: session key available.
-   */
-  CADET_TUNNEL3_KEY_OK,
-};
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct CadetTunnel3;
-
-
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_peer.h"
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetTunnel3Queue;
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param t Tunnel this message was on.
- * @param type Type of message sent.
- * @param size Size of the message.
- */
-typedef void (*GMT_sent) (void *cls,
-                          struct CadetTunnel3 *t,
-                          struct CadetTunnel3Queue *q,
-                          uint16_t type, size_t size);
-
-typedef void (*GMT_conn_iter) (void *cls, struct CadetConnection *c);
-typedef void (*GMT_chan_iter) (void *cls, struct CadetChannel *ch);
-
-
-/******************************************************************************/
-/********************************    API    
***********************************/
-/******************************************************************************/
-
-/**
- * Initialize tunnel subsystem.
- *
- * @param c Configuration handle.
- * @param key ECC private key, to derive all other keys and do crypto.
- */
-void
-GMT_init (const struct GNUNET_CONFIGURATION_Handle *c,
-          const struct GNUNET_CRYPTO_EddsaPrivateKey *key);
-
-/**
- * Shut down the tunnel subsystem.
- */
-void
-GMT_shutdown (void);
-
-/**
- * Create a tunnel.
- *
- * @param destination Peer this tunnel is towards.
- */
-struct CadetTunnel3 *
-GMT_new (struct CadetPeer *destination);
-
-/**
- * Tunnel is empty: destroy it.
- *
- * Notifies all connections about the destruction.
- *
- * @param t Tunnel to destroy.
- */
-void
-GMT_destroy_empty (struct CadetTunnel3 *t);
-
-/**
- * Destroy tunnel if empty (no more channels).
- *
- * @param t Tunnel to destroy if empty.
- */
-void
-GMT_destroy_if_empty (struct CadetTunnel3 *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.
- */
-void
-GMT_destroy (struct CadetTunnel3 *t);
-
-
-/**
- * Change the tunnel's connection state.
- *
- * @param t Tunnel whose connection state to change.
- * @param cstate New connection state.
- */
-void
-GMT_change_cstate (struct CadetTunnel3* t, enum CadetTunnel3CState cstate);
-
-
-/**
- * Change the tunnel encryption state.
- *
- * @param t Tunnel whose encryption state to change.
- * @param state New encryption state.
- */
-void
-GMT_change_estate (struct CadetTunnel3* t, enum CadetTunnel3EState state);
-
-/**
- * Add a connection to a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GMT_add_connection (struct CadetTunnel3 *t, struct CadetConnection *c);
-
-/**
- * Mark a path as no longer valid for this tunnel: has been tried and failed.
- *
- * @param t Tunnel to update.
- * @param path Invalid path to remove. Is destroyed after removal.
- */
-void
-GMT_remove_path (struct CadetTunnel3 *t, struct CadetPeerPath *path);
-
-/**
- * Remove a connection from a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GMT_remove_connection (struct CadetTunnel3 *t, struct CadetConnection *c);
-
-/**
- * Add a channel to a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GMT_add_channel (struct CadetTunnel3 *t, struct CadetChannel *ch);
-
-/**
- * Remove a channel from a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GMT_remove_channel (struct CadetTunnel3 *t, struct CadetChannel *ch);
-
-/**
- * Search for a channel by global ID.
- *
- * @param t Tunnel containing the channel.
- * @param chid Public channel number.
- *
- * @return channel handler, NULL if doesn't exist
- */
-struct CadetChannel *
-GMT_get_channel (struct CadetTunnel3 *t, CADET_ChannelNumber chid);
-
-/**
- * Decrypt and demultiplex by message type. Call appropriate handler
- * for a message
- * towards a channel of a local tunnel.
- *
- * @param t Tunnel this message came on.
- * @param msg Message header.
- */
-void
-GMT_handle_encrypted (struct CadetTunnel3 *t,
-                      const struct GNUNET_CADET_Encrypted *msg);
-
-/**
- * Demultiplex an encapsulated KX message by message type.
- *
- * @param t Tunnel on which the message came.
- * @param message KX message itself.
- */
-void
-GMT_handle_kx (struct CadetTunnel3 *t,
-               const struct GNUNET_MessageHeader *message);
-
-/**
- * @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.
- */
-struct CadetConnection *
-GMT_use_path (struct CadetTunnel3 *t, struct CadetPeerPath *p);
-
-/**
- * Count established (ready) connections of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of connections.
- */
-unsigned int
-GMT_count_connections (struct CadetTunnel3 *t);
-
-/**
- * Count channels of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of channels.
- */
-unsigned int
-GMT_count_channels (struct CadetTunnel3 *t);
-
-/**
- * Get the connectivity state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's connectivity state.
- */
-enum CadetTunnel3CState
-GMT_get_cstate (struct CadetTunnel3 *t);
-
-/**
- * Get the encryption state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's encryption state.
- */
-enum CadetTunnel3EState
-GMT_get_estate (struct CadetTunnel3 *t);
-
-/**
- * Get the maximum buffer space for a tunnel towards a local client.
- *
- * @param t Tunnel.
- *
- * @return Biggest buffer space offered by any channel in the tunnel.
- */
-unsigned int
-GMT_get_channels_buffer (struct CadetTunnel3 *t);
-
-/**
- * Get the total buffer space for a tunnel for P2P traffic.
- *
- * @param t Tunnel.
- *
- * @return Buffer space offered by all connections in the tunnel.
- */
-unsigned int
-GMT_get_connections_buffer (struct CadetTunnel3 *t);
-
-/**
- * Get the tunnel's destination.
- *
- * @param t Tunnel.
- *
- * @return ID of the destination peer.
- */
-const struct GNUNET_PeerIdentity *
-GMT_get_destination (struct CadetTunnel3 *t);
-
-/**
- * Get the tunnel's next free Channel ID.
- *
- * @param t Tunnel.
- *
- * @return ID of a channel free to use.
- */
-CADET_ChannelNumber
-GMT_get_next_chid (struct CadetTunnel3 *t);
-
-/**
- * Send ACK on one or more channels due to buffer in connections.
- *
- * @param t Channel which has some free buffer space.
- */
-void
-GMT_unchoke_channels (struct CadetTunnel3 *t);
-
-/**
- * Send ACK on one or more connections due to buffer space to the client.
- *
- * Iterates all connections of the tunnel and sends ACKs appropriately.
- *
- * @param t Tunnel which has some free buffer space.
- */
-void
-GMT_send_connection_acks (struct CadetTunnel3 *t);
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GMT_cancel (struct CadetTunnel3Queue *q);
-
-/**
- * Sends an already built message on a tunnel, encrypting it and
- * choosing the best connection.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param c Connection to use (autoselect if NULL).
- * @param force Force the tunnel to take the message (buffer overfill).
- * @param cont Continuation to call once message is really sent.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel message. NULL if @c cont is NULL.
- */
-struct CadetTunnel3Queue *
-GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           struct CadetTunnel3 *t, struct CadetConnection *c,
-                           int force, GMT_sent cont, void *cont_cls);
-
-/**
- * Is the tunnel directed towards the local peer?
- *
- * @param t Tunnel.
- *
- * @return #GNUNET_YES if it is loopback.
- */
-int
-GMT_is_loopback (const struct CadetTunnel3 *t);
-
-/**
- * Is the tunnel using this path already?
- *
- * @param t Tunnel.
- * @param p Path.
- *
- * @return #GNUNET_YES a connection uses this path.
- */
-int
-GMT_is_path_used (const struct CadetTunnel3 *t, const struct CadetPeerPath *p);
-
-/**
- * Get a cost of a path for a tunnel considering existing connections.
- *
- * @param t Tunnel.
- * @param path Candidate path.
- *
- * @return Cost of the path (path length + number of overlapping nodes)
- */
-unsigned int
-GMT_get_path_cost (const struct CadetTunnel3 *t,
-                   const struct CadetPeerPath *path);
-
-/**
- * Get the static string for the peer this tunnel is directed.
- *
- * @param t Tunnel.
- *
- * @return Static string the destination peer's ID.
- */
-const char *
-GMT_2s (const struct CadetTunnel3 *t);
-
-/**
- * Log all possible info about the tunnel state.
- *
- * @param t Tunnel to debug.
- */
-void
-GMT_debug (const struct CadetTunnel3 *t);
-
-/**
- * Iterate all tunnels.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
-
-/**
- * Count all tunnels.
- *
- * @return Number of tunnels to remote peers kept by this peer.
- */
-unsigned int
-GMT_count_all (void);
-
-/**
- * Iterate all connections of a tunnel.
- *
- * @param t Tunnel whose connections to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMT_iterate_connections (struct CadetTunnel3 *t, GMT_conn_iter iter, void 
*cls);
-
-/**
- * Iterate all channels of a tunnel.
- *
- * @param t Tunnel whose channels to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GMT_iterate_channels (struct CadetTunnel3 *t, GMT_chan_iter iter, void *cls);
-
-#if 0                           /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_TUNNEL_H */
-#endif
-/* end of gnunet-cadet-service_tunnel.h */

Deleted: gnunet/src/mesh/loopcheck.sh
===================================================================
--- gnunet/src/mesh/loopcheck.sh        2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/loopcheck.sh        2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-while true; do
-    date;
-    taskset 1 make check || break;
-    grep -B 10 Assert *log && break
-    ls core* &> /dev/null && break
-done

Deleted: gnunet/src/mesh/mesh.conf.in
===================================================================
--- gnunet/src/mesh/mesh.conf.in        2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/mesh.conf.in        2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,21 +0,0 @@
-[mesh]
-AUTOSTART = @AUTOSTART@
address@hidden@PORT = 2096
-HOSTNAME = localhost
-BINARY = gnunet-service-mesh
-ACCEPT_FROM = 127.0.0.1;
-ACCEPT_FROM6 = ::1;
-UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-mesh.sock
-UNIX_MATCH_UID = YES
-UNIX_MATCH_GID = YES
-REFRESH_CONNECTION_TIME = 5 min
-ID_ANNOUNCE_TIME = 1 h
-APP_ANNOUNCE_TIME = 1 h
-CONNECT_TIMEOUT = 30 s
-DEFAULT_TTL = 64
-DHT_REPLICATION_LEVEL = 3
-MAX_TUNNELS = 1000
-# MAX_TUNNELS deprecated
-MAX_CONNECTIONS = 1000
-MAX_MSGS_QUEUE = 10000
-MAX_PEERS = 1000

Deleted: gnunet/src/mesh/profiler.conf
===================================================================
--- gnunet/src/mesh/profiler.conf       2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/profiler.conf       2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,19 +0,0 @@
address@hidden@ test_mesh.conf
-
-[testbed]
-OVERLAY_TOPOLOGY = RANDOM
-OVERLAY_RANDOM_LINKS = %LINKS%
-MAX_PARALLEL_SERVICE_CONNECTIONS=4000
-SETUP_TIMEOUT = 60 m
-
-[transport]
-#MANIPULATE_DELAY_IN = 50 ms
-MANIPULATE_DELAY_OUT = 10 ms
-
-[mesh]
-REFRESH_CONNECTION_TIME = 1 h
-DISABLE_TRY_CONNECT = YES
-ID_ANNOUNCE_TIME = 240 s
-
-[dht]
-FORCE_NSE = %NSE%

Deleted: gnunet/src/mesh/run_profiler.sh
===================================================================
--- gnunet/src/mesh/run_profiler.sh     2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/run_profiler.sh     2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-if [ "$#" -lt "3" ]; then
-    echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS";
-    echo "example: $0 30s 16 1";
-    exit 1;
-fi
-
-ROUNDTIME=$1
-PEERS=$2
-PINGS=$3
-
-if [ $PEERS -eq 1 ]; then
-    echo "cannot run 1 peer";
-    exit 1;
-fi
-
-LINKS=`echo "l($PEERS)/l(2) * $PEERS" | bc -l`
-LINKS=`printf "%.0f" $LINKS`
-NSE=`echo "l($PEERS)/l(2)" | bc -l`
-echo "using $PEERS peers, $LINKS links";
-    
-sed -e "s/%LINKS%/$LINKS/;s/%NSE%/$NSE/" profiler.conf > .profiler.conf
-
-./gnunet-mesh-profiler $ROUNDTIME $PEERS $PINGS $4 |& tee log | grep -v DEBUG

Deleted: gnunet/src/mesh/small.dat
===================================================================
--- gnunet/src/mesh/small.dat   2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/small.dat   2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,21 +0,0 @@
-16
-1:2
-1:9
-2:3
-3:4
-3:11
-4:5
-5:6
-5:13
-6:7
-7:8
-7:15
-8:9
-9:10
-10:11
-11:12
-12:13
-13:14
-14:15
-15:16
-16:1

Deleted: gnunet/src/mesh/test_cadet.c
===================================================================
--- gnunet/src/mesh/test_cadet.c        2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/test_cadet.c        2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,953 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file cadet/test_cadet.c
- *
- * @brief Test for the cadet service: retransmission of traffic.
- */
-#include <stdio.h>
-#include "platform.h"
-#include "cadet_test_lib.h"
-#include "gnunet_cadet_service.h"
-#include "gnunet_statistics_service.h"
-#include <gauger.h>
-
-
-/**
- * How namy messages to send
- */
-#define TOTAL_PACKETS 100
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
-
-/**
- * Time to wait for stuff that should be rather fast
- */
-#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-
-/**
- * DIFFERENT TESTS TO RUN
- */
-#define SETUP 0
-#define FORWARD 1
-#define KEEPALIVE 2
-#define SPEED 3
-#define SPEED_ACK 4
-#define SPEED_REL 8
-#define P2P_SIGNAL 10
-
-/**
- * Which test are we running?
- */
-static int test;
-
-/**
- * String with test name
- */
-char *test_name;
-
-/**
- * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
- */
-static int test_backwards = GNUNET_NO;
-
-/**
- * How many events have happened
- */
-static int ok;
-
-/**
- * Number of events expected to conclude the test successfully.
- */
-int ok_goal;
-
-/**
- * Size of each test packet
- */
-size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
-
-/**
- * Operation to get peer ids.
- */
-struct GNUNET_TESTBED_Operation *t_op[2];
-
-/**
- * Peer ids.
- */
-struct GNUNET_PeerIdentity *p_id[2];
-
-/**
- * Peer ids counter.
- */
-unsigned int p_ids;
-
-/**
- * Is the setup initialized?
- */
-static int initialized;
-
-/**
- * Number of payload packes sent
- */
-static int data_sent;
-
-/**
- * Number of payload packets received
- */
-static int data_received;
-
-/**
- * Number of payload packed explicitly (app level) acknowledged
- */
-static int data_ack;
-
-/**
- * Total number of currently running peers.
- */
-static unsigned long long peers_running;
-
-/**
- * Test context (to shut down).
- */
-struct GNUNET_CADET_TEST_Context *test_ctx;
-
-/**
- * Task called to disconnect peers.
- */
-static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-/**
- * Task To perform tests
- */
-static GNUNET_SCHEDULER_TaskIdentifier test_task;
-
-/**
- * Task called to shutdown test.
- */
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
-
-/**
- * Cadet handle for the root peer
- */
-static struct GNUNET_CADET_Handle *h1;
-
-/**
- * Cadet handle for the first leaf peer
- */
-static struct GNUNET_CADET_Handle *h2;
-
-/**
- * Channel handle for the root peer
- */
-static struct GNUNET_CADET_Channel *ch;
-
-/**
- * Channel handle for the dest peer
- */
-static struct GNUNET_CADET_Channel *incoming_ch;
-
-/**
- * Time we started the data transmission (after channel has been established
- * and initilized).
- */
-static struct GNUNET_TIME_Absolute start_time;
-
-/**
- * Peers handle.
- */
-static struct GNUNET_TESTBED_Peer **testbed_peers;
-
-/**
- * Statistics operation handle.
- */
-static struct GNUNET_TESTBED_Operation *stats_op;
-
-/**
- * Keepalives sent.
- */
-static unsigned int ka_sent;
-
-/**
- * Keepalives received.
- */
-static unsigned int ka_received;
-
-
-/**
- * Show the results of the test (banwidth acheived) and log them to GAUGER
- */
-static void
-show_end_data (void)
-{
-  static struct GNUNET_TIME_Absolute end_time;
-  static struct GNUNET_TIME_Relative total_time;
-
-  end_time = GNUNET_TIME_absolute_get();
-  total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time);
-  FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name);
-  FPRINTF (stderr, "Test time %s\n",
-          GNUNET_STRINGS_relative_time_to_string (total_time,
-                                                  GNUNET_YES));
-  FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
-          4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 
4bytes * ms
-  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
-          TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // 
packets * ms
-  GAUGER ("CADET", test_name,
-          TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000),
-          "packets/s");
-}
-
-
-/**
- * Shut down peergroup, clean up.
- *
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n");
-  shutdown_handle = GNUNET_SCHEDULER_NO_TASK;
-}
-
-
-/**
- * Disconnect from cadet services af all peers, call shutdown.
- *
- * @param cls Closure (unused).
- * @param tc Task Context.
- */
-static void
-disconnect_cadet_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
-{
-  long line = (long) cls;
-  unsigned int i;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "disconnecting cadet service of peers, called from line %ld\n",
-              line);
-  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  for (i = 0; i < 2; i++)
-  {
-    GNUNET_TESTBED_operation_done (t_op[i]);
-  }
-  if (NULL != ch)
-  {
-    GNUNET_CADET_channel_destroy (ch);
-    ch = NULL;
-  }
-  if (NULL != incoming_ch)
-  {
-    GNUNET_CADET_channel_destroy (incoming_ch);
-    incoming_ch = NULL;
-  }
-  GNUNET_CADET_TEST_cleanup (test_ctx);
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_handle);
-  }
-  shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
-}
-
-
-/**
- * Abort test: schedule disconnect and shutdown immediately
- *
- * @param line Line in the code the abort is requested from (__LINE__).
- */
-static void
-abort_test (long line)
-{
-  if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
-                                                (void *) line);
-  }
-}
-
-/**
- * Transmit ready callback.
- *
- * @param cls Closure (message type).
- * @param size Size of the tranmist buffer.
- * @param buf Pointer to the beginning of the buffer.
- *
- * @return Number of bytes written to buf.
- */
-static size_t
-tmt_rdy (void *cls, size_t size, void *buf);
-
-
-/**
- * Task to schedule a new data transmission.
- *
- * @param cls Closure (peer #).
- * @param tc Task Context.
- */
-static void
-data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CADET_TransmitHandle *th;
-  struct GNUNET_CADET_Channel *channel;
-
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n");
-  if (GNUNET_YES == test_backwards)
-  {
-    channel = incoming_ch;
-  }
-  else
-  {
-    channel = ch;
-  }
-  th = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
-                                          GNUNET_TIME_UNIT_FOREVER_REL,
-                                          size_payload, &tmt_rdy, (void *) 1L);
-  if (NULL == th)
-  {
-    unsigned long i = (unsigned long) cls;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n");
-    if (0 == i)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
-                                    &data_task, (void *)1UL);
-    }
-    else
-    {
-      i++;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i);
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(
-                                      GNUNET_TIME_UNIT_MILLISECONDS,
-                                      i),
-                                    &data_task, (void *)i);
-    }
-  }
-}
-
-
-/**
- * Transmit ready callback
- *
- * @param cls Closure (message type).
- * @param size Size of the buffer we have.
- * @param buf Buffer to copy data to.
- */
-size_t
-tmt_rdy (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *msg = buf;
-  uint32_t *data;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "tmt_rdy called, filling buffer\n");
-  if (size < size_payload || NULL == buf)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "size %u, buf %p, data_sent %u, data_received %u\n",
-                size, buf, data_sent, data_received);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal);
-    GNUNET_break (ok >= ok_goal - 2);
-
-    return 0;
-  }
-  msg->size = htons (size);
-  msg->type = htons ((long) cls);
-  data = (uint32_t *) &msg[1];
-  *data = htonl (data_sent);
-  if (GNUNET_NO == initialized)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "sending initializer\n");
-  }
-  else if (SPEED == test)
-  {
-    data_sent++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Sent packet %d\n", data_sent);
-    if (data_sent < TOTAL_PACKETS)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " Scheduling packet %d\n", data_sent + 1);
-      GNUNET_SCHEDULER_add_now (&data_task, NULL);
-    }
-  }
-
-  return size_payload;
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_CADET_connect)
- * @param channel connection to the other end
- * @param channel_ctx place to store local state associated with the channel
- * @param message the actual message
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-int
-data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
-               void **channel_ctx,
-               const struct GNUNET_MessageHeader *message)
-{
-  long client = (long) cls;
-  long expected_target_client;
-  uint32_t *data;
-
-  ok++;
-
-  GNUNET_CADET_receive_done (channel);
-
-  if ((ok % 20) == 0)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    {
-      GNUNET_SCHEDULER_cancel (disconnect_task);
-      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                      &disconnect_cadet_peers,
-                                                      (void *) __LINE__);
-    }
-  }
-
-  switch (client)
-  {
-  case 0L:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
-    break;
-  case 4L:
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Leaf client %li got a message.\n",
-                client);
-    break;
-  default:
-    GNUNET_assert (0);
-    break;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
-  data = (uint32_t *) &message[1];
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data));
-  if (SPEED == test && GNUNET_YES == test_backwards)
-  {
-    expected_target_client = 0L;
-  }
-  else
-  {
-    expected_target_client = 4L;
-  }
-
-  if (GNUNET_NO == initialized)
-  {
-    initialized = GNUNET_YES;
-    start_time = GNUNET_TIME_absolute_get ();
-    if (SPEED == test)
-    {
-      GNUNET_assert (4L == client);
-      GNUNET_SCHEDULER_add_now (&data_task, NULL);
-      return GNUNET_OK;
-    }
-  }
-
-  if (client == expected_target_client) // Normally 4
-  {
-    data_received++;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
-    if (SPEED != test || (ok_goal - 2) == ok)
-    {
-      GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         size_payload, &tmt_rdy, (void *) 1L);
-      return GNUNET_OK;
-    }
-    else
-    {
-      if (data_received < TOTAL_PACKETS)
-        return GNUNET_OK;
-    }
-  }
-  else // Normally 0
-  {
-    if (test == SPEED_ACK || test == SPEED)
-    {
-      data_ack++;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", data_ack);
-      GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
-                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                         size_payload, &tmt_rdy, (void *) 1L);
-      if (data_ack < TOTAL_PACKETS && SPEED != test)
-        return GNUNET_OK;
-      if (ok == 2 && SPEED == test)
-        return GNUNET_OK;
-      show_end_data();
-    }
-    if (test == P2P_SIGNAL)
-    {
-      GNUNET_CADET_channel_destroy (incoming_ch);
-      incoming_ch = NULL;
-    }
-    else
-    {
-      GNUNET_CADET_channel_destroy (ch);
-      ch = NULL;
-    }
-  }
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                    &disconnect_cadet_peers,
-                                                    (void *) __LINE__);
-  }
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Stats callback. Finish the stats testbed operation and when all stats have
- * been iterated, shutdown the test.
- *
- * @param cls closure
- * @param op the operation that has been finished
- * @param emsg error message in case the operation has failed; will be NULL if
- *          operation has executed successfully.
- */
-static void
-stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stats_cont for peer %u\n", cls);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " sent: %u, received: %u\n",
-              ka_sent, ka_received);
-  if (ka_sent < 2 || ka_sent > ka_received + 1)
-    ok--;
-  GNUNET_TESTBED_operation_done (stats_op);
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
-                                              (void *) __LINE__);
-
-}
-
-
-/**
- * Process statistic values.
- *
- * @param cls closure
- * @param peer the peer the statistic belong to
- * @param subsystem name of subsystem that created the statistic
- * @param name the name of the datum
- * @param value the current value
- * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
- * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
- */
-static int
-stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer,
-                const char *subsystem, const char *name,
-                uint64_t value, int is_persistent)
-{
-  static const char *s_sent = "# keepalives sent";
-  static const char *s_recv = "# keepalives received";
-  uint32_t i;
-
-  i = GNUNET_TESTBED_get_index (peer);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  %u - %s [%s]: %llu\n",
-              i, subsystem, name, value);
-  if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i)
-    ka_sent = value;
-
-  if (0 == strncmp(s_recv, name, strlen (s_recv)) && 4 == i)
-    ka_received = value;
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Task check that keepalives were sent and received.
- *
- * @param cls Closure (NULL).
- * @param tc Task Context.
- */
-static void
-check_keepalives (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "check keepalives\n");
-  GNUNET_CADET_channel_destroy (ch);
-  stats_op = GNUNET_TESTBED_get_statistics (5, testbed_peers,
-                                            "cadet", NULL,
-                                            stats_iterator, stats_cont, NULL);
-}
-
-
-/**
- * Handlers, for diverse services
- */
-static struct GNUNET_CADET_MessageHandler handlers[] = {
-  {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Method called whenever another peer has added us to a channel
- * the other peer initiated.
- *
- * @param cls Closure.
- * @param channel New handle to the channel.
- * @param initiator Peer that started the channel.
- * @param port Port this channel is connected to.
- * @param options channel option flags
- * @return Initial channel context for the channel
- *         (can be NULL -- that's not an error).
- */
-static void *
-incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel,
-                 const struct GNUNET_PeerIdentity *initiator,
-                 uint32_t port, enum GNUNET_CADET_ChannelOption options)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming channel from %s to peer %d\n",
-              GNUNET_i2s (initiator), (long) cls);
-  ok++;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-  if ((long) cls == 4L)
-    incoming_ch = channel;
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Incoming channel for unknown client %lu\n", (long) cls);
-    GNUNET_break(0);
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    if (KEEPALIVE == test)
-    {
-      struct GNUNET_TIME_Relative delay;
-      delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS , 5);
-      disconnect_task =
-        GNUNET_SCHEDULER_add_delayed (delay, &check_keepalives, NULL);
-    }
-    else
-      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                      &disconnect_cadet_peers,
-                                                      (void *) __LINE__);
-  }
-
-  return NULL;
-}
-
-/**
- * Function called whenever an inbound channel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_CADET_connect)
- * @param channel connection to the other end (henceforth invalid)
- * @param channel_ctx place where local state associated
- *                   with the channel is stored
- */
-static void
-channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel,
-                 void *channel_ctx)
-{
-  long i = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Incoming channel disconnected at peer %ld\n", i);
-  if (4L == i)
-  {
-    ok++;
-    GNUNET_break (channel == incoming_ch);
-    incoming_ch = NULL;
-  }
-  else if (0L == i)
-  {
-    if (P2P_SIGNAL == test)
-    {
-      ok ++;
-    }
-    GNUNET_break (channel == ch);
-    ch = NULL;
-  }
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Unknown peer! %d\n", i);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok);
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
-                                                (void *) __LINE__);
-  }
-
-  return;
-}
-
-
-/**
- * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
- *
- * Testcase continues when the root receives confirmation of connected peers,
- * on callback funtion ch.
- *
- * @param cls Closure (unsued).
- * @param tc Task Context.
- */
-static void
-do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  enum GNUNET_CADET_ChannelOption flags;
-
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n");
-
-  if (GNUNET_SCHEDULER_NO_TASK != disconnect_task)
-  {
-    GNUNET_SCHEDULER_cancel (disconnect_task);
-  }
-
-  flags = GNUNET_CADET_OPTION_DEFAULT;
-  if (SPEED_REL == test)
-  {
-    test = SPEED;
-    flags |= GNUNET_CADET_OPTION_RELIABLE;
-  }
-  ch = GNUNET_CADET_channel_create (h1, NULL, p_id[1], 1, flags);
-
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_cadet_peers,
-                                                  (void *) __LINE__);
-  if (KEEPALIVE == test)
-    return; /* Don't send any data. */
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending data initializer...\n");
-  data_ack = 0;
-  data_received = 0;
-  data_sent = 0;
-  GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     size_payload, &tmt_rdy, (void *) 1L);
-}
-
-/**
- * Callback to be called when the requested peer information is available
- *
- * @param cls the closure from GNUNET_TESTBED_peer_get_information()
- * @param op the operation this callback corresponds to
- * @param pinfo the result; will be NULL if the operation has failed
- * @param emsg error message if the operation has failed;
- *             NULL if the operation is successfull
- */
-static void
-pi_cb (void *cls,
-       struct GNUNET_TESTBED_Operation *op,
-       const struct GNUNET_TESTBED_PeerInformation *pinfo,
-       const char *emsg)
-{
-  long i = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i);
-
-  if (NULL == pinfo || NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
-    abort_test (__LINE__);
-    return;
-  }
-  p_id[i] = pinfo->result.id;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  id: %s\n", GNUNET_i2s (p_id[i]));
-  p_ids++;
-  if (p_ids < 2)
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n");
-  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                            &do_test, NULL);
-}
-
-/**
- * test main: start test when all peers are connected
- *
- * @param cls Closure.
- * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
- * @param num_peers Number of peers that are running.
- * @param peers Array of peers.
- * @param cadetes Handle to each of the CADETs of the peers.
- */
-static void
-tmain (void *cls,
-       struct GNUNET_CADET_TEST_Context *ctx,
-       unsigned int num_peers,
-       struct GNUNET_TESTBED_Peer **peers,
-       struct GNUNET_CADET_Handle **cadetes)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n");
-  ok = 0;
-  test_ctx = ctx;
-  peers_running = num_peers;
-  testbed_peers = peers;
-  h1 = cadetes[0];
-  h2 = cadetes[num_peers - 1];
-  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
-                                                  &disconnect_cadet_peers,
-                                                  (void *) __LINE__);
-  shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                                  &shutdown_task, NULL);
-  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
-                                                 GNUNET_TESTBED_PIT_IDENTITY,
-                                                 &pi_cb, (void *) 0L);
-  t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
-                                                 GNUNET_TESTBED_PIT_IDENTITY,
-                                                 &pi_cb, (void *) 1L);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
-}
-
-
-/**
- * Main: start test
- */
-int
-main (int argc, char *argv[])
-{
-  initialized = GNUNET_NO;
-  static uint32_t ports[2];
-  const char *config_file;
-
-  GNUNET_log_setup ("test", "DEBUG", NULL);
-  config_file = "test_cadet.conf";
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n");
-  if (strstr (argv[0], "_cadet_forward") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n");
-    test = FORWARD;
-    test_name = "unicast";
-    ok_goal = 4;
-  }
-  else if (strstr (argv[0], "_cadet_signal") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n");
-    test = P2P_SIGNAL;
-    test_name = "signal";
-    ok_goal = 4;
-  }
-  else if (strstr (argv[0], "_cadet_speed_ack") != NULL)
-  {
-    /* Test is supposed to generate the following callbacks:
-     * 1 incoming channel (@dest)
-     * TOTAL_PACKETS received data packet (@dest)
-     * TOTAL_PACKETS received data packet (@orig)
-     * 1 received channel destroy (@dest)
-     */
-    ok_goal = TOTAL_PACKETS * 2 + 2;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n");
-    test = SPEED_ACK;
-    test_name = "speed ack";
-  }
-  else if (strstr (argv[0], "_cadet_speed") != NULL)
-  {
-    /* Test is supposed to generate the following callbacks:
-     * 1 incoming channel (@dest)
-     * 1 initial packet (@dest)
-     * TOTAL_PACKETS received data packet (@dest)
-     * 1 received data packet (@orig)
-     * 1 received channel destroy (@dest)
-     */
-    ok_goal = TOTAL_PACKETS + 4;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n");
-    if (strstr (argv[0], "_reliable") != NULL)
-    {
-      test = SPEED_REL;
-      test_name = "speed reliable";
-      config_file = "test_cadet_drop.conf";
-    }
-    else
-    {
-      test = SPEED;
-      test_name = "speed";
-    }
-  }
-  else if (strstr (argv[0], "_keepalive") != NULL)
-  {
-    test = KEEPALIVE;
-    /* Test is supposed to generate the following callbacks:
-     * 1 incoming channel (@dest)
-     * [wait]
-     * 1 received channel destroy (@dest)
-     */
-    ok_goal = 2;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
-    test = SETUP;
-    ok_goal = 0;
-  }
-
-  if (strstr (argv[0], "backwards") != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n");
-    test_backwards = GNUNET_YES;
-    GNUNET_asprintf (&test_name, "backwards %s", test_name);
-  }
-
-  p_ids = 0;
-  ports[0] = 1;
-  ports[1] = 0;
-  GNUNET_CADET_TEST_run ("test_cadet_small",
-                        config_file,
-                        5,
-                        &tmain,
-                        NULL, /* tmain cls */
-                        &incoming_channel,
-                        &channel_cleaner,
-                        handlers,
-                        ports);
-
-  if (ok_goal > ok)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "FAILED! (%d/%d)\n", ok, ok_goal);
-    return 1;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n");
-  return 0;
-}
-
-/* end of test_cadet.c */
-

Deleted: gnunet/src/mesh/test_cadet.conf
===================================================================
--- gnunet/src/mesh/test_cadet.conf     2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/test_cadet.conf     2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,100 +0,0 @@
-[testbed]
-AUTOSTART = NO
-PORT = 12113
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-OVERLAY_TOPOLOGY = LINE
-#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
-
-[fs]
-AUTOSTART = NO
-
-[resolver]
-AUTOSTART = NO
-
-[mesh]
-#BINARY = gnunet-service-mesh-enc
-#PREFIX = valgrind --leak-check=full
-#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
-AUTOSTART = NO
-ACCEPT_FROM = 127.0.0.1;
-REFRESH_CONNECTION_TIME = 2 s
-ID_ANNOUNCE_TIME = 5 s
-CONNECT_TIMEOUT = 30 s
-DEFAULT_TTL = 16
-DHT_REPLICATION_LEVEL = 10
-MAX_TUNNELS = 10
-MAX_CONNECTIONS = 10
-MAX_MSGS_QUEUE = 20
-DISABLE_TRY_CONNECT = YES
-
-[dht]
-AUTOSTART = NO
-DISABLE_TRY_CONNECT = YES
-FORCE_NSE = 3
-
-[dhtcache]
-QUOTA = 1 MB
-DATABASE = heap
-
-[transport]
-PLUGINS = udp
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-NEIGHBOUR_LIMIT = 50
-PORT = 12365
-#MANIPULATE_DELAY_IN = 10 ms
-#MANIPULATE_DELAY_OUT = 10 ms
-
-
-[ats]
-WAN_QUOTA_OUT = 3932160
-WAN_QUOTA_IN = 3932160
-
-[core]
-PORT = 12092
-AUTOSTART = YES
-USE_EPHEMERAL_KEYS = NO
-
-[arm]
-DEFAULTSERVICES = core transport dht mesh statistics
-PORT = 12366
-
-[transport-udp]
-TIMEOUT = 300 s
-PORT = 12368
-
-[gnunetd]
-HOSTKEY = $GNUNET_TEST_HOME/.hostkey
-
-[PATHS]
-GNUNET_TEST_HOME = /tmp/test-mesh/
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[vpn]
-AUTOSTART = NO
-
-[nat]
-RETURN_LOCAL_ADDRESSES = YES
-DISABLEV6 = YES
-USE_LOCALADDR = YES
-
-[gns-helper-service-w32]
-AUTOSTART = NO
-
-[consensus]
-AUTOSTART = NO
-
-[gns]
-AUTOSTART = NO
-
-[statistics]
-AUTOSTART = NO
-
-[peerinfo]
-NO_IO = YES

Deleted: gnunet/src/mesh/test_cadet_drop.conf
===================================================================
--- gnunet/src/mesh/test_cadet_drop.conf        2014-05-07 12:07:02 UTC (rev 
33185)
+++ gnunet/src/mesh/test_cadet_drop.conf        2014-05-07 12:07:16 UTC (rev 
33186)
@@ -1,4 +0,0 @@
address@hidden@ test_mesh.conf
-
-[mesh]
-DROP_PERCENT = 1

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

Deleted: gnunet/src/mesh/test_cadet_single.c
===================================================================
--- gnunet/src/mesh/test_cadet_single.c 2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/test_cadet_single.c 2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,329 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file cadet/test_cadet_single.c
- * @brief test cadet single: test of cadet channels with just one client
- * @author Bartlomiej Polot
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_dht_service.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_cadet_service.h"
-
-#define REPETITIONS 5
-#define DATA_SIZE 35000
-
-struct GNUNET_TESTING_Peer *me;
-
-static struct GNUNET_CADET_Handle *cadet;
-
-static struct GNUNET_CADET_Channel *ch1;
-
-static struct GNUNET_CADET_Channel *ch2;
-
-static int result;
-
-static GNUNET_SCHEDULER_TaskIdentifier abort_task;
-
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
-
-static unsigned int repetition;
-
-
-/* forward declaration */
-static size_t
-do_send (void *cls, size_t size, void *buf);
-
-
-/**
- * Shutdown nicely
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
-  if (GNUNET_SCHEDULER_NO_TASK != abort_task)
-  {
-    GNUNET_SCHEDULER_cancel (abort_task);
-  }
-  if (NULL != ch1)
-  {
-    GNUNET_CADET_channel_destroy (ch1);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n");
-  if (NULL != cadet)
-  {
-    GNUNET_CADET_disconnect (cadet);
-    cadet = NULL;
-  }
-  else
-  {
-    GNUNET_break (0);
-  }
-}
-
-
-/**
- * Something went wrong and timed out. Kill everything and set error flag
- */
-static void
-do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n");
-  result = GNUNET_SYSERR;
-  abort_task = GNUNET_SCHEDULER_NO_TASK;
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-    shutdown_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  do_shutdown (cls, tc);
-}
-
-
-static void
-finish (void)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_task)
-    GNUNET_SCHEDULER_cancel (shutdown_task);
-  shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                &do_shutdown, NULL);
-}
-
-
-/**
- * Function is called whenever a message is received.
- *
- * @param cls closure (set from GNUNET_CADET_connect)
- * @param channel connection to the other end
- * @param channel_ctx place to store local state associated with the channel
- * @param message the actual message
- *
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
-               void **channel_ctx,
-               const struct GNUNET_MessageHeader *message)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Data callback! Repetition %u/%u\n",
-              repetition, REPETITIONS);
-  repetition = repetition + 1;
-  if (repetition < REPETITIONS)
-  {
-    struct GNUNET_CADET_Channel *my_channel;
-    if (repetition % 2 == 0)
-      my_channel = ch1;
-    else
-      my_channel = ch2;
-    GNUNET_CADET_notify_transmit_ready (my_channel, GNUNET_NO,
-                                       GNUNET_TIME_UNIT_FOREVER_REL,
-                                       sizeof (struct GNUNET_MessageHeader)
-                                       + DATA_SIZE,
-                                       &do_send, NULL);
-    GNUNET_CADET_receive_done (channel);
-    return GNUNET_OK;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All data OK. Destroying channel.\n");
-  GNUNET_CADET_channel_destroy (ch1);
-  ch1 = NULL;
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called whenever another peer has added us to a channel
- * the other peer initiated.
- *
- * @param cls closure
- * @param channel new handle to the channel
- * @param initiator peer that started the channel
- * @param port port number
- * @param options channel option flags
- * @return initial channel context for the channel
- *         (can be NULL -- that's not an error)
- */
-static void *
-inbound_channel (void *cls, struct GNUNET_CADET_Channel *channel,
-                const struct GNUNET_PeerIdentity *initiator,
-                uint32_t port, enum GNUNET_CADET_ChannelOption options)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "received incoming channel on port %u\n",
-              port);
-  ch2 = channel;
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound channel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_CADET_connect)
- * @param channel connection to the other end (henceforth invalid)
- * @param channel_ctx place where local state associated
- *                   with the channel is stored
- */
-static void
-channel_end (void *cls, const struct GNUNET_CADET_Channel *channel,
-             void *channel_ctx)
-{
-  long id = (long) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "incoming channel closed at peer %ld\n",
-              id);
-  if (REPETITIONS == repetition && channel == ch2)
-  {
-    ch2 = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "everything fine! finishing!\n");
-    result = GNUNET_OK;
-    finish ();
-  }
-}
-
-
-/**
- * Handler array for traffic received on peer1
- */
-static struct GNUNET_CADET_MessageHandler handlers1[] = {
-  {&data_callback, 1, 0},
-  {NULL, 0, 0}
-};
-
-
-/**
- * Data send callback: fillbuffer with test packet.
- *
- * @param cls Closure (unused).
- * @param size Buffer size.
- * @param buf Buffer to fill.
- *
- * @return size of test packet.
- */
-static size_t
-do_send (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *m = buf;
-
-  if (NULL == buf)
-  {
-    GNUNET_break (0);
-    result = GNUNET_SYSERR;
-    return 0;
-  }
-  m->size = htons (sizeof (struct GNUNET_MessageHeader));
-  m->type = htons (1);
-  memset (&m[1], 0, DATA_SIZE);
-  GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader) + DATA_SIZE);
-  return sizeof (struct GNUNET_MessageHeader) + DATA_SIZE;
-}
-
-/**
- * Connect to other client and send data
- *
- * @param cls Closue (unused).
- * @param tc TaskContext.
- */
-static void
-do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_PeerIdentity id;
-  size_t size = sizeof (struct GNUNET_MessageHeader) + DATA_SIZE;
-
-  if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
-    return;
-
-  GNUNET_TESTING_peer_get_identity (me, &id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n");
-  ch1 = GNUNET_CADET_channel_create (cadet, NULL, &id, 1,
-                                    GNUNET_CADET_OPTION_DEFAULT);
-  GNUNET_CADET_notify_transmit_ready (ch1, GNUNET_NO,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     size, &do_send, NULL);
-}
-
-
-/**
- * Initialize framework and start test
- *
- * @param cls Closure (unused).
- * @param cfg Configuration handle.
- * @param peer Testing peer handle.
- */
-static void
-run (void *cls,
-     const struct GNUNET_CONFIGURATION_Handle *cfg,
-     struct GNUNET_TESTING_Peer *peer)
-{
-  static uint32_t ports[] = {1, 0};
-
-  me = peer;
-  abort_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort,
-                                    NULL);
-  cadet = GNUNET_CADET_connect (cfg,       /* configuration */
-                              (void *) 1L,     /* cls */
-                              &inbound_channel,   /* inbound new hndlr */
-                              &channel_end,      /* inbound end hndlr */
-                              handlers1, /* traffic handlers */
-                              ports);     /* ports offered */
-
-  if (NULL == cadet)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to cadet :(\n");
-    result = GNUNET_SYSERR;
-    return;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO CADET :D\n");
-  }
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_connect, NULL);
-}
-
-
-/**
- * Main
- */
-int
-main (int argc, char *argv[])
-{
-  result = GNUNET_NO;
-  if (0 != GNUNET_TESTING_peer_run ("test-cadet-local",
-                                    "test_cadet.conf",
-                                    &run, NULL))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n");
-    return 2;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result);
-  return (result == GNUNET_OK) ? 0 : 1;
-}
-
-/* end of test_cadet_single.c */

Deleted: gnunet/src/mesh/valgrind-mesh.supp
===================================================================
--- gnunet/src/mesh/valgrind-mesh.supp  2014-05-07 12:07:02 UTC (rev 33185)
+++ gnunet/src/mesh/valgrind-mesh.supp  2014-05-07 12:07:16 UTC (rev 33186)
@@ -1,116 +0,0 @@
-{
-   logsetup_addr
-   Memcheck:Addr8
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:get_type
-   fun:GNUNET_log_setup
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   scanf_addr
-   Memcheck:Addr8
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:vsscanf
-   fun:sscanf
-   fun:GNUNET_CONFIGURATION_get_value_number
-   fun:GNUNET_SERVICE_get_server_addresses
-   fun:setup_service
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   mylog_addr
-   Memcheck:Addr8
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:service_task
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   mylog_uninit
-   Memcheck:Value8
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:mylog
-   fun:GNUNET_log_from_nocheck
-   fun:service_task
-   ...
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   mylog_from_cond
-   Memcheck:Cond
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:mylog
-   fun:GNUNET_log_from_nocheck
-   ...
-   fun:service_task
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   mylog_cond
-   Memcheck:Cond
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:mylog
-   fun:GNUNET_log_nocheck
-   ...
-   fun:service_task
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   inet_ntop_cond
-   Memcheck:Cond
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:inet_ntop
-   fun:GNUNET_a2s
-   ...
-   fun:service_task
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   create_key_from_file
-   Memcheck:Addr8
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:GNUNET_CRYPTO_rsa_key_create_from_file
-   fun:run
-   fun:service_task
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
-
-{
-   main_notify_handler
-   Memcheck:Addr8
-   obj:/lib/libc-2.14.1.so
-   ...
-   fun:main_notify_handler
-   fun:receive_ready
-   fun:GNUNET_SCHEDULER_run
-   fun:GNUNET_SERVICE_run
-   fun:main
-}
\ No newline at end of file




reply via email to

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