gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [gnunet] branch master updated: more work on tng


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated: more work on tng
Date: Sun, 16 Dec 2018 17:13:49 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new d37218d0b more work on tng
d37218d0b is described below

commit d37218d0b13292b78fcfc08d2903d6e415da0236
Author: Christian Grothoff <address@hidden>
AuthorDate: Sun Dec 16 17:13:42 2018 +0100

    more work on tng
---
 src/include/gnunet_bandwidth_lib.h                 |   6 +-
 src/include/gnunet_container_lib.h                 |   2 +-
 src/include/gnunet_protocols.h                     |  26 ++
 src/include/gnunet_signatures.h                    |   8 +-
 .../gnunet_transport_communication_service.h       |  39 +-
 src/include/gnunet_transport_monitor_service.h     |   2 +-
 src/transport/Makefile.am                          |   2 +-
 src/transport/gnunet-communicator-unix.c           |  27 +-
 src/transport/gnunet-service-tng.c                 | 512 ++++++++++++++++++---
 src/transport/transport.h                          | 101 ++--
 src/transport/transport_api2_communication.c       |  66 ++-
 src/transport/transport_api2_core.c                |   2 +-
 src/transport/transport_api_core.c                 |   1 +
 13 files changed, 673 insertions(+), 121 deletions(-)

diff --git a/src/include/gnunet_bandwidth_lib.h 
b/src/include/gnunet_bandwidth_lib.h
index 4395b878b..cb30b73e1 100644
--- a/src/include/gnunet_bandwidth_lib.h
+++ b/src/include/gnunet_bandwidth_lib.h
@@ -236,10 +236,10 @@ GNUNET_BANDWIDTH_tracker_init (struct 
GNUNET_BANDWIDTH_Tracker *av,
 /**
  * Initialize bandwidth tracker.  Note that in addition to the
  * 'max_carry_s' limit, we also always allow at least
- * GNUNET_MAX_MESSAGE_SIZE to accumulate.  So if the
+ * #GNUNET_MAX_MESSAGE_SIZE to accumulate.  So if the
  * bytes-per-second limit is so small that within 'max_carry_s' not
- * even GNUNET_MAX_MESSAGE_SIZE is allowed to accumulate, it is
- * ignored and replaced by GNUNET_MAX_MESSAGE_SIZE (which is in
+ * even #GNUNET_MAX_MESSAGE_SIZE is allowed to accumulate, it is
+ * ignored and replaced by #GNUNET_MAX_MESSAGE_SIZE (which is in
  * bytes).
  *
  * @param av tracker to initialize
diff --git a/src/include/gnunet_container_lib.h 
b/src/include/gnunet_container_lib.h
index a06d697f7..1fb460ece 100644
--- a/src/include/gnunet_container_lib.h
+++ b/src/include/gnunet_container_lib.h
@@ -11,7 +11,7 @@
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Affero General Public License for more details.
-    
+
      You should have received a copy of the GNU Affero General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index c82b11762..fd5adeef2 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -3076,6 +3076,20 @@ extern "C"
  */
 #define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR 1211
 
+/**
+ * Tell transport that it should assist with exchanging a
+ * message between communicators.  Usually used when
+ * communciators are uni-directional and need an alternative
+ * back-channel.
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL 1212
+
+/**
+ * Message type used between transport services when they
+ * internally forward communicator backchannel messages.
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION 1213
+
 
 /**
  * Message sent to indicate to the transport that a monitor
@@ -3094,6 +3108,18 @@ extern "C"
  */
 #define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END 1252
 
+/**
+ * Message exchanged between communicators to confirm
+ * successful KX (and address validation).
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_KX_CONFIRMATION 1275
+
+/**
+ * Message exchanged between communicators to exchange
+ * flow control (FC) limits and acknowledgemets.
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_FC_LIMITS 1276
+
 
 /* ************** NEW (NG) ATS Messages ************* */
 
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index 03c97f199..109fe7045 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -11,7 +11,7 @@
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Affero General Public License for more details.
-    
+
      You should have received a copy of the GNU Affero General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -194,6 +194,12 @@ extern "C"
  */
 #define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS 29
 
+/**
+ * Signature by a peer affirming that the given ephemeral
+ * key is currently in use by that peer's transport service.
+ */
+#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL 30
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
diff --git a/src/include/gnunet_transport_communication_service.h 
b/src/include/gnunet_transport_communication_service.h
index 2ba1f831a..a5547778e 100644
--- a/src/include/gnunet_transport_communication_service.h
+++ b/src/include/gnunet_transport_communication_service.h
@@ -105,15 +105,23 @@ enum GNUNET_TRANSPORT_CommunicatorCharacteristics {
 /**
  * Function called when the transport service has received an
  * acknowledgement for this communicator (!) via a different return
- * path. 
+ * path.
+ *
+ * Typically used to receive messages of type
+ * #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_FC_LIMITS or
+ * #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_KX_CONFIRMATION
+ * as well as communicator-specific messages to assist with
+ * NAT traversal.
+ *
+ * @param cls closure
+ * @param sender which peer sent the notification
+ * @param msg payload
  */
 typedef void
 (*GNUNET_TRANSPORT_CommunicatorNotify) (void *cls,
                                        const struct GNUNET_PeerIdentity 
*sender,
-                                       struct GNUNET_TIME_Absolute 
monotonic_time,
-                                       struct GNUNET_TIME_Relative validity,
-                                       const struct GNUNET_HashCode *token     
                
-                                       );
+                                        const struct GNUNET_MessageHeader 
*msg);
+
 
 /**
  * Connect to the transport service.
@@ -127,6 +135,8 @@ typedef void
  *                the address of another peer, can be NULL if the
  *                communicator only supports receiving messages
  * @param mq_init_cls closure for @a mq_init
+ * @param notify_cb function to pass backchannel messages to communicator
+ * @param notify_cb_cls closure for @a notify_cb
  * @return NULL on error
  */
 struct GNUNET_TRANSPORT_CommunicatorHandle *
@@ -135,9 +145,9 @@ GNUNET_TRANSPORT_communicator_connect (const struct 
GNUNET_CONFIGURATION_Handle
                                       const char *addr_prefix,
                                        enum 
GNUNET_TRANSPORT_CommunicatorCharacteristics cc,
                                        GNUNET_TRANSPORT_CommunicatorMqInit 
mq_init,
-                                       void *mq_init_cls);
-//                                    GNUNET_TRANSPORT_CommunicatorNotify 
notify_cb,
-//                                    void *notify_cb_cls);
+                                       void *mq_init_cls,
+                                      GNUNET_TRANSPORT_CommunicatorNotify 
notify_cb,
+                                      void *notify_cb_cls);
 
 
 /**
@@ -221,7 +231,7 @@ enum GNUNET_TRANSPORT_ConnectionStatus {
 
 
 /**
- * Notify transport service that an MQ became available due to an
+ * Notify transport service that a MQ became available due to an
  * "inbound" connection or because the communicator discovered the
  * presence of another peer.
  *
@@ -299,17 +309,16 @@ GNUNET_TRANSPORT_communicator_address_remove (struct 
GNUNET_TRANSPORT_AddressIde
  * send the message back itself).
  *
  * @param ch handle of this communicator
- * @param target_pid peer to send the message to
- * @param target_comm name of the communicator to send the message to
+ * @param pid peer to send the message to
+ * @param comm name of the communicator to send the message to
+ * @param header header of the message to transmit and pass via the
+ *        notify-API to @a pid's communicator @a comm
  */
 void
 GNUNET_TRANSPORT_communicator_notify (struct 
GNUNET_TRANSPORT_CommunicatorHandle *ch,
                                      const struct GNUNET_PeerIdentity *pid,
                                      const char *comm,
-                                     struct GNUNET_TIME_Absolute 
monotonic_time,
-                                     struct GNUNET_TIME_Relative validity,
-                                     const struct GNUNET_HashCode *token
-                                     );
+                                     const struct GNUNET_MessageHeader 
*header);
 
 
 #if 0                           /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_transport_monitor_service.h 
b/src/include/gnunet_transport_monitor_service.h
index ef599f902..8357b101f 100644
--- a/src/include/gnunet_transport_monitor_service.h
+++ b/src/include/gnunet_transport_monitor_service.h
@@ -41,7 +41,7 @@ extern "C"
 #endif
 
 #include "gnunet_util_lib.h"
-#include "gnunet_ats_service.h"
+#include "gnunet_ats_transport_service.h"
 #include "gnunet_transport_communication_service.h"
 
 
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index da79773be..ab4ef4bfa 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -328,7 +328,7 @@ gnunet_service_transport_CFLAGS = \
 gnunet_service_tng_SOURCES = \
  gnunet-service-tng.c
 gnunet_service_tng_LDADD = \
-  $(top_builddir)/src/ats/libgnunetats.la \
+  $(top_builddir)/src/ats/libgnunetatstransport.la \
   $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
diff --git a/src/transport/gnunet-communicator-unix.c 
b/src/transport/gnunet-communicator-unix.c
index e8a1cf0b2..57fa22ecf 100644
--- a/src/transport/gnunet-communicator-unix.c
+++ b/src/transport/gnunet-communicator-unix.c
@@ -983,6 +983,29 @@ do_shutdown (void *cls)
 
 
 /**
+ * Function called when the transport service has received an
+ * acknowledgement for this communicator (!) via a different return
+ * path.
+ *
+ * Not applicable for UNIX.
+ *
+ * @param cls closure
+ * @param sender which peer sent the notification
+ * @param msg payload
+ */
+static void
+enc_notify_cb (void *cls,
+               const struct GNUNET_PeerIdentity *sender,
+               const struct GNUNET_MessageHeader *msg)
+{
+  (void) cls;
+  (void) sender;
+  (void) msg;
+  GNUNET_break_op (0);
+}
+
+
+/**
  * Setup communicator and launch network interactions.
  *
  * @param cls NULL (always)
@@ -1087,7 +1110,9 @@ run (void *cls,
                                              COMMUNICATOR_ADDRESS_PREFIX,
                                               GNUNET_TRANSPORT_CC_RELIABLE,
                                              &mq_init,
-                                             NULL);
+                                             NULL,
+                                              &enc_notify_cb,
+                                              NULL);
   if (NULL == ch)
   {
     GNUNET_break (0);
diff --git a/src/transport/gnunet-service-tng.c 
b/src/transport/gnunet-service-tng.c
index 3630e6af0..85ac3da83 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -16,32 +16,70 @@
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
- * @file transport/gnunet-service-transport.c
- * @brief main for gnunet-service-transport
+ * @file transport/gnunet-service-tng.c
+ * @brief main for gnunet-service-tng
  * @author Christian Grothoff
  *
  * TODO:
- * - design ATS-NG API
  * - figure out how to transmit (selective) ACKs in case of uni-directional
  *   communicators (with/without core? DV-only?) When do we use ACKs?
- *   How/where do we distinguish between TCP/HTTP and unreliable communicators?
- *   => Should communicator provide reliable/unreliable ("flags") information?
+ *   => communicators use selective ACKs for flow control
+ *   => transport uses message-level ACKs for RTT, fragment confirmation
+ *   => integrate DV into transport, use neither core nor communicators
+ *      but rather give communicators transport-encapsulated messages
+ *      (which could be core-data, background-channel traffic, or
+ *       transport-to-transport traffic)
+ *
+ * Implement:
  * - manage fragmentation/defragmentation, retransmission, track RTT, loss, 
etc.
+ *
+ * Easy:
+ * - use ATS bandwidth allocation callback and schedule transmissions!
+ *
+ * Plan:
  * - inform ATS about RTT, goodput/loss, overheads, etc.
- * - ask ATS about bandwidth allocation!
+ *
+ * Later:
  * - change transport-core API to provide proper flow control in both
  *   directions, allow multiple messages per peer simultaneously (tag
  *   confirmations with unique message ID), and replace quota-out with
  *   proper flow control;
+ *
+ * Design realizations / discussion:
+ * - communicators do flow control by calling MQ "notify sent"
+ *   when 'ready'. They determine flow implicitly (i.e. TCP blocking)
+ *   or explicitly via background channel FC ACKs.  As long as the
+ *   channel is not full, they may 'notify sent' even if the other
+ *   peer has not yet confirmed receipt. The other peer confirming
+ *   is _only_ for FC, not for more reliable transmission; reliable
+ *   transmission (i.e. of fragments) is left to _transport_.
+ * - ACKs sent back in uni-directional communicators are done via
+ *   the background channel API; here transport _may_ initially
+ *   broadcast (with bounded # hops) if no path is known;
+ * - transport should _integrate_ DV-routing and build a view of
+ *   the network; then background channel traffic can be
+ *   routed via DV as well as explicit "DV" traffic.
+ * - background channel is also used for ACKs and NAT traversal support
+ * - transport service is responsible for AEAD'ing the background
+ *   channel, timestamps and monotonic time are used against replay
+ *   of old messages -> peerstore needs to be supplied with
+ *   "latest timestamps seen" data
+ * - if transport implements DV, we likely need a 3rd peermap
+ *   in addition to ephemerals and (direct) neighbours
+ *   => in this data structure, we should track ATS metrics (distance, RTT, 
etc.)
+ *   as well as latest timestamps seen, goodput, fragments for transmission, 
etc.
+ *   ==> check if stuff needs to be moved out of "Neighbour"
+ * - transport should encapsualte core-level messages and do its
+ *   own ACKing for RTT/goodput/loss measurements _and_ fragment
+ *   for retransmission
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_statistics_service.h"
-#include "gnunet_transport_service.h"
 #include "gnunet_transport_monitor_service.h"
 #include "gnunet_peerstore_service.h"
-#include "gnunet_ats_service.h"
-#include "gnunet-service-transport.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_ats_transport_service.h"
 #include "transport.h"
 
 
@@ -60,6 +98,122 @@
 #define MAX_PENDING (128 * 1024)
 
 
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Outer layer of an encapsulated backchannel message.
+ */
+struct TransportBackchannelEncapsulationMessage
+{
+  /**
+   * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Distance the backchannel message has traveled, to be updated at
+   * each hop.  Used to bound the number of hops in case a backchannel
+   * message is broadcast and thus travels without routing
+   * information (during initial backchannel discovery).
+   */
+  uint32_t distance;
+
+  /**
+   * Target's peer identity (as backchannels may be transmitted
+   * indirectly, or even be broadcast).
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Ephemeral key setup by the sender for @e target, used
+   * to encrypt the payload.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
+
+  /**
+   * HMAC over the ciphertext of the encrypted, variable-size
+   * body that follows.  Verified via DH of @e target and
+   * @e ephemeral_key
+   */
+  struct GNUNET_HashCode hmac;
+
+  /* Followed by encrypted, variable-size payload */
+};
+
+
+/**
+ * Message by which a peer confirms that it is using an
+ * ephemeral key.
+ */
+struct EphemeralConfirmation
+{
+
+  /**
+   * Purpose is #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * How long is this signature over the ephemeral key
+   * valid?
+   */
+  struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
+
+  /**
+   * Ephemeral key setup by the sender for @e target, used
+   * to encrypt the payload.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
+
+};
+
+/**
+ * Plaintext of the variable-size payload that is encrypted
+ * within a `struct TransportBackchannelEncapsulationMessage`
+ */
+struct TransportBackchannelRequestPayload
+{
+
+  /**
+   * Sender's peer identity.
+   */
+  struct GNUNET_PeerIdentity sender;
+
+  /**
+   * Signature of the sender over an
+   * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL.
+   */
+  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
+
+  /**
+   * How long is this signature over the ephemeral key
+   * valid?
+   */
+  struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
+
+  /**
+   * Current monotonic time of the sending transport service.  Used to
+   * detect replayed messages.  Note that the receiver should remember
+   * a list of the recently seen timestamps and only reject messages
+   * if the timestamp is in the list, or the list is "full" and the
+   * timestamp is smaller than the lowest in the list.  This list of
+   * timestamps per peer should be persisted to guard against replays
+   * after restarts.
+   */
+  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+  /* Followed by a `struct GNUNET_MessageHeader` with a message
+     for a communicator */
+
+  /* Followed by a 0-termianted string specifying the name of
+     the communicator which is to receive the message */
+
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
+
 /**
  * What type of client is the `struct TransportClient` about?
  */
@@ -88,6 +242,42 @@ enum ClientType
 
 
 /**
+ * Entry in our cache of ephemeral keys we currently use.
+ */
+struct EphemeralCacheEntry
+{
+
+  /**
+   * Target's peer identity (we don't re-use ephemerals
+   * to limit linkability of messages).
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Signature affirming @e ephemeral_key of type
+   * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL
+   */
+  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
+
+  /**
+   * How long is @e sender_sig valid
+   */
+  struct GNUNET_TIME_Absolute ephemeral_validity;
+
+  /**
+   * Our ephemeral key.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
+
+  /**
+   * Node in the ephemeral cache for this entry.
+   * Used for expiration.
+   */
+  struct GNUNET_CONTAINER_HeapNode *hn;
+};
+
+
+/**
  * Client connected to the transport service.
  */
 struct TransportClient;
@@ -100,72 +290,73 @@ struct Neighbour;
 
 
 /**
- * List of available queues for a particular neighbour.
+ * An ATS session is a message queue provided by a communicator
+ * via which we can reach a particular neighbour.
  */
-struct Queue
+struct GNUNET_ATS_Session
 {
   /**
    * Kept in a MDLL.
    */
-  struct Queue *next_neighbour;
+  struct GNUNET_ATS_Session *next_neighbour;
 
   /**
    * Kept in a MDLL.
    */
-  struct Queue *prev_neighbour;
+  struct GNUNET_ATS_Session *prev_neighbour;
 
   /**
    * Kept in a MDLL.
    */
-  struct Queue *prev_client;
+  struct GNUNET_ATS_Session *prev_client;
 
   /**
    * Kept in a MDLL.
    */
-  struct Queue *next_client;
+  struct GNUNET_ATS_Session *next_client;
 
   /**
-   * Which neighbour is this queue for?
+   * Which neighbour is this ATS session for?
    */
   struct Neighbour *neighbour;
 
   /**
-   * Which communicator offers this queue?
+   * Which communicator offers this ATS session?
    */
   struct TransportClient *tc;
 
   /**
-   * Address served by the queue.
+   * Address served by the ATS session.
    */
   const char *address;
 
   /**
-   * Our current RTT estimate for this queue.
+   * Our current RTT estimate for this ATS session.
    */
   struct GNUNET_TIME_Relative rtt;
 
   /**
-   * Unique identifier of this queue with the communicator.
+   * Unique identifier of this ATS session with the communicator.
    */
   uint32_t qid;
 
   /**
-   * Maximum transmission unit supported by this queue.
+   * Maximum transmission unit supported by this ATS session.
    */
   uint32_t mtu;
 
   /**
-   * Distance to the target of this queue.
+   * Distance to the target of this ATS session.
    */
   uint32_t distance;
 
   /**
-   * Network type offered by this queue.
+   * Network type offered by this ATS session.
    */
   enum GNUNET_NetworkType nt;
 
   /**
-   * Connection status for this queue.
+   * Connection status for this ATS session.
    */
   enum GNUNET_TRANSPORT_ConnectionStatus cs;
 
@@ -179,7 +370,15 @@ struct Queue
    */
   uint32_t num_bytes_pending;
 
-  // FIXME: add ATS-specific fields here!
+  /**
+   * How much outbound bandwidth do we have available for this session?
+   */
+  struct GNUNET_BANDWIDTH_Tracker tracker_out;
+
+  /**
+   * How much inbound bandwidth do we have available for this session?
+   */
+  struct GNUNET_BANDWIDTH_Tracker tracker_in;
 };
 
 
@@ -205,14 +404,14 @@ struct Neighbour
   struct PendingMessage *pending_msg_tail;
 
   /**
-   * Head of DLL of queues to this peer.
+   * Head of DLL of ATS sessions to this peer.
    */
-  struct Queue *queue_head;
+  struct GNUNET_ATS_Session *session_head;
 
   /**
-   * Tail of DLL of queues to this peer.
+   * Tail of DLL of ATS sessions to this peer.
    */
-  struct Queue *queue_tail;
+  struct GNUNET_ATS_Session *session_tail;
 
   /**
    * Quota at which CORE is allowed to transmit to this peer
@@ -411,12 +610,12 @@ struct TransportClient
       /**
        * Head of DLL of queues offered by this communicator.
        */
-      struct Queue *queue_head;
+      struct GNUNET_ATS_Session *session_head;
 
       /**
        * Tail of DLL of queues offered by this communicator.
        */
-      struct Queue *queue_tail;
+      struct GNUNET_ATS_Session *session_tail;
 
       /**
        * Head of list of the addresses of this peer offered by this 
communicator.
@@ -453,22 +652,22 @@ static struct TransportClient *clients_tail;
 /**
  * Statistics handle.
  */
-struct GNUNET_STATISTICS_Handle *GST_stats;
+static struct GNUNET_STATISTICS_Handle *GST_stats;
 
 /**
  * Configuration handle.
  */
-const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
+static const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
 
 /**
  * Our public key.
  */
-struct GNUNET_PeerIdentity GST_my_identity;
+static struct GNUNET_PeerIdentity GST_my_identity;
 
 /**
  * Our private key.
  */
-struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
+static struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
 
 /**
  * Map from PIDs to `struct Neighbour` entries.  A peer is
@@ -481,6 +680,42 @@ static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
  */
 static struct GNUNET_PEERSTORE_Handle *peerstore;
 
+/**
+ * Heap sorting `struct EphemeralCacheEntry` by their
+ * key/signature validity.
+ */
+static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
+
+/**
+ * Hash map for looking up `struct EphemeralCacheEntry`s
+ * by peer identity. (We may have ephemerals in our
+ * cache for which we do not have a neighbour entry,
+ * and similar many neighbours may not need ephemerals,
+ * so we use a second map.)
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
+
+/**
+ * Our connection to ATS for allocation and bootstrapping.
+ */
+static struct GNUNET_ATS_TransportHandle *ats;
+
+
+/**
+ * Free cached ephemeral key.
+ *
+ * @param ece cached signature to free
+ */
+static void
+free_ephemeral (struct EphemeralCacheEntry *ece)
+{
+  GNUNET_CONTAINER_multipeermap_remove (ephemeral_map,
+                                        &ece->target,
+                                        ece);
+  GNUNET_CONTAINER_heap_remove_node (ece->hn);
+  GNUNET_free (ece);
+}
+
 
 /**
  * Lookup neighbour record for peer @a pid.
@@ -654,7 +889,7 @@ client_connect_cb (void *cls,
 static void
 free_neighbour (struct Neighbour *neighbour)
 {
-  GNUNET_assert (NULL == neighbour->queue_head);
+  GNUNET_assert (NULL == neighbour->session_head);
   GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_remove (neighbours,
                                                       &neighbour->pid,
@@ -743,7 +978,7 @@ cores_send_disconnect_info (const struct 
GNUNET_PeerIdentity *pid)
  * @param queue the queue to free
  */
 static void
-free_queue (struct Queue *queue)
+free_queue (struct GNUNET_ATS_Session *queue)
 {
   struct Neighbour *neighbour = queue->neighbour;
   struct TransportClient *tc = queue->tc;
@@ -753,20 +988,22 @@ free_queue (struct Queue *queue)
   };
 
   GNUNET_CONTAINER_MDLL_remove (neighbour,
-                               neighbour->queue_head,
-                               neighbour->queue_tail,
+                               neighbour->session_head,
+                               neighbour->session_tail,
                                queue);
   GNUNET_CONTAINER_MDLL_remove (client,
-                               tc->details.communicator.queue_head,
-                               tc->details.communicator.queue_tail,
+                               tc->details.communicator.session_head,
+                               tc->details.communicator.session_tail,
                                queue);
 
   notify_monitors (&neighbour->pid,
                   queue->address,
                   queue->nt,
                   &me);
+  GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_in);
+  GNUNET_BANDWIDTH_tracker_notification_stop (&queue->tracker_out);
   GNUNET_free (queue);
-  if (NULL == neighbour->queue_head)
+  if (NULL == neighbour->session_head)
     {
       cores_send_disconnect_info (&neighbour->pid);
       free_neighbour (neighbour);
@@ -844,10 +1081,10 @@ client_disconnect_cb (void *cls,
     break;
   case CT_COMMUNICATOR:
     {
-      struct Queue *q;
+      struct GNUNET_ATS_Session *q;
       struct AddressListEntry *ale;
 
-      while (NULL != (q = tc->details.communicator.queue_head))
+      while (NULL != (q = tc->details.communicator.session_head))
        free_queue (q);
       while (NULL != (ale = tc->details.communicator.addr_head))
        free_address_list_entry (ale);
@@ -1356,6 +1593,34 @@ check_add_queue_message (void *cls,
 
 
 /**
+ * Bandwidth tracker informs us that the delay until we
+ * can transmit again changed.
+ *
+ * @param cls a `struct GNUNET_ATS_Session` for which the delay changed
+ */
+static void
+tracker_update_cb (void *cls)
+{
+  struct GNUNET_ATS_Session *queue = cls;
+
+  // FIXME: re-schedule transmission tasks if applicable!
+}
+
+
+/**
+ * Bandwidth tracker informs us that excessive bandwidth was allocated
+ * which is not being used.
+ *
+ * @param cls a `struct GNUNET_ATS_Session` for which the excess was noted
+ */
+static void
+tracker_excess_cb (void *cls)
+{
+  /* FIXME: what do we do? */
+}
+
+
+/**
  * New queue became available.  Process the request.
  *
  * @param cls the client
@@ -1366,7 +1631,7 @@ handle_add_queue_message (void *cls,
                           const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
 {
   struct TransportClient *tc = cls;
-  struct Queue *queue;
+  struct GNUNET_ATS_Session *queue;
   struct Neighbour *neighbour;
   const char *addr;
   uint16_t addr_len;
@@ -1388,7 +1653,7 @@ handle_add_queue_message (void *cls,
   addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
   addr = (const char *) &aqm[1];
 
-  queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
+  queue = GNUNET_malloc (sizeof (struct GNUNET_ATS_Session) + addr_len);
   queue->tc = tc;
   queue->address = (const char *) &queue[1];
   queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
@@ -1398,6 +1663,20 @@ handle_add_queue_message (void *cls,
   queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
   queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
   queue->neighbour = neighbour;
+  GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
+                                  &tracker_update_cb,
+                                  queue,
+                                  GNUNET_BANDWIDTH_ZERO,
+                                  0 /* FIXME: max carry in seconds! */,
+                                  &tracker_excess_cb,
+                                  queue);
+  GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
+                                  &tracker_update_cb,
+                                  queue,
+                                  GNUNET_BANDWIDTH_ZERO,
+                                  0 /* FIXME: max carry in seconds! */,
+                                  &tracker_excess_cb,
+                                  queue);
   memcpy (&queue[1],
          addr,
          addr_len);
@@ -1414,12 +1693,12 @@ handle_add_queue_message (void *cls,
                     &me);
   }
   GNUNET_CONTAINER_MDLL_insert (neighbour,
-                               neighbour->queue_head,
-                               neighbour->queue_tail,
+                               neighbour->session_head,
+                               neighbour->session_tail,
                                queue);
   GNUNET_CONTAINER_MDLL_insert (client,
-                               tc->details.communicator.queue_head,
-                               tc->details.communicator.queue_tail,
+                               tc->details.communicator.session_head,
+                               tc->details.communicator.session_tail,
                                queue);
   // FIXME: possibly transmit queued messages?
   GNUNET_SERVICE_client_continue (tc->client);
@@ -1444,7 +1723,7 @@ handle_del_queue_message (void *cls,
     GNUNET_SERVICE_client_drop (tc->client);
     return;
   }
-  for (struct Queue *queue = tc->details.communicator.queue_head;
+  for (struct GNUNET_ATS_Session *queue = 
tc->details.communicator.session_head;
        NULL != queue;
        queue = queue->next_client)
   {
@@ -1504,7 +1783,7 @@ notify_client_queues (void *cls,
   struct Neighbour *neighbour = value;
 
   GNUNET_assert (CT_MONITOR == tc->type);
-  for (struct Queue *q = neighbour->queue_head;
+  for (struct GNUNET_ATS_Session *q = neighbour->session_head;
        NULL != q;
        q = q->next_neighbour)
   {
@@ -1555,6 +1834,74 @@ handle_monitor_start (void *cls,
 
 
 /**
+ * Signature of a function called by ATS with the current bandwidth
+ * allocation to be used as determined by ATS.
+ *
+ * @param cls closure, NULL
+ * @param session session this is about
+ * @param bandwidth_out assigned outbound bandwidth for the connection,
+ *        0 to signal disconnect
+ * @param bandwidth_in assigned inbound bandwidth for the connection,
+ *        0 to signal disconnect
+ */
+static void
+ats_allocation_cb (void *cls,
+                   struct GNUNET_ATS_Session *session,
+                   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
+                   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
+{
+  (void) cls;
+  GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_out,
+                                         bandwidth_out);
+  GNUNET_BANDWIDTH_tracker_update_quota (&session->tracker_in,
+                                         bandwidth_in);
+}
+
+
+/**
+ * Find transport client providing communication service
+ * for the protocol @a prefix.
+ *
+ * @param prefix communicator name
+ * @return NULL if no such transport client is available
+ */
+static struct TransportClient *
+lookup_communicator (const char *prefix)
+{
+  GNUNET_break (0); // FIXME: implement
+  return NULL;
+}
+
+
+/**
+ * Signature of a function called by ATS suggesting transport to
+ * try connecting with a particular address.
+ *
+ * @param cls closure, NULL
+ * @param pid target peer
+ * @param address the address to try
+ */
+static void
+ats_suggestion_cb (void *cls,
+                   const struct GNUNET_PeerIdentity *pid,
+                   const char *address)
+{
+  struct TransportClient *tc;
+  char *prefix;
+
+  (void) cls;
+  prefix = NULL; // FIXME
+  tc = lookup_communicator (prefix);
+  if (NULL == tc)
+  {
+    // STATS...
+    return;
+  }
+  // FIXME: forward suggestion to tc
+}
+
+
+/**
  * Free neighbour entry.
  *
  * @param cls NULL
@@ -1579,6 +1926,28 @@ free_neighbour_cb (void *cls,
 
 
 /**
+ * Free ephemeral entry.
+ *
+ * @param cls NULL
+ * @param pid unused
+ * @param value a `struct Neighbour`
+ * @return #GNUNET_OK (always)
+ */
+static int
+free_ephemeral_cb (void *cls,
+                  const struct GNUNET_PeerIdentity *pid,
+                  void *value)
+{
+  struct EphemeralCacheEntry *ece = value;
+
+  (void) cls;
+  (void) pid;
+  free_ephemeral (ece);
+  return GNUNET_OK;
+}
+
+
+/**
  * Function called when the service shuts down.  Unloads our plugins
  * and cancels pending validations.
  *
@@ -1592,6 +1961,11 @@ do_shutdown (void *cls)
   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
                                         &free_neighbour_cb,
                                         NULL);
+  if (NULL != ats)
+  {
+    GNUNET_ATS_transport_done (ats);
+    ats = NULL;
+  }
   if (NULL != peerstore)
   {
     GNUNET_PEERSTORE_disconnect (peerstore,
@@ -1610,6 +1984,14 @@ do_shutdown (void *cls)
     GST_my_private_key = NULL;
   }
   GNUNET_CONTAINER_multipeermap_destroy (neighbours);
+  neighbours = NULL;
+  GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
+                                        &free_ephemeral_cb,
+                                        NULL);
+  GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
+  ephemeral_map = NULL;
+  GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
+  ephemeral_heap = NULL;
 }
 
 
@@ -1630,6 +2012,9 @@ run (void *cls,
   GST_cfg = c;
   neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
                                                     GNUNET_YES);
+  ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32,
+                                                        GNUNET_YES);
+  ephemeral_heap = GNUNET_CONTAINER_heap_create 
(GNUNET_CONTAINER_HEAP_ORDER_MIN);
   GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration 
(GST_cfg);
   if (NULL == GST_my_private_key)
   {
@@ -1643,19 +2028,28 @@ run (void *cls,
   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
              "My identity is `%s'\n",
              GNUNET_i2s_full (&GST_my_identity));
-
   GST_stats = GNUNET_STATISTICS_create ("transport",
                                         GST_cfg);
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                 NULL);
   peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
   if (NULL == peerstore)
-    {
-      GNUNET_break (0);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    }
-  /* start subsystems */
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  ats = GNUNET_ATS_transport_init (GST_cfg,
+                                   &ats_allocation_cb,
+                                   NULL,
+                                   &ats_suggestion_cb,
+                                   NULL);
+  if (NULL == ats)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
 }
 
 
diff --git a/src/transport/transport.h b/src/transport/transport.h
index df1321d1a..3c5fe72de 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -26,7 +26,6 @@
 
 #include "gnunet_crypto_lib.h"
 #include "gnunet_time_lib.h"
-#include "gnunet_transport_service.h"
 #include "gnunet_constants.h"
 
 #define DEBUG_TRANSPORT GNUNET_EXTRA_LOGGING
@@ -79,6 +78,7 @@ typedef void
 
 GNUNET_NETWORK_STRUCT_BEGIN
 
+
 /**
  * Message from the transport service to the library
  * asking to check if both processes agree about this
@@ -241,61 +241,67 @@ struct SendOkMessage
 
 };
 
+
 /**
- * Message used to notify the transport API about an address to string
- * conversion. Message is followed by the string with the humand-readable
- * address.  For each lookup, multiple results may be returned.  The
- * last message must have a @e res of #GNUNET_OK and an @e addr_len
- * of zero.
+ * Message used to notify the transport service about a message
+ * to be transmitted to another peer.  The actual message follows.
  */
-struct AddressToStringResultMessage
+struct OutboundMessage
 {
 
   /**
-   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY
+   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
    */
   struct GNUNET_MessageHeader header;
 
   /**
-   * #GNUNET_OK if the conversion succeeded,
-   * #GNUNET_SYSERR if it failed
+   * Always zero.
    */
-  uint32_t res GNUNET_PACKED;
+  uint32_t reserved GNUNET_PACKED;
 
   /**
-   * Length of the following string, zero if @e is #GNUNET_SYSERR
+   * Allowed delay.
    */
-  uint32_t addr_len GNUNET_PACKED;
+  struct GNUNET_TIME_RelativeNBO timeout;
+
+  /**
+   * Which peer should receive the message?
+   */
+  struct GNUNET_PeerIdentity peer;
+
 };
 
 
+
+
+#if 
!(defined(GNUNET_TRANSPORT_COMMUNICATION_VERSION)||defined(GNUNET_TRANSPORT_CORE_VERSION))
+
+
 /**
- * Message used to notify the transport service about a message
- * to be transmitted to another peer.  The actual message follows.
+ * Message used to notify the transport API about an address to string
+ * conversion. Message is followed by the string with the humand-readable
+ * address.  For each lookup, multiple results may be returned.  The
+ * last message must have a @e res of #GNUNET_OK and an @e addr_len
+ * of zero.
  */
-struct OutboundMessage
+struct AddressToStringResultMessage
 {
 
   /**
-   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND
+   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY
    */
   struct GNUNET_MessageHeader header;
 
   /**
-   * Always zero.
-   */
-  uint32_t reserved GNUNET_PACKED;
-
-  /**
-   * Allowed delay.
+   * #GNUNET_OK if the conversion succeeded,
+   * #GNUNET_SYSERR if it failed
    */
-  struct GNUNET_TIME_RelativeNBO timeout;
+  uint32_t res GNUNET_PACKED;
 
   /**
-   * Which peer should receive the message?
+   * Length of the following string, zero if @e is #GNUNET_SYSERR
    */
-  struct GNUNET_PeerIdentity peer;
-
+  uint32_t addr_len GNUNET_PACKED;
 };
 
 
@@ -639,13 +645,7 @@ struct TransportPluginMonitorMessage
 
 };
 
-
-
-
-
-
-
-
+#else
 
 /* *********************** TNG messages ***************** */
 
@@ -950,6 +950,35 @@ struct GNUNET_TRANSPORT_SendMessageToAck
 };
 
 
+/**
+ * Message from communicator to transport service asking for
+ * transmission of a backchannel message with the given peer @e pid
+ * and communicator.
+ */
+struct GNUNET_TRANSPORT_CommunicatorBackchannel
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Always zero, for alignment.
+   */
+  uint32_t reserved;
+
+  /**
+   * Target peer.
+   */
+  struct GNUNET_PeerIdentity pid;
+
+  /* Followed by a `struct GNUNET_MessageHeader` with the encapsulated
+     message to the communicator */
+
+  /* Followed by the 0-terminated string specifying the desired
+     communicator */
+};
+
 
 
 /**
@@ -1028,9 +1057,7 @@ struct GNUNET_TRANSPORT_MonitorData
 
 };
 
-
-
-
+#endif
 
 GNUNET_NETWORK_STRUCT_END
 
diff --git a/src/transport/transport_api2_communication.c 
b/src/transport/transport_api2_communication.c
index ffd7f208e..a8237f18f 100644
--- a/src/transport/transport_api2_communication.c
+++ b/src/transport/transport_api2_communication.c
@@ -25,6 +25,7 @@
 #include "gnunet_util_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_transport_communication_service.h"
+#include "gnunet_ats_transport_service.h"
 #include "transport.h"
 
 
@@ -178,6 +179,18 @@ struct GNUNET_TRANSPORT_CommunicatorHandle
   void *mq_init_cls;
 
   /**
+   * Function to call when the transport service receives messages
+   * for a communicator (i.e. for NAT traversal or for non-bidirectional
+   * communicators).
+   */
+  GNUNET_TRANSPORT_CommunicatorNotify notify_cb;
+
+  /**
+   * Closure for @e notify_Cb.
+   */
+  void *notify_cb_cls;
+
+  /**
    * Queue to talk to the transport service.
    */
   struct GNUNET_MQ_Handle *mq;
@@ -744,6 +757,7 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
                           GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG,
                           struct GNUNET_TRANSPORT_SendMessageTo,
                           ch),
+    // FIXME: handle backchannel notifications!
     GNUNET_MQ_handler_end()
   };
   struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam;
@@ -790,6 +804,8 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
  *                the address of another peer, can be NULL if the
  *                communicator only supports receiving messages
  * @param mq_init_cls closure for @a mq_init
+ * @param notify_cb function to pass backchannel messages to communicator
+ * @param notify_cb_cls closure for @a notify_cb
  * @return NULL on error
  */
 struct GNUNET_TRANSPORT_CommunicatorHandle *
@@ -798,7 +814,9 @@ GNUNET_TRANSPORT_communicator_connect (const struct 
GNUNET_CONFIGURATION_Handle
                                       const char *addr_prefix,
                                        enum 
GNUNET_TRANSPORT_CommunicatorCharacteristics cc,
                                        GNUNET_TRANSPORT_CommunicatorMqInit 
mq_init,
-                                       void *mq_init_cls)
+                                       void *mq_init_cls,
+                                       GNUNET_TRANSPORT_CommunicatorNotify 
notify_cb,
+                                      void *notify_cb_cls)
 {
   struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
 
@@ -808,6 +826,8 @@ GNUNET_TRANSPORT_communicator_connect (const struct 
GNUNET_CONFIGURATION_Handle
   ch->addr_prefix = addr_prefix;
   ch->mq_init = mq_init;
   ch->mq_init_cls = mq_init_cls;
+  ch->notify_cb = notify_cb;
+  ch->notify_cb_cls = notify_cb_cls;
   ch->cc = cc;
   reconnect (ch);
   if (GNUNET_OK !=
@@ -1041,4 +1061,48 @@ GNUNET_TRANSPORT_communicator_address_remove (struct 
GNUNET_TRANSPORT_AddressIde
 }
 
 
+/* ************************* Backchannel *************************** */
+
+
+/**
+ * The communicator asks the transport service to route a message via
+ * a different path to another communicator service at another peer.
+ * This must only be done for special control traffic (as there is no
+ * flow control for this API), such as acknowledgements, and generally
+ * only be done if the communicator is uni-directional (i.e. cannot
+ * send the message back itself).
+ *
+ * @param ch handle of this communicator
+ * @param pid peer to send the message to
+ * @param comm name of the communicator to send the message to
+ * @param header header of the message to transmit and pass via the
+ *        notify-API to @a pid's communicator @a comm
+ */
+void
+GNUNET_TRANSPORT_communicator_notify (struct 
GNUNET_TRANSPORT_CommunicatorHandle *ch,
+                                     const struct GNUNET_PeerIdentity *pid,
+                                     const char *comm,
+                                     const struct GNUNET_MessageHeader *header)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb;
+  size_t slen = strlen (comm) + 1;
+  uint16_t mlen = ntohs (header->size);
+
+  GNUNET_assert (mlen + slen + sizeof (*cb) < UINT16_MAX);
+  env = GNUNET_MQ_msg_extra (cb,
+                             slen + mlen,
+                             
GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL);
+  cb->pid = *pid;
+  memcpy (&cb[1],
+          header,
+          mlen);
+  memcpy (((char *)&cb[1]) + mlen,
+          comm,
+          slen);
+  GNUNET_MQ_send (ch->mq,
+                  env);
+}
+
+
 /* end of transport_api2_communication.c */
diff --git a/src/transport/transport_api2_core.c 
b/src/transport/transport_api2_core.c
index 78d8dcce0..d81a6f730 100644
--- a/src/transport/transport_api2_core.c
+++ b/src/transport/transport_api2_core.c
@@ -11,7 +11,7 @@
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Affero General Public License for more details.
-    
+
      You should have received a copy of the GNU Affero General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/transport/transport_api_core.c 
b/src/transport/transport_api_core.c
index 2e897d94a..06d459f4e 100644
--- a/src/transport/transport_api_core.c
+++ b/src/transport/transport_api_core.c
@@ -28,6 +28,7 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_transport_core_service.h"
+#include "gnunet_transport_service.h"
 #include "transport.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "transport-api-core",__VA_ARGS__)

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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