gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [gnunet] branch master updated (bc32b1f4b -> 84b3c8716)


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated (bc32b1f4b -> 84b3c8716)
Date: Sat, 11 May 2019 22:14:11 +0200

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

grothoff pushed a change to branch master
in repository gnunet.

    from bc32b1f4b move encryption logic into DVBox
     new dc4902a53 reindenting
     new 84b3c8716 clean up transmission logic to have queues 'pull' for 
pending messages while control traffic is 'pushed' into queues

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/include/gnunet_common.h        | 494 +++++++++++++++++---------
 src/transport/gnunet-service-tng.c | 702 +++++++++++++++++++++++--------------
 2 files changed, 770 insertions(+), 426 deletions(-)

diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index 1f5600381..1916024b8 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -57,9 +57,8 @@
 #endif
 
 #ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
+extern "C" {
+#if 0 /* keep Emacsens' auto-indent happy */
 }
 #endif
 #endif
@@ -76,14 +75,14 @@ extern "C"
  * GNUNET_SYSERR`, `GNUNET_OK != GNUNET_NO`, `GNUNET_NO !=
  * GNUNET_SYSERR` and finally `GNUNET_YES != GNUNET_NO`.
  */
-#define GNUNET_OK      1
+#define GNUNET_OK 1
 #define GNUNET_SYSERR -1
-#define GNUNET_YES     1
-#define GNUNET_NO      0
+#define GNUNET_YES 1
+#define GNUNET_NO 0
 
-#define GNUNET_MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define GNUNET_MIN(a, b) (((a) < (b)) ? (a) : (b))
 
-#define GNUNET_MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define GNUNET_MAX(a, b) (((a) > (b)) ? (a) : (b))
 
 /* some systems use one underscore only, and mingw uses no underscore... */
 #ifndef __BYTE_ORDER
@@ -117,7 +116,7 @@ extern "C"
 /**
  * wrap va_arg for enums
  */
-#define GNUNET_VA_ARG_ENUM(va,X) ((enum X) va_arg (va, int))
+#define GNUNET_VA_ARG_ENUM(va, X) ((enum X) va_arg (va, int))
 
 
 /**
@@ -133,37 +132,37 @@ extern "C"
  * Endian operations
  */
 
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-#  define GNUNET_htobe16(x) __bswap_16 (x)
-#  define GNUNET_htole16(x) (x)
-#  define GNUNET_be16toh(x) __bswap_16 (x)
-#  define GNUNET_le16toh(x) (x)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define GNUNET_htobe16(x) __bswap_16 (x)
+#define GNUNET_htole16(x) (x)
+#define GNUNET_be16toh(x) __bswap_16 (x)
+#define GNUNET_le16toh(x) (x)
 
-#  define GNUNET_htobe32(x) __bswap_32 (x)
-#  define GNUNET_htole32(x) (x)
-#  define GNUNET_be32toh(x) __bswap_32 (x)
-#  define GNUNET_le32toh(x) (x)
+#define GNUNET_htobe32(x) __bswap_32 (x)
+#define GNUNET_htole32(x) (x)
+#define GNUNET_be32toh(x) __bswap_32 (x)
+#define GNUNET_le32toh(x) (x)
 
-#  define GNUNET_htobe64(x) __bswap_64 (x)
-#  define GNUNET_htole64(x) (x)
-#  define GNUNET_be64toh(x) __bswap_64 (x)
-#  define GNUNET_le64toh(x) (x)
+#define GNUNET_htobe64(x) __bswap_64 (x)
+#define GNUNET_htole64(x) (x)
+#define GNUNET_be64toh(x) __bswap_64 (x)
+#define GNUNET_le64toh(x) (x)
 #endif
-# if __BYTE_ORDER == __BIG_ENDIAN
-#  define GNUNET_htobe16(x) (x)
-#  define GNUNET_htole16(x) __bswap_16 (x)
-#  define GNUNET_be16toh(x) (x)
-#  define GNUNET_le16toh(x) __bswap_16 (x)
-
-#  define GNUNET_htobe32(x) (x)
-#  define GNUNET_htole32(x) __bswap_32 (x)
-#  define GNUNET_be32toh(x) (x)
-#  define GNUNET_le32toh(x) __bswap_32 (x)
-
-#  define GNUNET_htobe64(x) (x)
-#  define GNUNET_htole64(x) __bswap_64 (x)
-#  define GNUNET_be64toh(x) (x)
-#  define GNUNET_le64toh(x) __bswap_64 (x)
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define GNUNET_htobe16(x) (x)
+#define GNUNET_htole16(x) __bswap_16 (x)
+#define GNUNET_be16toh(x) (x)
+#define GNUNET_le16toh(x) __bswap_16 (x)
+
+#define GNUNET_htobe32(x) (x)
+#define GNUNET_htole32(x) __bswap_32 (x)
+#define GNUNET_be32toh(x) (x)
+#define GNUNET_le32toh(x) __bswap_32 (x)
+
+#define GNUNET_htobe64(x) (x)
+#define GNUNET_htole64(x) __bswap_64 (x)
+#define GNUNET_be64toh(x) (x)
+#define GNUNET_le64toh(x) __bswap_64 (x)
 #endif
 
 
@@ -179,19 +178,19 @@ extern "C"
  * on the stack with a variable-length that might be zero, write
  * "int[GNUNET_NZL(n)] x;" instead of "int[n] x".
  */
-#define GNUNET_NZL(l) GNUNET_MAX(1,l)
+#define GNUNET_NZL(l) GNUNET_MAX (1, l)
 
 
 /**
  * gcc-ism to get packed structs.
  */
-#define GNUNET_PACKED __attribute__((packed))
+#define GNUNET_PACKED __attribute__ ((packed))
 
 /**
  * gcc-ism to get gcc bitfield layout when compiling with -mms-bitfields
  */
 #if MINGW
-#define GNUNET_GCC_STRUCT_LAYOUT __attribute__((gcc_struct))
+#define GNUNET_GCC_STRUCT_LAYOUT __attribute__ ((gcc_struct))
 #else
 #define GNUNET_GCC_STRUCT_LAYOUT
 #endif
@@ -202,20 +201,20 @@ extern "C"
  * bug #33594.
  */
 #ifdef __BIGGEST_ALIGNMENT__
-#define GNUNET_ALIGN __attribute__((aligned (__BIGGEST_ALIGNMENT__)))
+#define GNUNET_ALIGN __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)))
 #else
-#define GNUNET_ALIGN __attribute__((aligned (8)))
+#define GNUNET_ALIGN __attribute__ ((aligned (8)))
 #endif
 
 /**
  * gcc-ism to document unused arguments
  */
-#define GNUNET_UNUSED __attribute__((unused))
+#define GNUNET_UNUSED __attribute__ ((unused))
 
 /**
  * gcc-ism to document functions that don't return
  */
-#define GNUNET_NORETURN __attribute__((noreturn))
+#define GNUNET_NORETURN __attribute__ ((noreturn))
 
 #if MINGW
 #if __GNUC__ > 3
@@ -225,9 +224,7 @@ extern "C"
  * so we *only* use this on W32 (see #670578 from Debian); fortunately,
  * W32 doesn't run on sparc anyway.
  */
-#define GNUNET_NETWORK_STRUCT_BEGIN \
-  _Pragma("pack(push)") \
-  _Pragma("pack(1)")
+#define GNUNET_NETWORK_STRUCT_BEGIN _Pragma ("pack(push)") _Pragma ("pack(1)")
 
 /**
  * gcc 4.x-ism to pack structures even on W32 (to be used after structs)
@@ -235,7 +232,7 @@ extern "C"
  * so we *only* use this on W32 (see #670578 from Debian); fortunately,
  * W32 doesn't run on sparc anyway.
  */
-#define GNUNET_NETWORK_STRUCT_END _Pragma("pack(pop)")
+#define GNUNET_NETWORK_STRUCT_END _Pragma ("pack(pop)")
 
 #else
 #error gcc 4.x or higher required on W32 systems
@@ -261,22 +258,20 @@ GNUNET_NETWORK_STRUCT_BEGIN
  */
 struct GNUNET_HashCode
 {
-  uint32_t bits[512 / 8 / sizeof (uint32_t)];   /* = 16 */
+  uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */
 };
 
 
-
 /**
  * @brief A 256-bit hashcode.  Used under special conditions, like when space
  * is critical and security is not impacted by it.
  */
 struct GNUNET_ShortHashCode
 {
-  uint32_t bits[256 / 8 / sizeof (uint32_t)];   /* = 8 */
+  uint32_t bits[256 / 8 / sizeof (uint32_t)]; /* = 8 */
 };
 
 
-
 /**
  * Header for all communications.
  */
@@ -293,7 +288,6 @@ struct GNUNET_MessageHeader
    * The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
    */
   uint16_t type GNUNET_PACKED;
-
 };
 
 
@@ -325,7 +319,7 @@ struct GNUNET_OperationResultMessage
  */
 struct GNUNET_AsyncScopeId
 {
-  uint32_t bits[16 / sizeof (uint32_t)];  /* = 16 bytes */
+  uint32_t bits[16 / sizeof (uint32_t)]; /* = 16 bytes */
 };
 
 GNUNET_NETWORK_STRUCT_END
@@ -334,7 +328,8 @@ GNUNET_NETWORK_STRUCT_END
 /**
  * Saved async scope identifier or root scope.
  */
-struct GNUNET_AsyncScopeSave {
+struct GNUNET_AsyncScopeSave
+{
   /**
    * Saved scope.  Unused if 'have_scope==GNUNET_NO'.
    */
@@ -356,9 +351,7 @@ struct GNUNET_AsyncScopeSave {
  *  #GNUNET_NO to stop iteration with no error,
  *  #GNUNET_SYSERR to abort iteration with error!
  */
-typedef int
-(*GNUNET_FileNameCallback) (void *cls,
-                            const char *filename);
+typedef int (*GNUNET_FileNameCallback) (void *cls, const char *filename);
 
 
 /**
@@ -366,8 +359,7 @@ typedef int
  *
  * @param cls  Closure.
  */
-typedef void
-(*GNUNET_ContinuationCallback) (void *cls);
+typedef void (*GNUNET_ContinuationCallback) (void *cls);
 
 
 /**
@@ -382,9 +374,10 @@ typedef void
  * @param data_size
  *        Size of @a data.
  */
-typedef void
-(*GNUNET_ResultCallback) (void *cls, int64_t result_code,
-                          const void *data, uint16_t data_size);
+typedef void (*GNUNET_ResultCallback) (void *cls,
+                                       int64_t result_code,
+                                       const void *data,
+                                       uint16_t data_size);
 
 
 /* ****************************** logging ***************************** */
@@ -420,12 +413,11 @@ enum GNUNET_ErrorType
  * @param date when was the message logged?
  * @param message what is the message
  */
-typedef void
-(*GNUNET_Logger) (void *cls,
-                  enum GNUNET_ErrorType kind,
-                  const char *component,
-                  const char *date,
-                  const char *message);
+typedef void (*GNUNET_Logger) (void *cls,
+                               enum GNUNET_ErrorType kind,
+                               const char *component,
+                               const char *date,
+                               const char *message);
 
 
 /**
@@ -438,7 +430,7 @@ int
 GNUNET_get_log_skip (void);
 
 
-#if !defined(GNUNET_CULL_LOGGING)
+#if ! defined(GNUNET_CULL_LOGGING)
 int
 GNUNET_get_log_call_status (int caller_level,
                             const char *comp,
@@ -462,23 +454,23 @@ GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const 
char *message, ...)
 
 /* from glib */
 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
-#define _GNUNET_BOOLEAN_EXPR(expr)              \
- __extension__ ({                               \
-   int _gnunet_boolean_var_;                    \
-   if (expr)                                    \
-      _gnunet_boolean_var_ = 1;                 \
-   else                                         \
-      _gnunet_boolean_var_ = 0;                 \
-   _gnunet_boolean_var_;                        \
-})
-#define GN_LIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 1))
-#define GN_UNLIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 0))
+#define _GNUNET_BOOLEAN_EXPR(expr) \
+  __extension__({                  \
+    int _gnunet_boolean_var_;      \
+    if (expr)                      \
+      _gnunet_boolean_var_ = 1;    \
+    else                           \
+      _gnunet_boolean_var_ = 0;    \
+    _gnunet_boolean_var_;          \
+  })
+#define GN_LIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR (expr), 1))
+#define GN_UNLIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR (expr), 0))
 #else
 #define GN_LIKELY(expr) (expr)
 #define GN_UNLIKELY(expr) (expr)
 #endif
 
-#if !defined(GNUNET_LOG_CALL_STATUS)
+#if ! defined(GNUNET_LOG_CALL_STATUS)
 #define GNUNET_LOG_CALL_STATUS -1
 #endif
 
@@ -494,35 +486,65 @@ GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const 
char *message, ...)
  * @param ... arguments for format string
  */
 void
-GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
-                         const char *message, ...);
-
-#if !defined(GNUNET_CULL_LOGGING)
-#define GNUNET_log_from(kind,comp,...) do { int log_line = __LINE__;\
-  static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
-  if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) 
{ \
-    if (GN_UNLIKELY(log_call_enabled == -1))\
-      log_call_enabled = GNUNET_get_log_call_status ((kind) & 
(~GNUNET_ERROR_TYPE_BULK), (comp), __FILE__, __FUNCTION__, log_line); \
-    if (GN_UNLIKELY(GNUNET_get_log_skip () > 0)) { GNUNET_log_skip (-1, 
GNUNET_NO); }\
-    else {\
-      if (GN_UNLIKELY(log_call_enabled))\
-        GNUNET_log_from_nocheck ((kind), comp, __VA_ARGS__);   \
-    }\
-  }\
-} while (0)
-
- #define GNUNET_log(kind,...) do { int log_line = __LINE__;\
-  static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\
-  if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) 
{ \
-    if (GN_UNLIKELY(log_call_enabled == -1))\
-      log_call_enabled = GNUNET_get_log_call_status ((kind) & 
(~GNUNET_ERROR_TYPE_BULK), NULL, __FILE__, __FUNCTION__, log_line);\
-    if (GN_UNLIKELY(GNUNET_get_log_skip () > 0)) { GNUNET_log_skip (-1, 
GNUNET_NO); }\
-    else {\
-      if (GN_UNLIKELY(log_call_enabled))\
-        GNUNET_log_nocheck ((kind), __VA_ARGS__);      \
-    }\
-  }\
-} while (0)
+GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind,
+                         const char *comp,
+                         const char *message,
+                         ...);
+
+#if ! defined(GNUNET_CULL_LOGGING)
+#define GNUNET_log_from(kind, comp, ...)                                  \
+  do                                                                      \
+  {                                                                       \
+    int log_line = __LINE__;                                              \
+    static int log_call_enabled = GNUNET_LOG_CALL_STATUS;                 \
+    if ((GNUNET_EXTRA_LOGGING > 0) ||                                     \
+        ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0))                        \
+    {                                                                     \
+      if (GN_UNLIKELY (log_call_enabled == -1))                           \
+        log_call_enabled =                                                \
+          GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), \
+                                      (comp),                             \
+                                      __FILE__,                           \
+                                      __FUNCTION__,                       \
+                                      log_line);                          \
+      if (GN_UNLIKELY (GNUNET_get_log_skip () > 0))                       \
+      {                                                                   \
+        GNUNET_log_skip (-1, GNUNET_NO);                                  \
+      }                                                                   \
+      else                                                                \
+      {                                                                   \
+        if (GN_UNLIKELY (log_call_enabled))                               \
+          GNUNET_log_from_nocheck ((kind), comp, __VA_ARGS__);            \
+      }                                                                   \
+    }                                                                     \
+  } while (0)
+
+#define GNUNET_log(kind, ...)                                             \
+  do                                                                      \
+  {                                                                       \
+    int log_line = __LINE__;                                              \
+    static int log_call_enabled = GNUNET_LOG_CALL_STATUS;                 \
+    if ((GNUNET_EXTRA_LOGGING > 0) ||                                     \
+        ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0))                        \
+    {                                                                     \
+      if (GN_UNLIKELY (log_call_enabled == -1))                           \
+        log_call_enabled =                                                \
+          GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), \
+                                      NULL,                               \
+                                      __FILE__,                           \
+                                      __FUNCTION__,                       \
+                                      log_line);                          \
+      if (GN_UNLIKELY (GNUNET_get_log_skip () > 0))                       \
+      {                                                                   \
+        GNUNET_log_skip (-1, GNUNET_NO);                                  \
+      }                                                                   \
+      else                                                                \
+      {                                                                   \
+        if (GN_UNLIKELY (log_call_enabled))                               \
+          GNUNET_log_nocheck ((kind), __VA_ARGS__);                       \
+      }                                                                   \
+    }                                                                     \
+  } while (0)
 #else
 #define GNUNET_log(...)
 #define GNUNET_log_from(...)
@@ -539,8 +561,8 @@ GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const 
char *comp,
  */
 void
 GNUNET_log_config_missing (enum GNUNET_ErrorType kind,
-                          const char *section,
-                          const char *option);
+                           const char *section,
+                           const char *option);
 
 
 /**
@@ -554,9 +576,9 @@ GNUNET_log_config_missing (enum GNUNET_ErrorType kind,
  */
 void
 GNUNET_log_config_invalid (enum GNUNET_ErrorType kind,
-                          const char *section,
-                          const char *option,
-                          const char *required);
+                           const char *section,
+                           const char *option,
+                           const char *required);
 
 
 /**
@@ -577,8 +599,7 @@ GNUNET_abort_ (void) GNUNET_NORETURN;
  * @param check_reset #GNUNET_YES to assert that the log skip counter is 
currently zero
  */
 void
-GNUNET_log_skip (int n,
-                 int check_reset);
+GNUNET_log_skip (int n, int check_reset);
 
 
 /**
@@ -591,9 +612,7 @@ GNUNET_log_skip (int n,
  * @return #GNUNET_OK on success, #GNUNET_SYSERR if logfile could not be opened
  */
 int
-GNUNET_log_setup (const char *comp,
-                  const char *loglevel,
-                  const char *logfile);
+GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile);
 
 
 /**
@@ -607,8 +626,7 @@ GNUNET_log_setup (const char *comp,
  * @param logger_cls closure for @a logger
  */
 void
-GNUNET_logger_add (GNUNET_Logger logger,
-                   void *logger_cls);
+GNUNET_logger_add (GNUNET_Logger logger, void *logger_cls);
 
 
 /**
@@ -619,8 +637,7 @@ GNUNET_logger_add (GNUNET_Logger logger,
  * @param logger_cls closure for @a logger
  */
 void
-GNUNET_logger_remove (GNUNET_Logger logger,
-                      void *logger_cls);
+GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls);
 
 
 /**
@@ -798,8 +815,7 @@ GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid);
  *  will be overwritten by next call to #GNUNET_a2s().
  */
 const char *
-GNUNET_a2s (const struct sockaddr *addr,
-            socklen_t addrlen);
+GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen);
 
 
 /**
@@ -817,14 +833,36 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * @ingroup logging
  * Use this for fatal errors that cannot be handled
  */
-#define GNUNET_assert(cond) do { if (! (cond)) { 
GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d. 
Aborting.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
+#define GNUNET_assert(cond)                                     \
+  do                                                            \
+  {                                                             \
+    if (! (cond))                                               \
+    {                                                           \
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                      \
+                  _ ("Assertion failed at %s:%d. Aborting.\n"), \
+                  __FILE__,                                     \
+                  __LINE__);                                    \
+      GNUNET_abort_ ();                                         \
+    }                                                           \
+  } while (0)
 
 
 /**
  * @ingroup logging
  * Use this for fatal errors that cannot be handled
  */
-#define GNUNET_assert_at(cond, f, l) do { if (! (cond)) { 
GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d. 
Aborting.\n"), f, l); GNUNET_abort_(); } } while(0)
+#define GNUNET_assert_at(cond, f, l)                            \
+  do                                                            \
+  {                                                             \
+    if (! (cond))                                               \
+    {                                                           \
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                      \
+                  _ ("Assertion failed at %s:%d. Aborting.\n"), \
+                  f,                                            \
+                  l);                                           \
+      GNUNET_abort_ ();                                         \
+    }                                                           \
+  } while (0)
 
 
 /**
@@ -834,7 +872,19 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * @param cond Condition to evaluate
  * @param comp Component string to use for logging
  */
-#define GNUNET_assert_from(cond, comp) do { if (! (cond)) { 
GNUNET_log_from(GNUNET_ERROR_TYPE_ERROR, comp, _("Assertion failed at %s:%d. 
Aborting.\n"), __FILE__, __LINE__); GNUNET_abort_(); } } while(0)
+#define GNUNET_assert_from(cond, comp)                               \
+  do                                                                 \
+  {                                                                  \
+    if (! (cond))                                                    \
+    {                                                                \
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,                      \
+                       comp,                                         \
+                       _ ("Assertion failed at %s:%d. Aborting.\n"), \
+                       __FILE__,                                     \
+                       __LINE__);                                    \
+      GNUNET_abort_ ();                                              \
+    }                                                                \
+  } while (0)
 
 
 /**
@@ -842,7 +892,17 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * Use this for internal assertion violations that are
  * not fatal (can be handled) but should not occur.
  */
-#define GNUNET_break(cond)  do { if (! (cond)) { 
GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d.\n"), 
__FILE__, __LINE__); } } while(0)
+#define GNUNET_break(cond)                            \
+  do                                                  \
+  {                                                   \
+    if (! (cond))                                     \
+    {                                                 \
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,            \
+                  _ ("Assertion failed at %s:%d.\n"), \
+                  __FILE__,                           \
+                  __LINE__);                          \
+    }                                                 \
+  } while (0)
 
 
 /**
@@ -854,7 +914,17 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * we still want to see these problems during
  * development and testing.  "OP == other peer".
  */
-#define GNUNET_break_op(cond)  do { if (! (cond)) { 
GNUNET_log(GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _("External 
protocol violation detected at %s:%d.\n"), __FILE__, __LINE__); } } while(0)
+#define GNUNET_break_op(cond)                                             \
+  do                                                                      \
+  {                                                                       \
+    if (! (cond))                                                         \
+    {                                                                     \
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,     \
+                  _ ("External protocol violation detected at %s:%d.\n"), \
+                  __FILE__,                                               \
+                  __LINE__);                                              \
+    }                                                                     \
+  } while (0)
 
 
 /**
@@ -863,7 +933,16 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * a failure of the command 'cmd' with the message given
  * by strerror(errno).
  */
-#define GNUNET_log_strerror(level, cmd) do { GNUNET_log(level, _("`%s' failed 
at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, STRERROR(errno)); } 
while(0)
+#define GNUNET_log_strerror(level, cmd)                      \
+  do                                                         \
+  {                                                          \
+    GNUNET_log (level,                                       \
+                _ ("`%s' failed at %s:%d with error: %s\n"), \
+                cmd,                                         \
+                __FILE__,                                    \
+                __LINE__,                                    \
+                STRERROR (errno));                           \
+  } while (0)
 
 
 /**
@@ -872,7 +951,17 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * a failure of the command 'cmd' with the message given
  * by strerror(errno).
  */
-#define GNUNET_log_from_strerror(level, component, cmd) do { GNUNET_log_from 
(level, component, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, 
__LINE__, STRERROR(errno)); } while(0)
+#define GNUNET_log_from_strerror(level, component, cmd)           \
+  do                                                              \
+  {                                                               \
+    GNUNET_log_from (level,                                       \
+                     component,                                   \
+                     _ ("`%s' failed at %s:%d with error: %s\n"), \
+                     cmd,                                         \
+                     __FILE__,                                    \
+                     __LINE__,                                    \
+                     STRERROR (errno));                           \
+  } while (0)
 
 
 /**
@@ -881,7 +970,17 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * a failure of the command 'cmd' with the message given
  * by strerror(errno).
  */
-#define GNUNET_log_strerror_file(level, cmd, filename) do { GNUNET_log(level, 
_("`%s' failed on file `%s' at %s:%d with error: %s\n"), cmd, filename, 
__FILE__, __LINE__, STRERROR(errno)); } while(0)
+#define GNUNET_log_strerror_file(level, cmd, filename)                    \
+  do                                                                      \
+  {                                                                       \
+    GNUNET_log (level,                                                    \
+                _ ("`%s' failed on file `%s' at %s:%d with error: %s\n"), \
+                cmd,                                                      \
+                filename,                                                 \
+                __FILE__,                                                 \
+                __LINE__,                                                 \
+                STRERROR (errno));                                        \
+  } while (0)
 
 
 /**
@@ -890,7 +989,18 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind);
  * a failure of the command 'cmd' with the message given
  * by strerror(errno).
  */
-#define GNUNET_log_from_strerror_file(level, component, cmd, filename) do { 
GNUNET_log_from (level, component, _("`%s' failed on file `%s' at %s:%d with 
error: %s\n"), cmd, filename,__FILE__, __LINE__, STRERROR(errno)); } while(0)
+#define GNUNET_log_from_strerror_file(level, component, cmd, filename)         
\
+  do                                                                           
\
+  {                                                                            
\
+    GNUNET_log_from (level,                                                    
\
+                     component,                                                
\
+                     _ ("`%s' failed on file `%s' at %s:%d with error: %s\n"), 
\
+                     cmd,                                                      
\
+                     filename,                                                 
\
+                     __FILE__,                                                 
\
+                     __LINE__,                                                 
\
+                     STRERROR (errno));                                        
\
+  } while (0)
 
 /* ************************* endianess conversion ****************** */
 
@@ -965,12 +1075,12 @@ GNUNET_ntoh_double (double d);
  * Compare memory in @a a and @a b, where both must be of
  * the same pointer type.
  */
-#define GNUNET_memcmp(a,b) ({ \
-  const typeof(*b) * _a = (a); \
-  const typeof(*a) * _b = (b); \
-  memcmp(_a, \
-         _b, \
-         sizeof (*a)); })
+#define GNUNET_memcmp(a, b)       \
+  ({                              \
+    const typeof (*b) *_a = (a);  \
+    const typeof (*a) *_b = (b);  \
+    memcmp (_a, _b, sizeof (*a)); \
+  })
 
 
 /**
@@ -979,11 +1089,11 @@ GNUNET_ntoh_double (double d);
  * @param a pointer to a struct which should be tested for the
  *          entire memory being zero'ed out.
  */
-#define GNUNET_is_zero(a) ({ \
-  static const typeof(*a) _z;      \
-  memcmp((a), \
-         &_z, \
-         sizeof (_z)); })
+#define GNUNET_is_zero(a)           \
+  ({                                \
+    static const typeof (*a) _z;    \
+    memcmp ((a), &_z, sizeof (_z)); \
+  })
 
 
 /**
@@ -995,7 +1105,14 @@ GNUNET_ntoh_double (double d);
  * @param src source of the copy, may be NULL if @a n is zero
  * @param n number of bytes to copy
  */
-#define GNUNET_memcpy(dst,src,n) do { if (0 != n) { (void) memcpy (dst,src,n); 
} } while (0)
+#define GNUNET_memcpy(dst, src, n) \
+  do                               \
+  {                                \
+    if (0 != n)                    \
+    {                              \
+      (void) memcpy (dst, src, n); \
+    }                              \
+  } while (0)
 
 
 /**
@@ -1018,7 +1135,8 @@ GNUNET_ntoh_double (double d);
  * @param m size of the second dimension
  * @param type name of the struct or union, i.e. pass 'struct Foo'.
  */
-#define GNUNET_new_array_2d(n, m, type) (type **) GNUNET_xnew_array_2d_ (n, m, 
sizeof (type), __FILE__, __LINE__)
+#define GNUNET_new_array_2d(n, m, type) \
+  (type **) GNUNET_xnew_array_2d_ (n, m, sizeof (type), __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1030,7 +1148,8 @@ GNUNET_ntoh_double (double d);
  * @param o size of the third dimension
  * @param type name of the struct or union, i.e. pass 'struct Foo'.
  */
-#define GNUNET_new_array_3d(n, m, o, type) (type ***) GNUNET_xnew_array_3d_ 
(n, m, o, sizeof (type), __FILE__, __LINE__)
+#define GNUNET_new_array_3d(n, m, o, type) \
+  (type ***) GNUNET_xnew_array_3d_ (n, m, o, sizeof (type), __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1041,7 +1160,7 @@ GNUNET_ntoh_double (double d);
  *        smaller than 40 MB.
  * @return pointer to size bytes of memory, never NULL (!)
  */
-#define GNUNET_malloc(size) GNUNET_xmalloc_(size, __FILE__, __LINE__)
+#define GNUNET_malloc(size) GNUNET_xmalloc_ (size, __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1051,7 +1170,7 @@ GNUNET_ntoh_double (double d);
  * @param size the number of bytes in buf (and size of the allocation)
  * @return pointer to size bytes of memory, never NULL (!)
  */
-#define GNUNET_memdup(buf,size) GNUNET_xmemdup_(buf, size, __FILE__, __LINE__)
+#define GNUNET_memdup(buf, size) GNUNET_xmemdup_ (buf, size, __FILE__, 
__LINE__)
 
 /**
  * @ingroup memory
@@ -1061,7 +1180,8 @@ GNUNET_ntoh_double (double d);
  * @param size the number of bytes to allocate
  * @return pointer to size bytes of memory, NULL if we do not have enough 
memory
  */
-#define GNUNET_malloc_large(size) GNUNET_xmalloc_unchecked_(size, __FILE__, 
__LINE__)
+#define GNUNET_malloc_large(size) \
+  GNUNET_xmalloc_unchecked_ (size, __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1072,7 +1192,8 @@ GNUNET_ntoh_double (double d);
  * @param size the number of bytes to reallocate
  * @return pointer to size bytes of memory
  */
-#define GNUNET_realloc(ptr, size) GNUNET_xrealloc_(ptr, size, __FILE__, 
__LINE__)
+#define GNUNET_realloc(ptr, size) \
+  GNUNET_xrealloc_ (ptr, size, __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1083,7 +1204,7 @@ GNUNET_ntoh_double (double d);
  * @param ptr location where to free the memory. ptr must have
  *     been returned by #GNUNET_strdup, #GNUNET_strndup, #GNUNET_malloc or 
#GNUNET_array_grow earlier.
  */
-#define GNUNET_free(ptr) GNUNET_xfree_(ptr, __FILE__, __LINE__)
+#define GNUNET_free(ptr) GNUNET_xfree_ (ptr, __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1092,7 +1213,15 @@ GNUNET_ntoh_double (double d);
  *
  * @param ptr the location in memory to free
  */
-#define GNUNET_free_non_null(ptr) do { void * __x__ = ptr; if (__x__ != NULL) 
{ GNUNET_free(__x__); } } while(0)
+#define GNUNET_free_non_null(ptr) \
+  do                              \
+  {                               \
+    void *__x__ = ptr;            \
+    if (__x__ != NULL)            \
+    {                             \
+      GNUNET_free (__x__);        \
+    }                             \
+  } while (0)
 
 /**
  * @ingroup memory
@@ -1102,7 +1231,7 @@ GNUNET_ntoh_double (double d);
  * @param a pointer to a zero-terminated string
  * @return a copy of the string including zero-termination
  */
-#define GNUNET_strdup(a) GNUNET_xstrdup_(a,__FILE__,__LINE__)
+#define GNUNET_strdup(a) GNUNET_xstrdup_ (a, __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1113,7 +1242,8 @@ GNUNET_ntoh_double (double d);
  * @param length of the string to duplicate
  * @return a partial copy of the string including zero-termination
  */
-#define GNUNET_strndup(a,length) GNUNET_xstrndup_(a,length,__FILE__,__LINE__)
+#define GNUNET_strndup(a, length) \
+  GNUNET_xstrndup_ (a, length, __FILE__, __LINE__)
 
 /**
  * @ingroup memory
@@ -1150,7 +1280,13 @@ GNUNET_ntoh_double (double d);
  * @param tsize the target size for the resulting vector, use 0 to
  *        free the vector (then, arr will be NULL afterwards).
  */
-#define GNUNET_array_grow(arr,size,tsize) GNUNET_xgrow_((void**)&(arr), 
sizeof((arr)[0]), &size, tsize, __FILE__, __LINE__)
+#define GNUNET_array_grow(arr, size, tsize) \
+  GNUNET_xgrow_ ((void **) &(arr),          \
+                 sizeof ((arr)[0]),         \
+                 &size,                     \
+                 tsize,                     \
+                 __FILE__,                  \
+                 __LINE__)
 
 /**
  * @ingroup memory
@@ -1165,7 +1301,12 @@ GNUNET_ntoh_double (double d);
  *        array size
  * @param element the element that will be appended to the array
  */
-#define GNUNET_array_append(arr,size,element) do { 
GNUNET_array_grow(arr,size,size+1); (arr)[size-1] = element; } while(0)
+#define GNUNET_array_append(arr, size, element) \
+  do                                            \
+  {                                             \
+    GNUNET_array_grow (arr, size, size + 1);    \
+    (arr)[size - 1] = element;                  \
+  } while (0)
 
 /**
  * @ingroup memory
@@ -1226,8 +1367,11 @@ GNUNET_xmalloc_ (size_t size, const char *filename, int 
linenumber);
  * @return allocated memory, never NULL
  */
 void **
-GNUNET_xnew_array_2d_ (size_t n, size_t m, size_t elementSize,
-                       const char *filename, int linenumber);
+GNUNET_xnew_array_2d_ (size_t n,
+                       size_t m,
+                       size_t elementSize,
+                       const char *filename,
+                       int linenumber);
 
 
 /**
@@ -1246,8 +1390,12 @@ GNUNET_xnew_array_2d_ (size_t n, size_t m, size_t 
elementSize,
  * @return allocated memory, never NULL
  */
 void ***
-GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, size_t elementSize,
-                       const char *filename, int linenumber);
+GNUNET_xnew_array_3d_ (size_t n,
+                       size_t m,
+                       size_t o,
+                       size_t elementSize,
+                       const char *filename,
+                       int linenumber);
 
 
 /**
@@ -1262,7 +1410,9 @@ GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, 
size_t elementSize,
  * @return allocated memory, never NULL
  */
 void *
-GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename,
+GNUNET_xmemdup_ (const void *buf,
+                 size_t size,
+                 const char *filename,
                  int linenumber);
 
 
@@ -1323,7 +1473,9 @@ GNUNET_xstrdup_ (const char *str, const char *filename, 
int linenumber);
  * @return the duplicated string
  */
 char *
-GNUNET_xstrndup_ (const char *str, size_t len, const char *filename,
+GNUNET_xstrndup_ (const char *str,
+                  size_t len,
+                  const char *filename,
                   int linenumber);
 
 /**
@@ -1342,8 +1494,12 @@ GNUNET_xstrndup_ (const char *str, size_t len, const 
char *filename,
  * @param linenumber line where this call is being made (for debugging)
  */
 void
-GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
-               unsigned int newCount, const char *filename, int linenumber);
+GNUNET_xgrow_ (void **old,
+               size_t elementSize,
+               unsigned int *oldCount,
+               unsigned int newCount,
+               const char *filename,
+               int linenumber);
 
 
 /**
@@ -1475,7 +1631,7 @@ enum GNUNET_SCHEDULER_Priority
 };
 
 
-#if 0                           /* keep Emacsens' auto-indent happy */
+#if 0 /* keep Emacsens' auto-indent happy */
 {
 #endif
 #ifdef __cplusplus
diff --git a/src/transport/gnunet-service-tng.c 
b/src/transport/gnunet-service-tng.c
index f07e1c88d..56cf61c2b 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -24,15 +24,8 @@
  *
  * TODO:
  * Implement next:
- * - realize "pull" based logic (#handle_client_send()) for
- *   `struct PendingMessage` which waits for a queue on any
- *   applicable route to be 'ready', in contrast
- *   to the 'push' based routing we use for control messages.
- *   Basically, when a queue goes idle, it should "search"
- *   via its neighbour for either virtual links or DVH's that
- *   have it as first hop and then find messages in those
- *   virtual links!
- * - realize transport-to-transport flow control (needed in case
+ * - FIXME-NEXT: logic to decide which pm to pick for a given queue (sorting!)
+ * - FIXME-FC: realize transport-to-transport flow control (needed in case
  *   communicators do not offer flow control).  Note that we may not
  *   want to simply delay the ACKs as that may cause unnecessary
  *   re-transmissions. => Introduce proper flow and congestion window(s)!
@@ -1375,7 +1368,7 @@ struct DistanceVector
    * Do we have a confirmed working queue and are thus visible to
    * CORE?  If so, this is the virtual link, otherwise NULL.
    */
-  struct VirtualLink *link;
+  struct VirtualLink *vl;
 
   /**
    * Signature affirming @e ephemeral_key of type
@@ -1565,6 +1558,12 @@ struct Queue
    * Connection status for this queue.
    */
   enum GNUNET_TRANSPORT_ConnectionStatus cs;
+
+  /**
+   * Set to #GNUNET_YES if this queue is idle waiting for some
+   * virtual link to give it a pending message.
+   */
+  int idle;
 };
 
 
@@ -1696,7 +1695,7 @@ struct Neighbour
    * Do we have a confirmed working queue and are thus visible to
    * CORE?  If so, this is the virtual link, otherwise NULL.
    */
-  struct VirtualLink *link;
+  struct VirtualLink *vl;
 
   /**
    * Latest DVLearn monotonic time seen from this peer.  Initialized only
@@ -1766,17 +1765,7 @@ enum PendingMessageType
   /**
    * Reliability box.
    */
-  PMT_RELIABILITY_BOX = 2,
-
-  /**
-   * Any type of acknowledgement.
-   */
-  PMT_ACKNOWLEDGEMENT = 3,
-
-  /**
-   * Control traffic generated by the TRANSPORT service itself.
-   */
-  PMT_CONTROL = 4
+  PMT_RELIABILITY_BOX = 2
 
 };
 
@@ -2751,6 +2740,41 @@ free_distance_vector_hop (struct DistanceVectorHop *dvh)
 }
 
 
+/**
+ * Task run to check whether the hops of the @a cls still
+ * are validated, or if we need to core about disconnection.
+ *
+ * @param cls a `struct VirtualLink`
+ */
+static void
+check_link_down (void *cls);
+
+
+/**
+ * Send message to CORE clients that we lost a connection.
+ *
+ * @param pid peer the connection was for
+ */
+static void
+cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Informing CORE clients about disconnect from %s\n",
+              GNUNET_i2s (pid));
+  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
+  {
+    struct GNUNET_MQ_Envelope *env;
+    struct DisconnectInfoMessage *dim;
+
+    if (CT_CORE != tc->type)
+      continue;
+    env = GNUNET_MQ_msg (dim, GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
+    dim->peer = *pid;
+    GNUNET_MQ_send (tc->mq, env);
+  }
+}
+
+
 /**
  * Free entry in #dv_routes.  First frees all hops to the target, and
  * if there are no entries left, frees @a dv as well.
@@ -2766,11 +2790,33 @@ free_dv_route (struct DistanceVector *dv)
     free_distance_vector_hop (dvh);
   if (NULL == dv->dv_head)
   {
+    struct VirtualLink *vl;
+
     GNUNET_assert (
       GNUNET_YES ==
       GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv));
+    if (NULL != (vl = dv->vl))
+    {
+      GNUNET_assert (dv == vl->dv);
+      vl->dv = NULL;
+      if (NULL == vl->n)
+      {
+        cores_send_disconnect_info (&dv->target);
+        free_virtual_link (vl);
+      }
+      else
+      {
+        GNUNET_SCHEDULER_cancel (vl->visibility_task);
+        vl->visibility_task = GNUNET_SCHEDULER_add_now (&check_link_down, vl);
+      }
+      dv->vl = NULL;
+    }
+
     if (NULL != dv->timeout_task)
+    {
       GNUNET_SCHEDULER_cancel (dv->timeout_task);
+      dv->timeout_task = NULL;
+    }
     GNUNET_free (dv);
   }
 }
@@ -2950,6 +2996,7 @@ static void
 free_neighbour (struct Neighbour *neighbour)
 {
   struct DistanceVectorHop *dvh;
+  struct VirtualLink *vl;
 
   GNUNET_assert (NULL == neighbour->queue_head);
   GNUNET_assert (GNUNET_YES ==
@@ -2989,6 +3036,22 @@ free_neighbour (struct Neighbour *neighbour)
     GNUNET_PEERSTORE_store_cancel (neighbour->sc);
     neighbour->sc = NULL;
   }
+  if (NULL != (vl = neighbour->vl))
+  {
+    GNUNET_assert (neighbour == vl->n);
+    vl->n = NULL;
+    if (NULL == vl->dv)
+    {
+      cores_send_disconnect_info (&vl->target);
+      free_virtual_link (vl);
+    }
+    else
+    {
+      GNUNET_SCHEDULER_cancel (vl->visibility_task);
+      vl->visibility_task = GNUNET_SCHEDULER_add_now (&check_link_down, vl);
+    }
+    neighbour->vl = NULL;
+  }
   GNUNET_free (neighbour);
 }
 
@@ -3033,31 +3096,6 @@ cores_send_connect_info (const struct 
GNUNET_PeerIdentity *pid)
 }
 
 
-/**
- * Send message to CORE clients that we lost a connection.
- *
- * @param pid peer the connection was for
- */
-static void
-cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Informing CORE clients about disconnect from %s\n",
-              GNUNET_i2s (pid));
-  for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next)
-  {
-    struct GNUNET_MQ_Envelope *env;
-    struct DisconnectInfoMessage *dim;
-
-    if (CT_CORE != tc->type)
-      continue;
-    env = GNUNET_MQ_msg (dim, GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
-    dim->peer = *pid;
-    GNUNET_MQ_send (tc->mq, env);
-  }
-}
-
-
 /**
  * We believe we are ready to transmit a message on a queue. Gives the
  * message to the communicator for transmission (updating the tracker,
@@ -3070,19 +3108,15 @@ transmit_on_queue (void *cls);
 
 
 /**
- * Schedule next run of #transmit_on_queue().  Does NOTHING if
- * we should run immediately or if the message queue is empty.
- * Test for no task being added AND queue not being empty to
- * transmit immediately afterwards!  This function must only
- * be called if the message queue is non-empty!
+ * Called whenever something changed that might effect when we
+ * try to do the next transmission on @a queue using #transmit_on_queue().
  *
  * @param queue the queue to do scheduling for
- * @param inside_job set to #GNUNET_YES if called from
- *            #transmit_on_queue() itself and NOT setting
- *            the task means running immediately
+ * @param p task priority to use, if @a queue is scheduled
  */
 static void
-schedule_transmit_on_queue (struct Queue *queue, int inside_job)
+schedule_transmit_on_queue (struct Queue *queue,
+                            enum GNUNET_SCHEDULER_Priority p)
 {
   if (queue->tc->details.communicator.total_queue_length >=
       COMMUNICATOR_TOTAL_QUEUE_LIMIT)
@@ -3092,6 +3126,7 @@ schedule_transmit_on_queue (struct Queue *queue, int 
inside_job)
       "# Transmission throttled due to communicator queue limit",
       1,
       GNUNET_NO);
+    queue->idle = GNUNET_NO;
     return;
   }
   if (queue->queue_length >= QUEUE_LENGTH_LIMIT)
@@ -3100,38 +3135,18 @@ schedule_transmit_on_queue (struct Queue *queue, int 
inside_job)
                               "# Transmission throttled due to queue queue 
limit",
                               1,
                               GNUNET_NO);
+    queue->idle = GNUNET_NO;
     return;
   }
-#if FIXME - NEXT
-  struct Neighbour *n = queue->neighbour;
-  struct GNUNET_TIME_Relative out_delay;
-
-  if ((GNUNET_YES == inside_job) && (0 == out_delay.rel_value_us))
-  {
-    GNUNET_log (
-      GNUNET_ERROR_TYPE_DEBUG,
-      "Schedule transmission <%llu> on queue %llu of %s decides to run 
immediately\n",
-      pm->logging_uuid,
-      (unsigned long long) queue->qid,
-      GNUNET_i2s (&n->pid));
-    return; /* we should run immediately! */
-  }
-  /* queue has changed since we were scheduled, reschedule again */
+  /* queue might indeed be ready, schedule it */
+  if (NULL != queue->transmit_task)
+    GNUNET_SCHEDULER_cancel (queue->transmit_task);
   queue->transmit_task =
-    GNUNET_SCHEDULER_add_delayed (out_delay, &transmit_on_queue, queue);
-  if (out_delay.rel_value_us > DELAY_WARN_THRESHOLD.rel_value_us)
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Next transmission <%llu> on queue `%s' in %s (high delay)\n",
-                pm->logging_uuid,
-                queue->address,
-                GNUNET_STRINGS_relative_time_to_string (out_delay, 
GNUNET_YES));
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Next transmission <%llu> on queue `%s' in %s\n",
-                pm->logging_uuid,
-                queue->address,
-                GNUNET_STRINGS_relative_time_to_string (out_delay, 
GNUNET_YES));
-#endif
+    GNUNET_SCHEDULER_add_with_priority (p, &transmit_on_queue, queue);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Considering transmission on queue `%s' to %s\n",
+              queue->address,
+              GNUNET_i2s (&queue->neighbour->pid));
 }
 
 
@@ -3156,15 +3171,21 @@ check_link_down (void *cls)
        pos = pos->next_dv)
     dvh_timeout = GNUNET_TIME_absolute_max (dvh_timeout, 
pos->path_valid_until);
   if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
+  {
+    vl->dv->vl = NULL;
     vl->dv = NULL;
+  }
   q_timeout = GNUNET_TIME_UNIT_ZERO_ABS;
   for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour)
     q_timeout = GNUNET_TIME_absolute_max (q_timeout, q->validated_until);
-  if (0 == GNUNET_TIME_absolute_get_remaining (dvh_timeout).rel_value_us)
+  if (0 == GNUNET_TIME_absolute_get_remaining (q_timeout).rel_value_us)
+  {
+    vl->n->vl = NULL;
     vl->n = NULL;
+  }
   if ((NULL == vl->n) && (NULL == vl->dv))
   {
-    cores_send_disconnect_info (&dv->target);
+    cores_send_disconnect_info (&vl->target);
     free_virtual_link (vl);
     return;
   }
@@ -3229,7 +3250,7 @@ free_queue (struct Queue *queue)
   if ((maxxed) && (COMMUNICATOR_TOTAL_QUEUE_LIMIT <
                    tc->details.communicator.total_queue_length))
   {
-    /* Communicator dropped below threshold, resume all queues */
+    /* Communicator dropped below threshold, resume all _other_ queues */
     GNUNET_STATISTICS_update (
       GST_stats,
       "# Transmission throttled due to communicator queue limit",
@@ -3237,7 +3258,7 @@ free_queue (struct Queue *queue)
       GNUNET_NO);
     for (struct Queue *s = tc->details.communicator.queue_head; NULL != s;
          s = s->next_client)
-      schedule_transmit_on_queue (s, GNUNET_NO);
+      schedule_transmit_on_queue (s, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
   }
   notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
   GNUNET_free (queue);
@@ -3579,6 +3600,79 @@ pick_random_dv_hops (const struct DistanceVector *dv,
 }
 
 
+/**
+ * There is a message at the head of the pending messages for @a vl
+ * which may be ready for transmission. Check if a queue is ready to
+ * take it.
+ *
+ * This function must (1) check for flow control to ensure that we can
+ * right now send to @a vl, (2) check that the pending message in the
+ * queue is actually eligible, (3) determine if any applicable queue
+ * (direct neighbour or DVH path) is ready to accept messages, and
+ * (4) prioritize based on the preferences associated with the
+ * pending message.
+ *
+ * So yeah, easy.
+ *
+ * @param vl virtual link where we should check for transmission
+ */
+static void
+check_vl_transmission (struct VirtualLink *vl)
+{
+  struct Neighbour *n = vl->n;
+  struct DistanceVector *dv = vl->dv;
+  struct GNUNET_TIME_Absolute now;
+  int elig;
+
+  /* FIXME-FC: need to implement virtual link flow control! */
+
+  /* Check that we have an eligible pending message!
+     (cheaper than having #transmit_on_queue() find out!) */
+  elig = GNUNET_NO;
+  for (struct PendingMessage *pm = vl->pending_msg_head; NULL != pm;
+       pm = pm->next_vl)
+  {
+    if (NULL != pm->qe)
+      continue; /* not eligible, is in a queue! */
+    elig = GNUNET_YES;
+    break;
+  }
+  if (GNUNET_NO == elig)
+    return;
+
+  /* Notify queues at direct neighbours that we are interested */
+  now = GNUNET_TIME_absolute_get ();
+  if (NULL != n)
+  {
+    for (struct Queue *queue = n->queue_head; NULL != queue;
+         queue = queue->next_neighbour)
+      if ((GNUNET_YES == queue->idle) &&
+          (queue->validated_until.abs_value_us > now.abs_value_us))
+        schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
+  }
+  /* Notify queues via DV that we are interested */
+  if (NULL != dv)
+  {
+    /* Do DV with lower scheduler priority, which effectively means that
+       IF a neighbour exists and is available, we prefer it. */
+    for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos;
+         pos = pos->next_dv)
+    {
+      struct Neighbour *nh = pos->next_hop;
+
+      if (pos->path_valid_until.abs_value_us <= now.abs_value_us)
+        continue; /* skip this one: path not validated */
+      for (struct Queue *queue = nh->queue_head; NULL != queue;
+           queue = queue->next_neighbour)
+        if ((GNUNET_YES == queue->idle) &&
+            (queue->validated_until.abs_value_us > now.abs_value_us))
+          schedule_transmit_on_queue (queue,
+                                      GNUNET_SCHEDULER_PRIORITY_BACKGROUND);
+    }
+  }
+}
+
+
 /**
  * Client asked for transmission to a peer.  Process the request.
  *
@@ -3594,7 +3688,6 @@ handle_client_send (void *cls, const struct 
OutboundMessage *obm)
   uint32_t bytes_msg;
   struct VirtualLink *vl;
   enum GNUNET_MQ_PriorityPreferences pp;
-  int was_empty;
 
   GNUNET_assert (CT_CORE == tc->type);
   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
@@ -3631,32 +3724,11 @@ handle_client_send (void *cls, const struct 
OutboundMessage *obm)
                                 tc->details.core.pending_msg_head,
                                 tc->details.core.pending_msg_tail,
                                 pm);
-  was_empty = (NULL == vl->pending_msg_head);
   GNUNET_CONTAINER_MDLL_insert (vl,
                                 vl->pending_msg_head,
                                 vl->pending_msg_tail,
                                 pm);
-  if (! was_empty)
-    return; /* all queues must already be busy */
-#if 0
-  // FIXME: check if any DVH or neighbour queue of 'vl'
-  // is ready for transmission now. If so, encapsulate
-  // 'pm' accordingly and send!
-  for (struct Queue *queue = target->queue_head; NULL != queue;
-       queue = queue->next_neighbour)
-  {
-    /* try transmission on any queue that is idle */
-    if (NULL == queue->transmit_task)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Queue %llu to %s is idle, triggering transmission\n",
-                  (unsigned long long) queue->qid,
-                  GNUNET_i2s (&queue->neighbour->pid));
-      queue->transmit_task =
-        GNUNET_SCHEDULER_add_now (&transmit_on_queue, queue);
-    }
-  }
-#endif
+  check_vl_transmission (vl);
 }
 
 
@@ -3861,7 +3933,7 @@ update_ephemeral (struct DistanceVector *dv)
 
 
 /**
- * Send the control message @a payload on @a queue.
+ * Send the message @a payload on @a queue.
  *
  * @param queue the queue to use for transmission
  * @param pm pending message to update once transmission is done, may be NULL!
@@ -3879,6 +3951,7 @@ queue_send_msg (struct Queue *queue,
   struct GNUNET_TRANSPORT_SendMessageTo *smt;
   struct GNUNET_MQ_Envelope *env;
 
+  queue->idle = GNUNET_NO;
   GNUNET_log (
     GNUNET_ERROR_TYPE_DEBUG,
     "Queueing %u bytes of payload for transmission <%llu> on queue %llu to 
%s\n",
@@ -3910,6 +3983,11 @@ queue_send_msg (struct Queue *queue,
     GNUNET_assert (CT_COMMUNICATOR == queue->tc->type);
     queue->queue_length++;
     queue->tc->details.communicator.total_queue_length++;
+    if (COMMUNICATOR_TOTAL_QUEUE_LIMIT ==
+        queue->tc->details.communicator.total_queue_length)
+      queue->idle = GNUNET_NO;
+    if (QUEUE_LENGTH_LIMIT == queue->queue_length)
+      queue->idle = GNUNET_NO;
     GNUNET_MQ_send (queue->tc->mq, env);
   }
 }
@@ -5209,6 +5287,50 @@ update_dvh_performance (struct DistanceVectorHop *dvh,
 }
 
 
+/**
+ * We have completed transmission of @a pm, remove it from
+ * the transmission queues (and if it is a fragment, continue
+ * up the tree as necessary).
+ *
+ * @param pm pending message that was transmitted
+ */
+static void
+completed_pending_message (struct PendingMessage *pm)
+{
+  struct PendingMessage *pos;
+
+  switch (pm->pmt)
+  {
+  case PMT_CORE:
+  case PMT_RELIABILITY_BOX:
+    /* Full message sent, we are done */
+    client_send_response (pm);
+    return;
+  case PMT_FRAGMENT_BOX:
+    /* Fragment sent over reliabile channel */
+    free_fragment_tree (pm);
+    pos = pm->frag_parent;
+    GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
+    GNUNET_free (pm);
+    /* check if subtree is done */
+    while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
+           (pos != pm))
+    {
+      pm = pos;
+      pos = pm->frag_parent;
+      GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, pm);
+      GNUNET_free (pm);
+    }
+
+    /* Was this the last applicable fragmment? */
+    if ((NULL == pos->head_frag) && (NULL == pos->frag_parent) &&
+        (pos->frag_off == pos->bytes_msg))
+      client_send_response (pos);
+    return;
+  }
+}
+
+
 /**
  * The @a pa was acknowledged, process the acknowledgement.
  *
@@ -5220,7 +5342,6 @@ static void
 handle_acknowledged (struct PendingAcknowledgement *pa,
                      struct GNUNET_TIME_Relative ack_delay)
 {
-  struct PendingMessage *pm = pa->pm;
   struct GNUNET_TIME_Relative delay;
 
   delay = GNUNET_TIME_absolute_get_duration (pa->transmission_time);
@@ -5232,25 +5353,8 @@ handle_acknowledged (struct PendingAcknowledgement *pa,
     update_queue_performance (pa->queue, delay, pa->message_size);
   if (NULL != pa->dvh)
     update_dvh_performance (pa->dvh, delay, pa->message_size);
-  if (NULL != pm)
-  {
-    if (NULL != pm->frag_parent)
-    {
-      pm = pm->frag_parent;
-      free_fragment_tree (pa->pm);
-    }
-    while ((NULL != pm->frag_parent) && (NULL == pm->head_frag))
-    {
-      struct PendingMessage *parent = pm->frag_parent;
-
-      free_fragment_tree (pm);
-      pm = parent;
-    }
-    if (NULL != pm->head_frag)
-      pm = NULL; /* we are done, otherwise free 'pm' below */
-  }
-  if (NULL != pm)
-    free_pending_message (pm);
+  if (NULL != pa->pm)
+    completed_pending_message (pa->pm);
   free_pending_acknowledgement (pa);
 }
 
@@ -5494,6 +5598,7 @@ activate_core_visible_dv_path (struct DistanceVectorHop 
*hop)
     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
   vl->target = dv->target;
   vl->dv = dv;
+  dv->vl = vl;
   vl->core_recv_window = RECV_WINDOW_SIZE;
   vl->visibility_task =
     GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl);
@@ -7185,6 +7290,7 @@ handle_validation_response (
   vl = GNUNET_new (struct VirtualLink);
   vl->target = n->pid;
   vl->n = n;
+  n->vl = vl;
   vl->core_recv_window = RECV_WINDOW_SIZE;
   vl->visibility_task =
     GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl);
@@ -7604,10 +7710,134 @@ update_pm_next_attempt (struct PendingMessage *pm,
 
 
 /**
- * We believe we are ready to transmit a message on a queue.
- * Gives the message to the
- * communicator for transmission (updating the tracker, and re-scheduling
- * itself if applicable).
+ * Context for #select_best_pending_from_link().
+ */
+struct PendingMessageScoreContext
+{
+  /**
+   * Set to the best message that was found, NULL for none.
+   */
+  struct PendingMessage *best;
+
+  /**
+   * DVH that @e best should take, or NULL for direct transmission.
+   */
+  struct DistanceVectorHop *dvh;
+
+  /**
+   * What is the estimated total overhead for this message?
+   */
+  size_t real_overhead;
+
+  /**
+   * Number of pending messages we seriously considered this time.
+   */
+  unsigned int consideration_counter;
+
+  /**
+   * Did we have to fragment?
+   */
+  int frag;
+
+  /**
+   * Did we have to reliability box?
+   */
+  int relb;
+};
+
+
+/**
+ * Select the best pending message from @a vl for transmission
+ * via @a queue.
+ *
+ * @param sc[in,out] best message so far (NULL for none), plus scoring data
+ * @param queue the queue that will be used for transmission
+ * @param vl the virtual link providing the messages
+ * @param dvh path we are currently considering, or NULL for none
+ * @param overhead number of bytes of overhead to be expected
+ *        from DV encapsulation (0 for without DV)
+ */
+static void
+select_best_pending_from_link (struct PendingMessageScoreContext *sc,
+                               struct Queue *queue,
+                               struct VirtualLink *vl,
+                               struct DistanceVectorHop *dvh,
+                               size_t overhead)
+{
+  /* FIXME-NEXT: right now we ignore all the 'fancy' sorting
+     we do on the pending message list, resulting in a
+     linear time algorithm (PLUS linear time list management).
+     So we should probably either avoid keeping a sorted list,
+     or find a way to make the sorting useful here! */
+  for (struct PendingMessage *pos = vl->pending_msg_head; NULL != pos;
+       pos = pos->next_vl)
+  {
+    size_t real_overhead = overhead;
+    int frag;
+    int relb;
+
+    if (NULL != pos->qe)
+      continue; /* not eligible */
+    sc->consideration_counter++;
+    /* determine if we have to reliability-box, if so add reliability box
+       overhead */
+    relb = GNUNET_NO;
+    if ((GNUNET_NO == frag) &&
+        (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) &&
+        (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc))
+    {
+      relb = GNUNET_YES;
+      real_overhead += sizeof (struct TransportReliabilityBoxMessage);
+    }
+    /* determine if we have to fragment, if so add fragmentation
+       overhead! */
+    frag = GNUNET_NO;
+    if ( ( (0 != queue->mtu) &&
+           (pos->bytes_msg + real_overhead > queue->mtu) ) ||
+         (pos->bytes_msg > UINT16_MAX - sizeof (struct 
GNUNET_TRANSPORT_SendMessageTo)) ||
+         (NULL != pos->head_frag /* fragments already exist, should
+                                    respect that even if MTU is 0 for
+                                    this queue */) )
+    {
+      frag = GNUNET_YES;
+      relb = GNUNET_NO; /* if we fragment, we never also reliability box */
+      if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc)
+      {
+        /* FIXME-OPTIMIZE: we could use an optimized, shorter fragmentation
+           header without the ACK UUID when using a *reliable* channel! */
+      }
+      real_overhead = overhead + sizeof (struct TransportFragmentBoxMessage);
+    }
+
+    /* Finally, compare to existing 'best' in sc to see if this 'pos' pending
+       message would beat it! */
+    if (NULL != sc->best)
+    {
+      /* FIXME-NEXT: CHECK if pos fits queue BETTER than pm, if not:
+         continue; */
+      /* NOTE: use 'overhead' to estimate need for fragmentation,
+         prefer it if MTU is sufficient and close! */
+    }
+    sc->best = pos;
+    sc->dvh = dvh;
+    sc->frag = frag;
+    sc->relb = relb;
+  }
+}
+
+
+/**
+ * We believe we are ready to transmit a `struct PendingMessage` on a
+ * queue, the big question is which one!  We need to see if there is
+ * one pending that is allowed by flow control and congestion control
+ * and (ideally) matches our queue's performance profile.
+ *
+ * If such a message is found, we give the message to the communicator
+ * for transmission (updating the tracker, and re-scheduling ourselves
+ * if applicable).
+ *
+ * If no such message is found, the queue's `idle` field must be set
+ * to #GNUNET_YES.
  *
  * @param cls the `struct Queue` to process transmissions for
  */
@@ -7615,128 +7845,99 @@ static void
 transmit_on_queue (void *cls)
 {
   struct Queue *queue = cls;
-
-  queue->transmit_task = NULL;
-#if FIXME - NEXT
   struct Neighbour *n = queue->neighbour;
+  struct PendingMessageScoreContext sc;
   struct PendingMessage *pm;
-  struct PendingMessage *s;
-  uint32_t overhead;
 
-  if (NULL == (pm = n->pending_msg_head))
+  queue->transmit_task = NULL;
+  if (NULL == n->vl)
   {
-    /* no message pending, nothing to do here! */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No messages waiting on queue %s to %s, going to sleep\n",
-                queue->address,
-                GNUNET_i2s (&n->pid));
+                "Virtual link `%s' is down, cannot have PM for queue `%s'\n",
+                GNUNET_i2s (&n->pid),
+                queue->address);
+    queue->idle = GNUNET_YES;
     return;
   }
-  if (NULL != pm->qe)
+  memset (&sc, 0, sizeof (sc));
+  select_best_pending_from_link (&sc, queue, n->vl, NULL, 0);
+  if (NULL == sc.best)
+  {
+    /* Also look at DVH that have the n as first hop! */
+    for (struct DistanceVectorHop *dvh = n->dv_head; NULL != dvh;
+         dvh = dvh->next_neighbour)
+    {
+      select_best_pending_from_link (&sc,
+                                     queue,
+                                     dvh->dv->vl,
+                                     dvh,
+                                     sizeof (struct GNUNET_PeerIdentity) *
+                                         (1 + dvh->distance) +
+                                       sizeof (struct TransportDVBoxMessage) +
+                                       sizeof (struct TransportDVBoxPayloadP));
+    }
+  }
+  if (NULL == sc.best)
   {
-    /* message still pending with communciator!
-       LOGGING-FIXME: Use stats? Should this not be rare? */
+    /* no message pending, nothing to do here! */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Waiting on communicator for queue %s to %s, going to sleep\n",
+                "No pending messages, queue `%s' to %s now idle\n",
                 queue->address,
                 GNUNET_i2s (&n->pid));
+    queue->idle = GNUNET_YES;
     return;
   }
-  schedule_transmit_on_queue (queue, GNUNET_YES);
-  if (NULL != queue->transmit_task)
+
+  /* Given selection in `sc`, do transmission */
+  pm = sc.best;
+  if (GNUNET_YES == sc.frag)
   {
-    GNUNET_log (
-      GNUNET_ERROR_TYPE_DEBUG,
-      "Scheduled transmission on queue %s to %s for later, going to sleep\n",
-      queue->address,
-      GNUNET_i2s (&n->pid));
-    return; /* do it later */
-  }
-  overhead = 0;
-  if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)
-    overhead += sizeof (struct TransportReliabilityBoxMessage);
-  s = pm;
-  if ( ( (0 != queue->mtu) &&
-        (pm->bytes_msg + overhead > queue->mtu) ) ||
-       (pm->bytes_msg > UINT16_MAX - sizeof (struct 
GNUNET_TRANSPORT_SendMessageTo)) ||
-       (NULL != pm->head_frag /* fragments already exist, should
-                                respect that even if MTU is 0 for
-                                this queue */) )
-    s = fragment_message (queue, pm->dvh, s);
-  if (NULL == s)
-  {
-    /* Fragmentation failed, try next message... */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Fragmentation failed queue %s to %s for <%llu>, trying 
again\n",
-                queue->address,
-                GNUNET_i2s (&n->pid),
-                pm->logging_uuid);
-    schedule_transmit_on_queue (queue, GNUNET_NO);
-    return;
+    pm = fragment_message (queue, sc.dvh, sc.best);
+    if (NULL == pm)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Fragmentation failed queue %s to %s for <%llu>, trying 
again\n",
+                  queue->address,
+                  GNUNET_i2s (&n->pid),
+                  pm->logging_uuid);
+      schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
+    }
   }
-  if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)
-    // FIXME-OPTIMIZE: and if reliability was requested for 's' by core!
-    s = reliability_box_message (queue, pm->dvh, s);
-  if (NULL == s)
+  else if (GNUNET_YES == sc.relb)
   {
-    /* Reliability boxing failed, try next message... */
-    GNUNET_log (
-      GNUNET_ERROR_TYPE_DEBUG,
-      "Reliability boxing failed queue %s to %s for <%llu>, trying again\n",
-      queue->address,
-      GNUNET_i2s (&n->pid),
-      pm->logging_uuid);
-    schedule_transmit_on_queue (queue, GNUNET_NO);
-    return;
+    pm = reliability_box_message (queue, sc.dvh, sc.best);
+    if (NULL == pm)
+    {
+      /* Reliability boxing failed, try next message... */
+      GNUNET_log (
+        GNUNET_ERROR_TYPE_DEBUG,
+        "Reliability boxing failed queue %s to %s for <%llu>, trying again\n",
+        queue->address,
+        GNUNET_i2s (&n->pid),
+        pm->logging_uuid);
+      schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
+      return;
+    }
   }
+  else
+    pm = sc.best; /* no boxing required */
 
-  /* Pass 's' for transission to the communicator */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Passing message <%llu> to queue %s for peer %s\n",
-              s->logging_uuid,
-              queue->address,
-              GNUNET_i2s (&n->pid));
-  queue_send_msg (queue, s, &s[1], s->bytes_msg);
-  // FIXME: do something similar to the logic below
-  // in defragmentation / reliability ACK handling!
+  /* Pass 'pm' for transission to the communicator */
+  GNUNET_log (
+    GNUNET_ERROR_TYPE_DEBUG,
+    "Passing message <%llu> to queue %s for peer %s (considered %u others)\n",
+    pm->logging_uuid,
+    queue->address,
+    GNUNET_i2s (&n->pid),
+    sc.consideration_counter);
+  queue_send_msg (queue, pm, &pm[1], pm->bytes_msg);
 
   /* Check if this transmission somehow conclusively finished handing 'pm'
      even without any explicit ACKs */
-  if ((PMT_CORE == s->pmt) &&
+  if ((PMT_CORE == pm->pmt) ||
       (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc))
   {
-    /* Full message sent, and over reliabile channel */
-    client_send_response (pm);
-  }
-  else if ((GNUNET_TRANSPORT_CC_RELIABLE ==
-            queue->tc->details.communicator.cc) &&
-           (PMT_FRAGMENT_BOX == s->pmt))
-  {
-    struct PendingMessage *pos;
-
-    /* Fragment sent over reliabile channel */
-    free_fragment_tree (s);
-    pos = s->frag_parent;
-    GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, s);
-    GNUNET_free (s);
-    /* check if subtree is done */
-    while ((NULL == pos->head_frag) && (pos->frag_off == pos->bytes_msg) &&
-           (pos != pm))
-    {
-      s = pos;
-      pos = s->frag_parent;
-      GNUNET_CONTAINER_MDLL_remove (frag, pos->head_frag, pos->tail_frag, s);
-      GNUNET_free (s);
-    }
-
-    /* Was this the last applicable fragmment? */
-    if ((NULL == pm->head_frag) && (pm->frag_off == pm->bytes_msg))
-      client_send_response (pm);
-  }
-  else if (PMT_CORE != pm->pmt)
-  {
-    /* This was an acknowledgement of some type, always free */
-    free_pending_message (pm);
+    completed_pending_message (pm);
   }
   else
   {
@@ -7748,15 +7949,13 @@ transmit_on_queue (void *cls)
        retransmitting.  Note that in the future this heuristic should
        likely be improved further (measure RTT stability, consider
        message urgency and size when delaying ACKs, etc.) */
-    update_pm_next_attempt (s,
+    update_pm_next_attempt (pm,
                             GNUNET_TIME_relative_to_absolute (
                               GNUNET_TIME_relative_multiply 
(queue->pd.aged_rtt,
                                                              4)));
   }
-
   /* finally, re-schedule queue transmission task itself */
-  schedule_transmit_on_queue (queue, GNUNET_NO);
-#endif
+  schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
 }
 
 
@@ -7871,7 +8070,7 @@ handle_send_message_ack (void *cls,
     for (struct Queue *queue = tc->details.communicator.queue_head;
          NULL != queue;
          queue = queue->next_client)
-      schedule_transmit_on_queue (queue, GNUNET_NO);
+      schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
   }
   else if (QUEUE_LENGTH_LIMIT - 1 == qe->queue->queue_length)
   {
@@ -7880,7 +8079,7 @@ handle_send_message_ack (void *cls,
                               "# Transmission throttled due to queue queue 
limit",
                               -1,
                               GNUNET_NO);
-    schedule_transmit_on_queue (qe->queue, GNUNET_NO);
+    schedule_transmit_on_queue (qe->queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
   }
 
   if (NULL != (pm = qe->pm))
@@ -7894,21 +8093,7 @@ handle_send_message_ack (void *cls,
        transmit on queue for queues of the neighbour */
     vl = pm->vl;
     if (vl->pending_msg_head == pm)
-    {
-#if FIXME - NEXT
-      for (struct Queue *queue = n->queue_head; NULL != queue;
-           queue = queue->next_neighbour)
-        schedule_transmit_on_queue (queue, GNUNET_NO);
-#endif
-    }
-    if (GNUNET_OK != ntohl (sma->status))
-    {
-      GNUNET_log (
-        GNUNET_ERROR_TYPE_INFO,
-        "Queue failed in transmission <%llu>, will try retransmission 
immediately\n",
-        pm->logging_uuid);
-      update_pm_next_attempt (pm, GNUNET_TIME_UNIT_ZERO_ABS);
-    }
+      check_vl_transmission (vl);
   }
   GNUNET_free (qe);
 }
@@ -8431,6 +8616,7 @@ 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;
+  queue->idle = GNUNET_YES;
   memcpy (&queue[1], addr, addr_len);
   /* notify monitors about new queue */
   {
@@ -8452,6 +8638,8 @@ handle_add_queue_message (void *cls,
                                                 &aqm->receiver,
                                                 
&check_validation_request_pending,
                                                 queue);
+  /* look for traffic for this queue */
+  schedule_transmit_on_queue (queue, GNUNET_SCHEDULER_PRIORITY_DEFAULT);
   /* might be our first queue, try launching DV learning */
   if (NULL == dvlearn_task)
     dvlearn_task = GNUNET_SCHEDULER_add_now (&start_dv_learn, NULL);

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



reply via email to

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