gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r16808 - in gnunet: contrib src/ats src/transport


From: gnunet
Subject: [GNUnet-SVN] r16808 - in gnunet: contrib src/ats src/transport
Date: Tue, 13 Sep 2011 14:40:14 +0200

Author: grothoff
Date: 2011-09-13 14:40:14 +0200 (Tue, 13 Sep 2011)
New Revision: 16808

Added:
   gnunet/src/ats/gnunet-service-transport_ats.c
   gnunet/src/ats/gnunet-service-transport_ats.h
   gnunet/src/transport/gnunet-service-transport.c
Removed:
   gnunet/src/transport/gnunet-service-transport-new.c
   gnunet/src/transport/gnunet-service-transport.c
   gnunet/src/transport/gnunet-service-transport_ats.c
   gnunet/src/transport/gnunet-service-transport_ats.h
Modified:
   gnunet/contrib/defaults.conf
   gnunet/src/transport/Makefile.am
Log:
make new current

Modified: gnunet/contrib/defaults.conf
===================================================================
--- gnunet/contrib/defaults.conf        2011-09-13 12:25:52 UTC (rev 16807)
+++ gnunet/contrib/defaults.conf        2011-09-13 12:40:14 UTC (rev 16808)
@@ -216,7 +216,7 @@
 HOSTNAME = localhost
 HOME = $SERVICEHOME
 CONFIG = $DEFAULTCONFIG
-BINARY = gnunet-service-transport-new
+BINARY = gnunet-service-transport
 #PREFIX = valgrind
 NEIGHBOUR_LIMIT = 50
 ACCEPT_FROM = 127.0.0.1;

Copied: gnunet/src/ats/gnunet-service-transport_ats.c (from rev 16807, 
gnunet/src/transport/gnunet-service-transport_ats.c)
===================================================================
--- gnunet/src/ats/gnunet-service-transport_ats.c                               
(rev 0)
+++ gnunet/src/ats/gnunet-service-transport_ats.c       2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -0,0 +1,1754 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file transport/gnunet-service-transport_ats.c
+ * @brief automatic transport selection
+ * @author Matthias Wachs
+ *
+ */
+
+
+#include "gnunet-service-transport_ats.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_container_lib.h"
+
+
+
+
+
+/* LP/MIP problem object */
+
+#if !HAVE_LIBGLPK
+
+#ifndef GLP_PROB_DEFINED
+#define GLP_PROB_DEFINED
+typedef struct
+{
+  double _opaque_prob[100];
+} glp_prob;
+#endif
+
+typedef struct
+{                               /* integer optimizer control parameters */
+  int msg_lev;                  /* message level (see glp_smcp) */
+  int br_tech;                  /* branching technique: */
+#define GLP_BR_FFV         1    /* first fractional variable */
+#define GLP_BR_LFV         2    /* last fractional variable */
+#define GLP_BR_MFV         3    /* most fractional variable */
+#define GLP_BR_DTH         4    /* heuristic by Driebeck and Tomlin */
+#define GLP_BR_PCH         5    /* hybrid pseudocost heuristic */
+  int bt_tech;                  /* backtracking technique: */
+#define GLP_BT_DFS         1    /* depth first search */
+#define GLP_BT_BFS         2    /* breadth first search */
+#define GLP_BT_BLB         3    /* best local bound */
+#define GLP_BT_BPH         4    /* best projection heuristic */
+  double tol_int;               /* mip.tol_int */
+  double tol_obj;               /* mip.tol_obj */
+  int tm_lim;                   /* mip.tm_lim (milliseconds) */
+  int out_frq;                  /* mip.out_frq (milliseconds) */
+  int out_dly;                  /* mip.out_dly (milliseconds) */
+  /* mip.cb_func */
+  void *cb_info;                /* mip.cb_info */
+  int cb_size;                  /* mip.cb_size */
+  int pp_tech;                  /* preprocessing technique: */
+#define GLP_PP_NONE        0    /* disable preprocessing */
+#define GLP_PP_ROOT        1    /* preprocessing only on root level */
+#define GLP_PP_ALL         2    /* preprocessing on all levels */
+  double mip_gap;               /* relative MIP gap tolerance */
+  int mir_cuts;                 /* MIR cuts       (GLP_ON/GLP_OFF) */
+  int gmi_cuts;                 /* Gomory's cuts  (GLP_ON/GLP_OFF) */
+  int cov_cuts;                 /* cover cuts     (GLP_ON/GLP_OFF) */
+  int clq_cuts;                 /* clique cuts    (GLP_ON/GLP_OFF) */
+  int presolve;                 /* enable/disable using MIP presolver */
+  int binarize;                 /* try to binarize integer variables */
+  int fp_heur;                  /* feasibility pump heuristic */
+#if 1                           /* 28/V-2010 */
+  int alien;                    /* use alien solver */
+#endif
+  double foo_bar[29];           /* (reserved) */
+} glp_iocp;
+
+typedef struct
+{                               /* simplex method control parameters */
+  int msg_lev;                  /* message level: */
+#define GLP_MSG_OFF        0    /* no output */
+#define GLP_MSG_ERR        1    /* warning and error messages only */
+#define GLP_MSG_ON         2    /* normal output */
+#define GLP_MSG_ALL        3    /* full output */
+#define GLP_MSG_DBG        4    /* debug output */
+  int meth;                     /* simplex method option: */
+#define GLP_PRIMAL         1    /* use primal simplex */
+#define GLP_DUALP          2    /* use dual; if it fails, use primal */
+#define GLP_DUAL           3    /* use dual simplex */
+  int pricing;                  /* pricing technique: */
+#define GLP_PT_STD      0x11    /* standard (Dantzig rule) */
+#define GLP_PT_PSE      0x22    /* projected steepest edge */
+  int r_test;                   /* ratio test technique: */
+#define GLP_RT_STD      0x11    /* standard (textbook) */
+#define GLP_RT_HAR      0x22    /* two-pass Harris' ratio test */
+  double tol_bnd;               /* spx.tol_bnd */
+  double tol_dj;                /* spx.tol_dj */
+  double tol_piv;               /* spx.tol_piv */
+  double obj_ll;                /* spx.obj_ll */
+  double obj_ul;                /* spx.obj_ul */
+  int it_lim;                   /* spx.it_lim */
+  int tm_lim;                   /* spx.tm_lim (milliseconds) */
+  int out_frq;                  /* spx.out_frq */
+  int out_dly;                  /* spx.out_dly (milliseconds) */
+  int presolve;                 /* enable/disable using LP presolver */
+  double foo_bar[36];           /* (reserved) */
+} glp_smcp;
+
+/* optimization direction flag: */
+#define GLP_MIN            1    /* minimization */
+#define GLP_MAX            2    /* maximization */
+
+/* kind of structural variable: */
+#define GLP_CV             1    /* continuous variable */
+#define GLP_IV             2    /* integer variable */
+#define GLP_BV             3    /* binary variable */
+
+/* type of auxiliary/structural variable: */
+#define GLP_FR             1    /* free variable */
+#define GLP_LO             2    /* variable with lower bound */
+#define GLP_UP             3    /* variable with upper bound */
+#define GLP_DB             4    /* double-bounded variable */
+#define GLP_FX             5    /* fixed variable */
+
+/* solution indicator: */
+#define GLP_SOL            1    /* basic solution */
+#define GLP_IPT            2    /* interior-point solution */
+#define GLP_MIP            3    /* mixed integer solution */
+
+/* solution status: */
+#define GLP_UNDEF          1    /* solution is undefined */
+#define GLP_FEAS           2    /* solution is feasible */
+#define GLP_INFEAS         3    /* solution is infeasible */
+#define GLP_NOFEAS         4    /* no feasible solution exists */
+#define GLP_OPT            5    /* solution is optimal */
+#define GLP_UNBND          6    /* solution is unbounded */
+
+/* return codes: */
+#define GLP_EBADB       0x01    /* invalid basis */
+#define GLP_ESING       0x02    /* singular matrix */
+#define GLP_ECOND       0x03    /* ill-conditioned matrix */
+#define GLP_EBOUND      0x04    /* invalid bounds */
+#define GLP_EFAIL       0x05    /* solver failed */
+#define GLP_EOBJLL      0x06    /* objective lower limit reached */
+#define GLP_EOBJUL      0x07    /* objective upper limit reached */
+#define GLP_EITLIM      0x08    /* iteration limit exceeded */
+#define GLP_ETMLIM      0x09    /* time limit exceeded */
+#define GLP_ENOPFS      0x0A    /* no primal feasible solution */
+#define GLP_ENODFS      0x0B    /* no dual feasible solution */
+#define GLP_EROOT       0x0C    /* root LP optimum not provided */
+#define GLP_ESTOP       0x0D    /* search terminated by application */
+#define GLP_EMIPGAP     0x0E    /* relative mip gap tolerance reached */
+#define GLP_ENOFEAS     0x0F    /* no primal/dual feasible solution */
+#define GLP_ENOCVG      0x10    /* no convergence */
+#define GLP_EINSTAB     0x11    /* numerical instability */
+#define GLP_EDATA       0x12    /* invalid data */
+#define GLP_ERANGE      0x13    /* result out of range */
+
+/* enable/disable flag: */
+#define GLP_ON             1    /* enable something */
+#define GLP_OFF            0    /* disable something */
+
+#endif
+
+/*
+ * Wrappers for GLPK Functions
+ */
+
+
+void *
+_lp_create_prob (void)
+{
+#if HAVE_LIBGLPK
+  return glp_create_prob ();
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return NULL;
+}
+
+void
+_lp_set_obj_dir (glp_prob *P, int dir)
+{
+#if HAVE_LIBGLPK
+  return glp_set_obj_dir (P, dir);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+void
+_lp_set_prob_name (glp_prob *P, const char *name)
+{
+#if HAVE_LIBGLPK
+  glp_set_prob_name (P, name);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+int
+_lp_add_cols (glp_prob *P, int ncs)
+{
+#if HAVE_LIBGLPK
+  return glp_add_cols (P, ncs);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+int
+_lp_add_rows (glp_prob *P, int nrs)
+{
+#if HAVE_LIBGLPK
+  return glp_add_rows (P, nrs);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+
+void
+_lp_set_row_bnds (glp_prob *P, int i, int type, double lb, double ub)
+{
+#if HAVE_LIBGLPK
+  glp_set_row_bnds (P, i, type, lb, ub);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+void
+_lp_init_smcp (void *parm)
+{
+#if HAVE_LIBGLPK
+  glp_init_smcp (parm);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+void
+_lp_set_col_name (glp_prob *P, int j, const char *name)
+{
+#if HAVE_LIBGLPK
+  glp_set_col_name (P, j, name);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+void
+_lp_set_col_bnds (glp_prob *P, int j, int type, double lb, double ub)
+{
+#if HAVE_LIBGLPK
+  glp_set_col_bnds (P, j, type, lb, ub);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+void
+_lp_set_obj_coef (glp_prob *P, int j, double coef)
+{
+#if HAVE_LIBGLPK
+  glp_set_obj_coef (P, j, coef);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+void
+_lp_delete_prob (void *P)
+{
+#if HAVE_LIBGLPK
+  glp_delete_prob (P);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+static int
+_lp_simplex (glp_prob *P, void *parm)
+{
+#if HAVE_LIBGLPK
+  return glp_simplex (P, parm);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+static void
+_lp_load_matrix (glp_prob *P, int ne, const int ia[], const int ja[],
+                 const double ar[])
+{
+#if HAVE_LIBGLPK
+  glp_load_matrix (P, ne, ia, ja, ar);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+static void
+_lp_set_mat_row (glp_prob *P, int i, int len, const int ind[],
+                 const double val[])
+{
+#if HAVE_LIBGLPK
+  glp_set_mat_row (P, i, len, ind, val);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+static int
+_lp_write_lp (glp_prob *P, const void *parm, const char *fname)
+{
+#if HAVE_LIBGLPK
+  return glp_write_lp (P, parm, fname);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+static void
+_lp_init_iocp (void *parm)
+{
+#if HAVE_LIBGLPK
+  glp_init_iocp (parm);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+static int
+_lp_intopt (glp_prob *P, const void *parm)
+{
+#if HAVE_LIBGLPK
+  return glp_intopt (P, parm);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+static int
+_lp_get_status (glp_prob *P)
+{
+#if HAVE_LIBGLPK
+  return glp_get_status (P);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+static int
+_lp_mip_status (glp_prob *P)
+{
+#if HAVE_LIBGLPK
+  return glp_mip_status (P);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+static void
+_lp_set_col_kind (glp_prob *P, int j, int kind)
+{
+#if HAVE_LIBGLPK
+  glp_set_col_kind (P, j, kind);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+static void
+_lp_free_env (void)
+{
+#if HAVE_LIBGLPK
+  glp_free_env ();
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+}
+
+static const char *
+_lp_get_col_name (glp_prob *P, int j)
+{
+#if HAVE_LIBGLPK
+  return glp_get_col_name (P, j);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return NULL;
+}
+
+static double
+_lp_mip_obj_val (glp_prob *P)
+{
+#if HAVE_LIBGLPK
+  return glp_mip_obj_val (P);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0.0;
+}
+
+
+static double
+_lp_get_col_prim (glp_prob *P, int j)
+{
+#if HAVE_LIBGLPK
+  return glp_get_col_prim (P, j);
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0.0;
+}
+
+static int
+_lp_print_sol (glp_prob *P, const char *fname)
+{
+#if HAVE_LIBGLPK
+#else
+  // Function not implemented
+  GNUNET_break (0);
+#endif
+  return 0;
+}
+
+/*
+ * Dummy functions for CFLAGS
+ */
+
+static void
+_dummy2 ();
+static void
+_dummy ()
+{
+  return;
+  _lp_get_col_name (NULL, 0);
+  _lp_mip_obj_val (NULL);
+  _lp_get_col_prim (NULL, 0);
+  _lp_set_mat_row (NULL, 0, 0, NULL, NULL);
+  _dummy2 ();
+}
+
+
+
+static void
+_dummy2 ()
+{
+  ats_modify_problem_state (NULL, 0);
+  qm[1].atis_index = 0;
+  _dummy ();
+  int t = ATS_COST_UPDATED + ATS_MODIFIED + ATS_NEW;
+
+  t++;
+}
+
+/*
+ * ATS Functions
+ */
+
+
+/**
+ * Initialize ATS
+ * @param cfg configuration handle to retrieve configuration (to be removed)
+ * @return
+ */
+
+struct ATS_Handle *
+ats_init (double D, double U, double R, int v_b_min, int v_n_min,
+          int max_iterations, struct GNUNET_TIME_Relative max_duration,
+          GNUNET_TRANSPORT_ATS_AddressNotification address_not,
+          GNUNET_TRANSPORT_ATS_ResultCallback res_cb)
+{
+  struct ATS_Handle *ats = NULL;
+
+  ats = GNUNET_malloc (sizeof (struct ATS_Handle));
+
+  ats->prob = NULL;
+
+  ats->addr_notification = address_not;
+  ats->result_cb = res_cb;
+
+  ats->max_iterations = max_iterations;
+  ats->max_exec_duration = max_duration;
+
+  ats->D = D;
+  ats->U = U;
+  ats->R = R;
+  ats->v_b_min = v_b_min;
+  ats->v_n_min = v_n_min;
+  ats->dump_min_peers = 0;
+  ats->dump_min_addr = 0;
+  ats->dump_overwrite = GNUNET_NO;
+  ats->mechanisms = NULL;
+  ats->peers = NULL;
+  ats->successful_executions = 0;
+  ats->invalid_executions = 0;
+
+  return ats;
+}
+
+
+/** solve the bandwidth distribution problem
+ * @param max_it maximum iterations
+ * @param max_dur maximum duration in ms
+ * @param D     weight for diversity
+ * @param U weight for utility
+ * @param R weight for relativity
+ * @param v_b_min minimal bandwidth per peer
+ * @param v_n_min minimum number of connections
+ * @param stat result struct
+ * @return GNUNET_SYSERR if glpk is not available, number of mechanisms used
+ */
+int
+ats_create_problem (struct ATS_Handle *ats, struct ATS_internals *stat,
+                    struct ATS_peer *peers, int c_p,
+                    struct ATS_mechanism *mechanisms, int c_m)
+{
+  if ((c_p == 0) || (c_m == 0))
+    return GNUNET_SYSERR;
+
+  ats->prob = _lp_create_prob ();
+
+  int c;
+  int c_c_ressources = available_ressources;
+  int c_q_metrics = available_quality_metrics;
+
+  double M = VERY_BIG_DOUBLE_VALUE;
+  double Q[c_q_metrics + 1];
+
+  for (c = 1; c <= c_q_metrics; c++)
+  {
+    Q[c] = 1;
+  }
+
+  if (ats->v_n_min > c_p)
+    ats->v_n_min = c_p;
+#if VERBOSE_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Creating problem with: %i peers, %i mechanisms, %i resource 
entries, %i quality metrics \n",
+              c_p, c_m, c_c_ressources, c_q_metrics);
+#endif
+
+  int size =
+      1 + 3 + 10 * c_m + c_p + (c_q_metrics * c_m) + c_q_metrics +
+      c_c_ressources * c_m;
+  int row_index;
+  int array_index = 1;
+  int *ia = GNUNET_malloc (size * sizeof (int));
+  int *ja = GNUNET_malloc (size * sizeof (int));
+  double *ar = GNUNET_malloc (size * sizeof (double));
+
+  _lp_set_prob_name (ats->prob, "gnunet ats bandwidth distribution");
+  _lp_set_obj_dir (ats->prob, GLP_MAX);
+
+  /* adding columns */
+  char *name;
+
+  _lp_add_cols (ats->prob, 2 * c_m);
+  /* adding b_t cols */
+  for (c = 1; c <= c_m; c++)
+  {
+    GNUNET_asprintf (&name, "p_%s_b%i",
+                     GNUNET_i2s (&(mechanisms[c].peer->peer)), c);
+    _lp_set_col_name (ats->prob, c, name);
+    GNUNET_free (name);
+    _lp_set_col_bnds (ats->prob, c, GLP_LO, 0.0, 0.0);
+    _lp_set_col_kind (ats->prob, c, GLP_CV);
+    _lp_set_obj_coef (ats->prob, c, 0);
+  }
+
+  /* adding n_t cols */
+  for (c = c_m + 1; c <= 2 * c_m; c++)
+  {
+    GNUNET_asprintf (&name, "p_%s_n%i",
+                     GNUNET_i2s (&(mechanisms[c - c_m].peer->peer)), (c - 
c_m));
+    _lp_set_col_name (ats->prob, c, name);
+    GNUNET_free (name);
+    _lp_set_col_bnds (ats->prob, c, GLP_DB, 0.0, 1.0);
+    _lp_set_col_kind (ats->prob, c, GLP_IV);
+    _lp_set_obj_coef (ats->prob, c, 0);
+  }
+
+  /* feasibility constraints */
+  /* Constraint 1: one address per peer */
+  row_index = 1;
+
+  _lp_add_rows (ats->prob, c_p);
+
+  for (c = 1; c <= c_p; c++)
+  {
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+
+    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 1.0, 1.0);
+    struct ATS_mechanism *m = peers[c].m_head;
+
+    while (m != NULL)
+    {
+      ia[array_index] = row_index;
+      ja[array_index] = (c_m + m->col_index);
+      ar[array_index] = 1;
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                  array_index, ia[array_index], ja[array_index],
+                  ar[array_index]);
+#endif
+      array_index++;
+      m = m->next;
+    }
+    row_index++;
+  }
+
+  /* Constraint 2: only active mechanism gets bandwidth assigned */
+  _lp_add_rows (ats->prob, c_m);
+  for (c = 1; c <= c_m; c++)
+  {
+    /* b_t - n_t * M <= 0 */
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+    _lp_set_row_bnds (ats->prob, row_index, GLP_UP, 0.0, 0.0);
+    ia[array_index] = row_index;
+    ja[array_index] = mechanisms[c].col_index;
+    ar[array_index] = 1;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+    ia[array_index] = row_index;
+    ja[array_index] = c_m + mechanisms[c].col_index;
+    ar[array_index] = -M;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+    row_index++;
+  }
+
+  /* Constraint 3: minimum bandwidth */
+  _lp_add_rows (ats->prob, c_m);
+
+  for (c = 1; c <= c_m; c++)
+  {
+    /* b_t - n_t * b_min <= 0 */
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+#if HAVE_LIBGLPK
+    _lp_set_row_bnds (ats->prob, row_index, GLP_LO, 0.0, 0.0);
+#endif
+    ia[array_index] = row_index;
+    ja[array_index] = mechanisms[c].col_index;
+    ar[array_index] = 1;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+    ia[array_index] = row_index;
+    ja[array_index] = c_m + mechanisms[c].col_index;
+    ar[array_index] = -ats->v_b_min;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+    row_index++;
+  }
+  int c2;
+
+  /* Constraint 4: max ressource capacity */
+  /* V cr: bt * ct_r <= cr_max
+   * */
+
+  _lp_add_rows (ats->prob, available_ressources);
+
+  double ct_max = VERY_BIG_DOUBLE_VALUE;
+  double ct_min = 0.0;
+
+  stat->begin_cr = array_index;
+
+  for (c = 0; c < available_ressources; c++)
+  {
+    ct_max = ressources[c].c_max;
+    ct_min = ressources[c].c_min;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] %f..%f\n",
+                row_index, ct_min, ct_max);
+#endif
+#if HAVE_LIBGLPK
+    _lp_set_row_bnds (ats->prob, row_index, GLP_DB, ct_min, ct_max);
+#endif
+    for (c2 = 1; c2 <= c_m; c2++)
+    {
+      double value = 0;
+
+      ia[array_index] = row_index;
+      ja[array_index] = c2;
+      value = mechanisms[c2].ressources[c].c;
+      ar[array_index] = value;
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                  array_index, ia[array_index], ja[array_index],
+                  ar[array_index]);
+#endif
+      array_index++;
+    }
+    row_index++;
+  }
+  stat->end_cr = array_index--;
+
+  /* Constraint 5: min number of connections */
+  _lp_add_rows (ats->prob, 1);
+
+  for (c = 1; c <= c_m; c++)
+  {
+    // b_t - n_t * b_min >= 0
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+    _lp_set_row_bnds (ats->prob, row_index, GLP_LO, ats->v_n_min, 0.0);
+    ia[array_index] = row_index;
+    ja[array_index] = c_m + mechanisms[c].col_index;
+    ar[array_index] = 1;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+  }
+  row_index++;
+
+  // optimisation constraints
+
+  // adding columns
+
+  // Constraint 6: optimize for diversity
+  int col_d;
+
+  col_d = _lp_add_cols (ats->prob, 1);
+
+  _lp_set_col_name (ats->prob, col_d, "d");
+  _lp_set_obj_coef (ats->prob, col_d, ats->D);
+  _lp_set_col_bnds (ats->prob, col_d, GLP_LO, 0.0, 0.0);
+  _lp_add_rows (ats->prob, 1);
+  _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
+
+  stat->col_d = col_d;
+#if VERBOSE_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+  for (c = 1; c <= c_m; c++)
+  {
+    ia[array_index] = row_index;
+    ja[array_index] = c_m + mechanisms[c].col_index;
+    ar[array_index] = 1;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+  }
+  ia[array_index] = row_index;
+  ja[array_index] = col_d;
+  ar[array_index] = -1;
+#if VERBOSE_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+              array_index, ia[array_index], ja[array_index], ar[array_index]);
+#endif
+  array_index++;
+  row_index++;
+
+  // Constraint 7: optimize for quality
+  int col_qm;
+
+  col_qm = _lp_add_cols (ats->prob, c_q_metrics);
+
+  stat->col_qm = col_qm;
+  //GNUNET_assert (col_qm == (2*c_mechs) + 3 + 1);
+  for (c = 0; c < c_q_metrics; c++)
+  {
+    GNUNET_asprintf (&name, "Q_%s", qm[c].name);
+    _lp_set_col_name (ats->prob, col_qm + c, name);
+    _lp_set_col_bnds (ats->prob, col_qm + c, GLP_LO, 0.0, 0.0);
+    GNUNET_free (name);
+    _lp_set_obj_coef (ats->prob, col_qm + c, Q[c]);
+  }
+
+  _lp_add_rows (ats->prob, available_quality_metrics);
+
+  stat->begin_qm = row_index;
+  for (c = 1; c <= c_q_metrics; c++)
+  {
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+    double value = 1;
+
+    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
+    for (c2 = 1; c2 <= c_m; c2++)
+    {
+      ia[array_index] = row_index;
+      ja[array_index] = c2;
+      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY)
+      {
+        double v0 = 0, v1 = 0, v2 = 0;
+
+        v0 = mechanisms[c2].quality[c - 1].values[0];
+        if (v1 < 1)
+          v0 = 0.1;
+        v1 = mechanisms[c2].quality[c - 1].values[1];
+        if (v1 < 1)
+          v0 = 0.1;
+        v2 = mechanisms[c2].quality[c - 1].values[2];
+        if (v1 < 1)
+          v0 = 0.1;
+        value = 100.0 / ((v0 + 2 * v1 + 3 * v2) / 6.0);
+        value = 1;
+      }
+      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
+      {
+        double v0 = 0, v1 = 0, v2 = 0;
+
+        v0 = mechanisms[c2].quality[c - 1].values[0];
+        if (v0 < 1)
+          v0 = 1;
+        v1 = mechanisms[c2].quality[c - 1].values[1];
+        if (v1 < 1)
+          v1 = 1;
+        v2 = mechanisms[c2].quality[c - 1].values[2];
+        if (v2 < 1)
+          v2 = 1;
+        value = (v0 + 2 * v1 + 3 * v2) / 6.0;
+        if (value >= 1)
+          value = (double) 10 / value;
+        else
+          value = 10;
+      }
+      ar[array_index] = (mechanisms[c2].peer->f) * value;
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: %s [%i,%i]=%f \n",
+                  array_index, qm[c - 1].name, ia[array_index], 
ja[array_index],
+                  ar[array_index]);
+#endif
+      array_index++;
+    }
+    ia[array_index] = row_index;
+    ja[array_index] = col_qm + c - 1;
+    ar[array_index] = -1;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+    row_index++;
+  }
+  stat->end_qm = row_index - 1;
+
+  // Constraint 8: optimize bandwidth utility
+  int col_u;
+
+  col_u = _lp_add_cols (ats->prob, 1);
+
+  _lp_set_col_name (ats->prob, col_u, "u");
+  _lp_set_obj_coef (ats->prob, col_u, ats->U);
+  _lp_set_col_bnds (ats->prob, col_u, GLP_LO, 0.0, 0.0);
+  _lp_add_rows (ats->prob, 1);
+  stat->col_u = col_u;
+#if VERBOSE_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+  _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
+  for (c = 1; c <= c_m; c++)
+  {
+    ia[array_index] = row_index;
+    ja[array_index] = c;
+    ar[array_index] = mechanisms[c].peer->f;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+  }
+  ia[array_index] = row_index;
+  ja[array_index] = col_u;
+  ar[array_index] = -1;
+#if VERBOSE_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+              array_index, ia[array_index], ja[array_index], ar[array_index]);
+#endif
+
+  array_index++;
+  row_index++;
+
+  // Constraint 9: optimize relativity
+  int col_r;
+
+  col_r = _lp_add_cols (ats->prob, 1);
+
+  _lp_set_col_name (ats->prob, col_r, "r");
+  _lp_set_obj_coef (ats->prob, col_r, ats->R);
+  _lp_set_col_bnds (ats->prob, col_r, GLP_LO, 0.0, 0.0);
+  _lp_add_rows (ats->prob, c_p);
+
+  stat->col_r = col_r;
+  for (c = 1; c <= c_p; c++)
+  {
+    _lp_set_row_bnds (ats->prob, row_index, GLP_LO, 0.0, 0.0);
+    struct ATS_mechanism *m = peers[c].m_head;
+
+    while (m != NULL)
+    {
+      ia[array_index] = row_index;
+      ja[array_index] = m->col_index;
+      ar[array_index] = 1 / mechanisms[c].peer->f;
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                  array_index, ia[array_index], ja[array_index],
+                  ar[array_index]);
+#endif
+      array_index++;
+      m = m->next;
+    }
+    ia[array_index] = row_index;
+    ja[array_index] = col_r;
+    ar[array_index] = -1;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
+#endif
+    array_index++;
+    row_index++;
+  }
+
+  /* Loading the matrix */
+  _lp_load_matrix (ats->prob, array_index - 1, ia, ja, ar);
+
+  stat->c_mechs = c_m;
+  stat->c_peers = c_p;
+  stat->solution = 0;
+  stat->valid = GNUNET_YES;
+
+  /* clean up */
+  GNUNET_free (ja);
+  GNUNET_free (ia);
+  GNUNET_free (ar);
+
+  return GNUNET_OK;
+}
+
+
+void
+ats_delete_problem (struct ATS_Handle *ats)
+{
+#if DEBUG_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting problem\n");
+#endif
+  int c;
+
+  for (c = 0; c < (ats->internal).c_mechs; c++)
+    GNUNET_free_non_null (ats->mechanisms[c].rc);
+  if (ats->mechanisms != NULL)
+  {
+    GNUNET_free (ats->mechanisms);
+    ats->mechanisms = NULL;
+  }
+
+  if (ats->peers != NULL)
+  {
+    GNUNET_free (ats->peers);
+    ats->peers = NULL;
+  }
+
+  if (ats->prob != NULL)
+  {
+    _lp_delete_prob (ats->prob);
+    ats->prob = NULL;
+  }
+
+  ats->internal.begin_cr = GNUNET_SYSERR;
+  ats->internal.begin_qm = GNUNET_SYSERR;
+  ats->internal.c_mechs = 0;
+  ats->internal.c_peers = 0;
+  ats->internal.end_cr = GNUNET_SYSERR;
+  ats->internal.end_qm = GNUNET_SYSERR;
+  ats->internal.solution = GNUNET_SYSERR;
+  ats->internal.valid = GNUNET_SYSERR;
+}
+
+void
+ats_modify_problem_state (struct ATS_Handle *ats, enum ATS_problem_state s)
+{
+  if (ats == NULL)
+    return;
+  switch (s)
+  {
+  case ATS_NEW:
+    ats->internal.recreate_problem = GNUNET_NO;
+    ats->internal.modified_quality = GNUNET_NO;
+    ats->internal.modified_resources = GNUNET_NO;
+    break;
+  case ATS_MODIFIED:
+    ats->internal.recreate_problem = GNUNET_YES;
+    break;
+  case ATS_QUALITY_UPDATED:
+    ats->internal.modified_quality = GNUNET_YES;
+    break;
+  case ATS_COST_UPDATED:
+    ats->internal.modified_resources = GNUNET_YES;
+    break;
+  case ATS_QUALITY_COST_UPDATED:
+    ats->internal.modified_resources = GNUNET_YES;
+    ats->internal.modified_quality = GNUNET_YES;
+    break;
+  default:
+    return;
+  }
+
+
+
+}
+
+void
+ats_solve_problem (struct ATS_Handle *ats, unsigned int max_it,
+                   unsigned int max_dur, unsigned int c_peers,
+                   unsigned int c_mechs, struct ATS_internals *stat)
+{
+  int result = GNUNET_SYSERR;
+  int lp_solution = GNUNET_SYSERR;
+  int mlp_solution = GNUNET_SYSERR;
+
+  // Solving simplex
+
+  glp_smcp opt_lp;
+
+  _lp_init_smcp (&opt_lp);
+#if VERBOSE_ATS
+  opt_lp.msg_lev = GLP_MSG_ALL;
+#else
+  opt_lp.msg_lev = GLP_MSG_OFF;
+#endif
+  // setting iteration limit
+  opt_lp.it_lim = max_it;
+  // maximum duration
+  opt_lp.tm_lim = max_dur;
+
+  if (ats->internal.recreate_problem == GNUNET_YES)
+    opt_lp.presolve = GLP_ON;
+
+  result = _lp_simplex (ats->prob, &opt_lp);
+  lp_solution = _lp_get_status (ats->prob);
+
+  if ((result == GLP_ETMLIM) || (result == GLP_EITLIM))
+  {
+    ats->internal.valid = GNUNET_NO;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "ATS exceeded time or iteration limit!\n");
+    return;
+  }
+
+  if (ats_evaluate_results (result, lp_solution, "LP") == GNUNET_YES)
+  {
+    stat->valid = GNUNET_YES;
+  }
+  else
+  {
+    ats->internal.simplex_rerun_required = GNUNET_YES;
+    opt_lp.presolve = GLP_ON;
+    result = _lp_simplex (ats->prob, &opt_lp);
+    lp_solution = _lp_get_status (ats->prob);
+
+    // TODO: Remove if this does not appear until release
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "" "EXECUTED SIMPLEX WITH PRESOLVER! %i \n", lp_solution);
+
+    if (ats_evaluate_results (result, lp_solution, "LP") != GNUNET_YES)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "After execution simplex with presolver: STILL INVALID!\n");
+      char *filename;
+
+      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i_%llu.mlp",
+                       ats->internal.c_peers, ats->internal.c_mechs,
+                       GNUNET_TIME_absolute_get ().abs_value);
+      _lp_write_lp ((void *) ats->prob, NULL, filename);
+      GNUNET_free (filename);
+      stat->valid = GNUNET_NO;
+      ats->internal.recreate_problem = GNUNET_YES;
+      return;
+    }
+    stat->valid = GNUNET_YES;
+  }
+
+  // Solving mlp
+  glp_iocp opt_mlp;
+
+  _lp_init_iocp (&opt_mlp);
+  // maximum duration
+  opt_mlp.tm_lim = max_dur;
+  // output level
+#if VERBOSE_ATS
+  opt_mlp.msg_lev = GLP_MSG_ALL;
+#else
+  opt_mlp.msg_lev = GLP_MSG_OFF;
+#endif
+
+  result = _lp_intopt (ats->prob, &opt_mlp);
+  mlp_solution = _lp_mip_status (ats->prob);
+  stat->solution = mlp_solution;
+
+  if (ats_evaluate_results (result, mlp_solution, "MLP") == GNUNET_YES)
+  {
+    stat->valid = GNUNET_YES;
+  }
+  else
+  {
+    // TODO: Remove if this does not appear until release
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "MLP solution for %i peers, %i mechs is invalid: %i\n",
+                ats->internal.c_peers, ats->internal.c_mechs, mlp_solution);
+    stat->valid = GNUNET_NO;
+  }
+
+#if VERBOSE_ATS
+  if (_lp_get_col_prim (ats->prob, 2 * c_mechs + 1) != 1)
+  {
+    int c;
+
+    for (c = 1; c <= available_quality_metrics; c++)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
+                  _lp_get_col_name (ats->prob, 2 * c_mechs + 3 + c),
+                  _lp_get_col_prim (ats->prob, 2 * c_mechs + 3 + c));
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
+                _lp_get_col_name (ats->prob, 2 * c_mechs + 1),
+                _lp_get_col_prim (ats->prob, 2 * c_mechs + 1));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
+                _lp_get_col_name (ats->prob, 2 * c_mechs + 2),
+                _lp_get_col_prim (ats->prob, 2 * c_mechs + 2));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
+                _lp_get_col_name (ats->prob, 2 * c_mechs + 3),
+                _lp_get_col_prim (ats->prob, 2 * c_mechs + 3));
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "objective value:  %f\n",
+                _lp_mip_obj_val (ats->prob));
+  }
+#endif
+}
+
+
+void
+ats_shutdown (struct ATS_Handle *ats)
+{
+#if DEBUG_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS shutdown\n");
+#endif
+  ats_delete_problem (ats);
+  _lp_free_env ();
+
+  GNUNET_free (ats);
+}
+
+void
+ats_update_problem_qm (struct ATS_Handle *ats)
+{
+  int array_index;
+  int row_index;
+  int c, c2;
+  int c_q_metrics = available_quality_metrics;
+
+  int *ja =
+      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
+                      available_quality_metrics) * sizeof (int));
+  double *ar =
+      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
+                      available_quality_metrics) * sizeof (double));
+#if DEBUG_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating problem quality metrics\n");
+#endif
+  row_index = ats->internal.begin_qm;
+
+  for (c = 1; c <= c_q_metrics; c++)
+  {
+    array_index = 1;
+    double value = 1;
+
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
+#endif
+    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
+    for (c2 = 1; c2 <= ats->internal.c_mechs; c2++)
+    {
+      ja[array_index] = c2;
+      GNUNET_assert (ats->mechanisms[c2].addr != NULL);
+      GNUNET_assert (ats->mechanisms[c2].peer != NULL);
+
+      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY)
+      {
+        double v0 = 0, v1 = 0, v2 = 0;
+
+        v0 = ats->mechanisms[c2].quality[c - 1].values[0];
+        if (v1 < 1)
+          v0 = 0.1;
+        v1 = ats->mechanisms[c2].quality[c - 1].values[1];
+        if (v1 < 1)
+          v0 = 0.1;
+        v2 = ats->mechanisms[c2].quality[c - 1].values[2];
+        if (v1 < 1)
+          v0 = 0.1;
+        value = 100.0 / ((v0 + 2 * v1 + 3 * v2) / 6.0);
+        //value = 1;
+      }
+      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
+      {
+        double v0 = 0, v1 = 0, v2 = 0;
+
+        v0 = ats->mechanisms[c2].quality[c - 1].values[0];
+        if (v0 < 1)
+          v0 = 1;
+        v1 = ats->mechanisms[c2].quality[c - 1].values[1];
+        if (v1 < 1)
+          v1 = 1;
+        v2 = ats->mechanisms[c2].quality[c - 1].values[2];
+        if (v2 < 1)
+          v2 = 1;
+        value = (v0 + 2 * v1 + 3 * v2) / 6.0;
+        if (value >= 1)
+          value = (double) 10 / value;
+        else
+          value = 10;
+      }
+      ar[array_index] = (ats->mechanisms[c2].peer->f) * value;
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: %s [%i,%i]=%f \n",
+                  array_index, qm[c - 1].name, row_index, ja[array_index],
+                  ar[array_index]);
+#endif
+      array_index++;
+    }
+    ja[array_index] = ats->internal.col_qm + c - 1;
+    ar[array_index] = -1;
+
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                array_index, row_index, ja[array_index], ar[array_index]);
+#endif
+    _lp_set_mat_row (ats->prob, row_index, array_index, ja, ar);
+    array_index = 1;
+    row_index++;
+  }
+  GNUNET_free_non_null (ja);
+  GNUNET_free_non_null (ar);
+
+}
+
+
+void
+ats_calculate_bandwidth_distribution (struct ATS_Handle *ats)
+{
+  struct GNUNET_TIME_Absolute start;
+  struct GNUNET_TIME_Relative creation;
+  struct GNUNET_TIME_Relative solving;
+  int c_m;
+  int c_p;
+  char *text = "unmodified";
+
+#if FIXME_WACHS
+  int dur;
+
+  if (INT_MAX < ats->max_exec_duration.rel_value)
+    dur = INT_MAX;
+  else
+    dur = (int) ats->max_exec_duration.rel_value;
+#endif
+
+  ats->internal.simplex_rerun_required = GNUNET_NO;
+  start = GNUNET_TIME_absolute_get ();
+  if ((ats->internal.recreate_problem == GNUNET_YES) || (ats->prob == NULL) ||
+      (ats->internal.valid == GNUNET_NO))
+  {
+    text = "new";
+    ats->internal.recreate_problem = GNUNET_YES;
+    ats_delete_problem (ats);
+    ats->addr_notification (&ats->peers, &c_p, &ats->mechanisms, &c_m);
+#if DEBUG_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Service returned: %i peer, %i mechs\n", c_p, c_m);
+#endif
+    ats_create_problem (ats, &ats->internal, ats->peers, c_p, ats->mechanisms,
+                        c_m);
+
+
+#if DEBUG_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Peers/Addresses were modified... new problem: %i peer, %i 
mechs\n",
+                ats->internal.c_peers, ats->internal.c_mechs);
+#endif
+  }
+
+  else if ((ats->internal.recreate_problem == GNUNET_NO) &&
+           (ats->internal.modified_resources == GNUNET_YES) &&
+           (ats->internal.valid == GNUNET_YES))
+  {
+    text = "modified resources";
+    ats_update_problem_cr (ats);
+  }
+  else if ((ats->internal.recreate_problem == GNUNET_NO) &&
+           (ats->internal.modified_quality == GNUNET_YES) &&
+           (ats->internal.valid == GNUNET_YES))
+  {
+    text = "modified quality";
+    ats_update_problem_qm (ats);
+    //ats_update_problem_qm_TEST ();
+  }
+#if DEBUG_ATS
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Problem is %s\n", text);
+#endif
+
+  creation =
+      GNUNET_TIME_absolute_get_difference (start, GNUNET_TIME_absolute_get ());
+  start = GNUNET_TIME_absolute_get ();
+
+  ats->internal.solution = GLP_UNDEF;
+  if (ats->internal.valid == GNUNET_YES)
+  {
+    ats_solve_problem (ats, ats->max_iterations,
+                       ats->max_exec_duration.rel_value, ats->internal.c_peers,
+                       ats->internal.c_mechs, &ats->internal);
+  }
+  solving =
+      GNUNET_TIME_absolute_get_difference (start, GNUNET_TIME_absolute_get ());
+
+  if (ats->internal.valid == GNUNET_YES)
+  {
+    /* Telling about new distribution */
+    ats->result_cb ();
+
+    int msg_type = GNUNET_ERROR_TYPE_DEBUG;
+
+#if DEBUG_ATS
+    msg_type = GNUNET_ERROR_TYPE_ERROR;
+#endif
+    GNUNET_log (msg_type,
+                "MLP %s: creation time: %llu, execution time: %llu, %i peers, 
%i mechanisms, simplex rerun: %s, solution %s\n",
+                text, creation.rel_value, solving.rel_value,
+                ats->internal.c_peers, ats->internal.c_mechs,
+                (ats->internal.simplex_rerun_required ==
+                 GNUNET_NO) ? "NO" : "YES",
+                (ats->internal.solution == 5) ? "OPTIMAL" : "INVALID");
+    ats->successful_executions++;
+    GNUNET_STATISTICS_set (ats->stats, "# ATS successful executions",
+                           ats->successful_executions, GNUNET_NO);
+
+    if ((ats->internal.recreate_problem == GNUNET_YES) || (ats->prob == NULL))
+      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_NEW, GNUNET_NO);
+    else if ((ats->internal.modified_resources == GNUNET_YES) &&
+             (ats->internal.modified_quality == GNUNET_NO))
+      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_COST_UPDATED,
+                             GNUNET_NO);
+    else if ((ats->internal.modified_resources == GNUNET_NO) &&
+             (ats->internal.modified_quality == GNUNET_YES) &&
+             (ats->internal.simplex_rerun_required == GNUNET_NO))
+      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_QUALITY_UPDATED,
+                             GNUNET_NO);
+    else if ((ats->internal.modified_resources == GNUNET_YES) &&
+             (ats->internal.modified_quality == GNUNET_YES) &&
+             (ats->internal.simplex_rerun_required == GNUNET_NO))
+      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_QUALITY_COST_UPDATED,
+                             GNUNET_NO);
+    else if (ats->internal.simplex_rerun_required == GNUNET_NO)
+      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_UNMODIFIED,
+                             GNUNET_NO);
+  }
+  else
+  {
+    if (ats->internal.c_peers != 0)
+    {
+      ats->invalid_executions++;
+      GNUNET_STATISTICS_set (ats->stats, "# ATS invalid executions",
+                             ats->invalid_executions, GNUNET_NO);
+    }
+    else
+    {
+      GNUNET_STATISTICS_set (ats->stats, "# ATS successful executions",
+                             ats->successful_executions, GNUNET_NO);
+    }
+  }
+
+  GNUNET_STATISTICS_set (ats->stats, "ATS duration",
+                         solving.rel_value + creation.rel_value, GNUNET_NO);
+  GNUNET_STATISTICS_set (ats->stats, "ATS mechanisms", ats->internal.c_mechs,
+                         GNUNET_NO);
+  GNUNET_STATISTICS_set (ats->stats, "ATS peers", ats->internal.c_peers,
+                         GNUNET_NO);
+  GNUNET_STATISTICS_set (ats->stats, "ATS solution", ats->internal.solution,
+                         GNUNET_NO);
+  GNUNET_STATISTICS_set (ats->stats, "ATS timestamp", start.abs_value,
+                         GNUNET_NO);
+
+  if ((ats->save_mlp == GNUNET_YES) &&
+      (ats->internal.c_mechs >= ats->dump_min_peers) &&
+      (ats->internal.c_mechs >= ats->dump_min_addr))
+  {
+    char *filename;
+
+    if (ats->dump_overwrite == GNUNET_NO)
+    {
+      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i_%s_%llu.mlp",
+                       ats->internal.c_peers, ats->internal.c_mechs, text,
+                       GNUNET_TIME_absolute_get ().abs_value);
+      _lp_write_lp ((void *) ats->prob, NULL, filename);
+    }
+    else
+    {
+      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i.mlp", ats->internal.c_peers,
+                       ats->internal.c_mechs);
+      _lp_write_lp ((void *) ats->prob, NULL, filename);
+    }
+    GNUNET_free (filename);
+  }
+  if ((ats->save_solution == GNUNET_YES) &&
+      (ats->internal.c_mechs >= ats->dump_min_peers) &&
+      (ats->internal.c_mechs >= ats->dump_min_addr))
+  {
+    char *filename;
+
+    if (ats->dump_overwrite == GNUNET_NO)
+    {
+      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i_%s_%llu.sol",
+                       ats->internal.c_peers, ats->internal.c_mechs, text,
+                       GNUNET_TIME_absolute_get ().abs_value);
+      _lp_print_sol (ats->prob, filename);
+    }
+    else
+    {
+      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i.sol", ats->internal.c_peers,
+                       ats->internal.c_mechs);
+      _lp_print_sol (ats->prob, filename);
+    }
+    GNUNET_free (filename);
+  }
+
+  ats->internal.recreate_problem = GNUNET_NO;
+  ats->internal.modified_resources = GNUNET_NO;
+  ats->internal.modified_quality = GNUNET_NO;
+}
+
+/**
+ * Evaluate the result of the last simplex or mlp solving
+ * @param result return value returned by the solver
+ * @param solution solution state
+ * @param problem mlp or lp
+ * @return GNUNET_NO if solution is invalid, GNUNET_YES if solution is
+ *      valid
+ */
+
+int
+ats_evaluate_results (int result, int solution, char *problem)
+{
+  int cont = GNUNET_NO;
+
+#if DEBUG_ATS || VERBOSE_ATS
+  int error_kind = GNUNET_ERROR_TYPE_DEBUG;
+#endif
+#if VERBOSE_ATS
+  error_kind = GNUNET_ERROR_TYPE_ERROR;
+#endif
+  switch (result)
+  {
+  case GNUNET_SYSERR:          /* GNUNET problem, not GLPK related */
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s, GLPK solving not executed\n", problem);
+#endif
+    break;
+  case GLP_ESTOP:              /* search terminated by application */
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s , Search terminated by application\n", 
problem);
+#endif
+    break;
+  case GLP_EITLIM:             /* iteration limit exceeded */
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s Iteration limit exceeded\n",
+                problem);
+#endif
+    break;
+  case GLP_ETMLIM:             /* time limit exceeded */
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s Time limit exceeded\n", 
problem);
+#endif
+    break;
+  case GLP_ENOPFS:             /* no primal feasible solution */
+  case GLP_ENODFS:             /* no dual feasible solution */
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s No feasible solution\n", problem);
+#endif
+    break;
+  case GLP_EBADB:              /* invalid basis */
+  case GLP_ESING:              /* singular matrix */
+  case GLP_ECOND:              /* ill-conditioned matrix */
+  case GLP_EBOUND:             /* invalid bounds */
+  case GLP_EFAIL:              /* solver failed */
+  case GLP_EOBJLL:             /* objective lower limit reached */
+  case GLP_EOBJUL:             /* objective upper limit reached */
+  case GLP_EROOT:              /* root LP optimum not provided */
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s Invalid Input data: %i\n", problem, result);
+#endif
+    break;
+  case 0:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s Problem has been solved\n", problem);
+#endif
+    break;
+  }
+
+  switch (solution)
+  {
+  case GLP_UNDEF:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s solution is undefined\n", problem);
+#endif
+    break;
+  case GLP_OPT:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s solution is optimal\n", problem);
+#endif
+    cont = GNUNET_YES;
+    break;
+  case GLP_FEAS:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind,
+                "%s solution is %s feasible, however, its optimality (or 
non-optimality) has not been proven\n",
+                problem, (0 == strcmp (problem, "LP") ? "" : "integer"));
+#endif
+    cont = GNUNET_YES;
+    break;
+  case GLP_NOFEAS:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s problem has no %sfeasible solution\n", problem,
+                (0 == strcmp (problem, "LP") ? "" : "integer "));
+#endif
+    break;
+  case GLP_INFEAS:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s problem is infeasible \n", problem);
+#endif
+    break;
+  case GLP_UNBND:
+#if DEBUG_ATS || VERBOSE_ATS
+    GNUNET_log (error_kind, "%s problem is unbounded \n", problem);
+#endif
+  default:
+    break;
+  }
+  return cont;
+}
+
+void
+ats_update_problem_cr (struct ATS_Handle *ats)
+{
+  int array_index;
+  int row_index;
+  int c, c2;
+  double ct_max, ct_min;
+
+  int *ja =
+      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
+                      available_quality_metrics) * sizeof (int));
+  double *ar =
+      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
+                      available_quality_metrics) * sizeof (double));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating problem quality metrics\n");
+  row_index = ats->internal.begin_cr;
+  array_index = 1;
+
+  for (c = 0; c < available_ressources; c++)
+  {
+    ct_max = ressources[c].c_max;
+    ct_min = ressources[c].c_min;
+#if VERBOSE_ATS
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] %f..%f\n",
+                row_index, ct_min, ct_max);
+#endif
+    _lp_set_row_bnds (ats->prob, row_index, GLP_DB, ct_min, ct_max);
+    for (c2 = 1; c2 <= ats->internal.c_mechs; c2++)
+    {
+      double value = 0;
+
+      GNUNET_assert (ats->mechanisms[c2].addr != NULL);
+      GNUNET_assert (ats->mechanisms[c2].peer != NULL);
+
+      ja[array_index] = c2;
+      value = ats->mechanisms[c2].ressources[c].c;
+      ar[array_index] = value;
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
+                  array_index, row_index, ja[array_index], ar[array_index]);
+#endif
+      array_index++;
+    }
+    _lp_set_mat_row (ats->prob, row_index, array_index, ja, ar);
+    row_index++;
+  }
+  GNUNET_free_non_null (ja);
+  GNUNET_free_non_null (ar);
+
+}
+
+void
+ats_set_logging_options (struct ATS_Handle *ats,
+                         struct GNUNET_STATISTICS_Handle *stats,
+                         const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  int minimum_addresses;
+  int minimum_peers;
+  int overwrite_dump;
+  int log_solution;
+  int log_problem;
+  unsigned long long value;
+
+  if (ats == NULL)
+    return;
+  log_problem =
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, "transport", "DUMP_MLP");
+  log_solution =
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, "transport", "DUMP_SOLUTION");
+  overwrite_dump =
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, "transport", 
"DUMP_OVERWRITE");
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "transport", 
"DUMP_MIN_PEERS",
+                                             &value))
+    minimum_peers = (int) value;
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "transport", 
"DUMP_MIN_ADDRS",
+                                             &value))
+    minimum_addresses = (int) value;
+
+
+  ats->stats = stats;
+  ats->dump_min_addr = minimum_addresses;
+  ats->dump_min_peers = minimum_peers;
+  ats->dump_overwrite = overwrite_dump;
+  ats->save_mlp = log_problem;
+  ats->save_solution = log_solution;
+}
+
+#if 0
+static void
+ats_update_problem_qm_TEST ()
+{
+  int row_index;
+  int c int c2;
+  int c_old;
+  int changed = 0;
+
+  int old_ja[ats->internal.c_mechs + 2];
+  double old_ar[ats->internal.c_mechs + 2];
+
+  int *ja =
+      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
+                      available_quality_metrics) * sizeof (int));
+  double *ar =
+      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
+                      available_quality_metrics) * sizeof (double));
+#if DEBUG_ATS
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Updating problem quality metrics TEST\n");
+#endif
+  if (ats->internal.begin_qm > 0)
+    row_index = ats->internal.begin_qm;
+  else
+    return;
+  for (c = 0; c < available_quality_metrics; c++)
+  {
+    c_old = _lp_get_mat_row (ats->prob, row_index, old_ja, old_ar);
+    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
+    for (c2 = 1; c2 <= c_old; c2++)
+    {
+      ja[c2] = old_ja[c2];
+      if ((changed < 3) && (c2 > 2) && (old_ar[c2] != -1))
+      {
+        ar[c2] = old_ar[c2] + 5 - changed;
+        changed++;
+      }
+      else
+        ar[c2] = old_ar[c2];
+#if VERBOSE_ATS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "[index]=[%i]: old [%i,%i]=%f  new [%i,%i]=%f\n", c2,
+                  row_index, old_ja[c2], old_ar[c2], row_index, ja[c2], 
ar[c2]);
+#endif
+    }
+    _lp_set_mat_row (ats->prob, row_index, c_old, ja, ar);
+    row_index++;
+  }
+  GNUNET_free_non_null (ja);
+  GNUNET_free_non_null (ar);
+}
+#endif
+
+
+
+/* end of transport_ats.c */

Copied: gnunet/src/ats/gnunet-service-transport_ats.h (from rev 16807, 
gnunet/src/transport/gnunet-service-transport_ats.h)
===================================================================
--- gnunet/src/ats/gnunet-service-transport_ats.h                               
(rev 0)
+++ gnunet/src/ats/gnunet-service-transport_ats.h       2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -0,0 +1,496 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010,2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file transport/gnunet-service-transport_ats.h
+ * @brief common internal definitions for transport service's ats code
+ * @author Matthias Wachs
+ */
+#ifndef GNUNET_SERVICE_TRANSPORT_ATS_H
+#define GNUNET_SERVICE_TRANSPORT_ATS_H
+
+#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_time_lib.h"
+
+
+#if HAVE_LIBGLPK
+#include <glpk.h>
+#endif
+
+/*
+ *  ATS defines
+ */
+
+#define DEBUG_ATS GNUNET_NO
+#define VERBOSE_ATS GNUNET_NO
+
+
+/* Minimum time between to calculations*/
+#define ATS_MIN_INTERVAL  
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15)
+#define ATS_EXEC_INTERVAL 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
+#define ATS_MAX_EXEC_DURATION 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
+#define ATS_MAX_ITERATIONS INT_MAX
+
+#define ATS_DEFAULT_D 1.0
+#define ATS_DEFAULT_U 1.0
+#define ATS_DEFAULT_R 1.0
+#define ATS_DEFAULT_B_MIN 64000
+#define ATS_DEFAULT_N_MIN 10
+
+#define VERY_BIG_DOUBLE_VALUE 100000000000LL
+
+
+/*
+ * Callback Functions
+ */
+
+struct ATS_mechanism;
+struct ATS_peer;
+
+typedef void (*GNUNET_TRANSPORT_ATS_AddressNotification) (struct ATS_peer **
+                                                          peers, int *c_p,
+                                                          struct ATS_mechanism
+                                                          ** mechanisms,
+                                                          int *c_m);
+
+typedef void (*GNUNET_TRANSPORT_ATS_ResultCallback) (void);
+
+enum ATS_problem_state
+{
+  /**
+   * Problem is new
+   */
+  ATS_NEW = 0,
+
+  /**
+   * Problem quality properties were modified
+   */
+  ATS_QUALITY_UPDATED = 1,
+
+  /**
+   * Problem ressource properties were modified
+   */
+  ATS_COST_UPDATED = 2,
+
+  /**
+   * Problem quality and ressource properties were modified
+   */
+  ATS_QUALITY_COST_UPDATED = 3,
+
+  /**
+   * Problem is modified and needs to be completely recalculated
+   * due to e.g. connecting or disconnecting peers
+   */
+  ATS_MODIFIED = 4,
+
+  /**
+   * Problem is unmodified
+   */
+  ATS_UNMODIFIED = 8
+};
+
+/*
+*  ATS data structures
+*/
+
+struct ATS_internals
+{
+    /**
+     * result of last GLPK run
+     * 5 == OPTIMAL
+     */
+  int solution;
+
+    /**
+     * Ressource costs or quality metrics changed
+     * update problem before solving
+     */
+  int modified_resources;
+
+    /**
+     * Ressource costs or quality metrics changed, update matrix
+     * update problem before solving
+     */
+  int modified_quality;
+
+    /**
+     * Peers have connected or disconnected
+     * problem has to be recreated
+     */
+  int recreate_problem;
+
+    /**
+     * Was the available basis invalid and we needed to rerun simplex?
+     */
+  int simplex_rerun_required;
+
+    /**
+     * is problem currently valid and can it be solved
+     */
+  int valid;
+
+    /**
+     * Number of transport mechanisms in the problem
+     */
+  int c_mechs;
+
+    /**
+     * Number of transport mechanisms in the problem
+     */
+  int c_peers;
+
+    /**
+     * row index where quality related rows start
+     */
+  int begin_qm;
+
+    /**
+     * row index where quality related rows end
+     */
+  int end_qm;
+
+    /**
+     * row index where ressource cost related rows start
+     */
+  int begin_cr;
+
+    /**
+     * row index where ressource cost related rows end
+     */
+  int end_cr;
+
+    /**
+     * column index for objective function value d
+     */
+  int col_d;
+
+    /**
+     * column index for objective function value u
+     */
+  int col_u;
+
+    /**
+     * column index for objective function value r
+     */
+  int col_r;
+
+    /**
+     * column index for objective function value quality metrics
+     */
+  int col_qm;
+
+    /**
+     * column index for objective function value cost ressources
+     */
+  int col_cr;
+};
+
+struct ATS_Handle
+{
+  /*
+   *  Callback functions
+   */
+
+  GNUNET_TRANSPORT_ATS_AddressNotification addr_notification;
+
+  GNUNET_TRANSPORT_ATS_ResultCallback result_cb;
+
+
+    /**
+     * Statistics handle
+     */
+  struct GNUNET_STATISTICS_Handle *stats;
+
+    /**
+     * Maximum execution time per calculation
+     */
+  struct GNUNET_TIME_Relative max_exec_duration;
+
+    /**
+     * GLPK (MLP) problem object
+     */
+#if HAVE_LIBGLPK
+
+  glp_prob *prob;
+#else
+  void *prob;
+#endif
+
+    /**
+     * Internal information state of the GLPK problem
+     */
+  struct ATS_internals internal;
+
+    /**
+     * mechanisms used in current problem
+     * needed for problem modification
+     */
+  struct ATS_mechanism *mechanisms;
+
+    /**
+     * peers used in current problem
+     * needed for problem modification
+     */
+  struct ATS_peer *peers;
+
+    /**
+     * State of the MLP problem
+     * value of ATS_problem_state
+     *
+     */
+  int state;
+
+    /**
+     * number of successful executions
+     */
+  int successful_executions;
+
+    /**
+     * number with an invalid result
+     */
+  int invalid_executions;
+
+    /**
+     * Maximum number of LP iterations per calculation
+     */
+  int max_iterations;
+
+
+  /*
+   * ATS configuration
+   */
+
+
+    /**
+     * Diversity weight
+     */
+  double D;
+
+    /**
+     * Utility weight
+     */
+  double U;
+
+    /**
+     * Relativity weight
+     */
+  double R;
+
+    /**
+     * Minimum bandwidth per peer
+     */
+  int v_b_min;
+
+    /**
+     * Minimum number of connections per peer
+     */
+  int v_n_min;
+
+
+    /**
+     * Logging related variables
+     */
+
+
+    /**
+     * Dump problem to a file?
+     */
+  int save_mlp;
+
+    /**
+     * Dump solution to a file
+     */
+  int save_solution;
+
+    /**
+     * Dump solution when minimum peers:
+     */
+  int dump_min_peers;
+
+    /**
+     * Dump solution when minimum addresses:
+     */
+  int dump_min_addr;
+
+    /**
+     * Dump solution overwrite file:
+     */
+  int dump_overwrite;
+};
+
+struct ATS_mechanism
+{
+  struct ATS_mechanism *prev;
+  struct ATS_mechanism *next;
+  struct ForeignAddressList *addr;
+  struct ATS_quality_entry *quality;
+  struct ATS_ressource_entry *ressources;
+  struct TransportPlugin *plugin;
+  struct ATS_peer *peer;
+  int col_index;
+  int id;
+  struct ATS_ressource_cost *rc;
+};
+
+struct ATS_peer
+{
+  struct GNUNET_PeerIdentity peer;
+
+  struct ATS_mechanism *m_head;
+  struct ATS_mechanism *m_tail;
+
+  /* preference value f */
+  double f;
+
+  //struct NeighbourList * n;
+};
+
+struct ATS_ressource
+{
+  /* index in ressources array */
+  int index;
+  /* depending ATSi parameter to calculcate limits */
+  int atis_index;
+  /* cfg option to load limits */
+  char *cfg_param;
+  /* lower bound */
+  double c_min;
+  /* upper bound */
+  double c_max;
+
+  /* cofficients for the specific plugins */
+  double c_unix;
+  double c_tcp;
+  double c_udp;
+  double c_http;
+  double c_https;
+  double c_wlan;
+  double c_default;
+};
+
+
+struct ATS_ressource_entry
+{
+  /* index in ressources array */
+  int index;
+  /* depending ATSi parameter to calculcate limits */
+  int atis_index;
+  /* lower bound */
+  double c;
+};
+
+
+struct ATS_quality_metric
+{
+  int index;
+  int atis_index;
+  char *name;
+};
+
+struct ATS_quality_entry
+{
+  int index;
+  int atsi_index;
+  uint32_t values[3];
+  int current;
+};
+
+/*
+ * ATS ressources
+ */
+
+
+static struct ATS_ressource ressources[] = {
+  /* FIXME: the coefficients for the specific plugins */
+  {1, 7, "LAN_BW_LIMIT", 0, VERY_BIG_DOUBLE_VALUE, 0, 1, 1, 2, 2, 1, 3},
+  {2, 7, "WAN_BW_LIMIT", 0, VERY_BIG_DOUBLE_VALUE, 0, 1, 1, 2, 2, 2, 3},
+  {3, 4, "WLAN_ENERGY_LIMIT", 0, VERY_BIG_DOUBLE_VALUE, 0, 0, 0, 0, 0, 2, 1}
+/*
+    {4, 4, "COST_ENERGY_CONSUMPTION", VERY_BIG_DOUBLE_VALUE},
+    {5, 5, "COST_CONNECT", VERY_BIG_DOUBLE_VALUE},
+    {6, 6, "COST_BANDWITH_AVAILABLE", VERY_BIG_DOUBLE_VALUE},
+    {7, 7, "COST_NETWORK_OVERHEAD", VERY_BIG_DOUBLE_VALUE},*/
+};
+
+#define available_ressources (sizeof(ressources)/sizeof(*ressources))
+
+/*
+ * ATS quality metrics
+ */
+
+static struct ATS_quality_metric qm[] = {
+  {1, 1028, "QUALITY_NET_DISTANCE"},
+  {2, 1034, "QUALITY_NET_DELAY"},
+};
+
+#define available_quality_metrics (sizeof(qm)/sizeof(*qm))
+
+
+/*
+ * ATS functions
+ */
+struct ATS_Handle *
+ats_init (double D, double U, double R, int v_b_min, int v_n_min,
+          int max_iterations, struct GNUNET_TIME_Relative max_duration,
+          GNUNET_TRANSPORT_ATS_AddressNotification address_not,
+          GNUNET_TRANSPORT_ATS_ResultCallback res_cb);
+
+void
+ats_shutdown (struct ATS_Handle *ats);
+
+void
+ats_delete_problem (struct ATS_Handle *ats);
+
+int
+ats_create_problem (struct ATS_Handle *ats, struct ATS_internals *stat,
+                    struct ATS_peer *peers, int c_p,
+                    struct ATS_mechanism *mechanisms, int c_m);
+
+void
+ats_modify_problem_state (struct ATS_Handle *ats, enum ATS_problem_state s);
+
+void
+ats_calculate_bandwidth_distribution (struct ATS_Handle *ats);
+
+void
+ats_solve_problem (struct ATS_Handle *ats, unsigned int max_it,
+                   unsigned int max_dur, unsigned int c_peers,
+                   unsigned int c_mechs, struct ATS_internals *stat);
+
+int
+ats_evaluate_results (int result, int solution, char *problem);
+
+void
+ats_update_problem_qm (struct ATS_Handle *ats);
+
+void
+ats_update_problem_cr (struct ATS_Handle *ats);
+
+
+void
+ats_set_logging_options (struct ATS_Handle *ats,
+                         struct GNUNET_STATISTICS_Handle *stats,
+                         const struct GNUNET_CONFIGURATION_Handle *cfg);
+
+#endif
+/* end of file gnunet-service-transport_ats.h */

Modified: gnunet/src/transport/Makefile.am
===================================================================
--- gnunet/src/transport/Makefile.am    2011-09-13 12:25:52 UTC (rev 16807)
+++ gnunet/src/transport/Makefile.am    2011-09-13 12:40:14 UTC (rev 16808)
@@ -87,7 +87,6 @@
  gnunet-transport \
  $(WLAN_BIN) \
  gnunet-service-transport \
- gnunet-service-transport-new \
  gnunet-transport-list-connections \
  gnunet-transport-certificate-creation
 
@@ -137,25 +136,14 @@
   libgnunettransport.la                                
 
 gnunet_service_transport_SOURCES = \
-  gnunet-service-transport.c
-gnunet_service_transport_LDADD = \
-  $(top_builddir)/src/ats/libgnunetats.la \
-  $(top_builddir)/src/hello/libgnunethello.la \
-  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(GN_GLPK) \
-  $(GN_LIBINTL)
-
-gnunet_service_transport_new_SOURCES = \
- gnunet-service-transport-new.c gnunet-service-transport.h \
+ gnunet-service-transport.c gnunet-service-transport.h \
  gnunet-service-transport_blacklist.h gnunet-service-transport_blacklist.c \
  gnunet-service-transport_clients.h gnunet-service-transport_clients.c \
  gnunet-service-transport_hello.h gnunet-service-transport_hello.c \
  gnunet-service-transport_neighbours.h gnunet-service-transport_neighbours.c \
  gnunet-service-transport_plugins.h gnunet-service-transport_plugins.c \
  gnunet-service-transport_validation.h gnunet-service-transport_validation.c 
-gnunet_service_transport_new_LDADD = \
+gnunet_service_transport_LDADD = \
   $(top_builddir)/src/ats/libgnunetats.la \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \

Deleted: gnunet/src/transport/gnunet-service-transport-new.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport-new.c 2011-09-13 12:25:52 UTC 
(rev 16807)
+++ gnunet/src/transport/gnunet-service-transport-new.c 2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -1,492 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2010,2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file transport/gnunet-service-transport-new.c
- * @brief
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_transport_service.h"
-#include "gnunet_peerinfo_service.h"
-#include "gnunet_ats_service.h"
-#include "gnunet-service-transport.h"
-#include "gnunet-service-transport_blacklist.h"
-#include "gnunet-service-transport_clients.h"
-#include "gnunet-service-transport_hello.h"
-#include "gnunet-service-transport_neighbours.h"
-#include "gnunet-service-transport_plugins.h"
-#include "gnunet-service-transport_validation.h"
-#include "transport.h"
-
-/* globals */
-
-/**
- * Statistics handle.
- */
-struct GNUNET_STATISTICS_Handle *GST_stats;
-
-/**
- * Configuration handle.
- */
-const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
-
-/**
- * Configuration handle.
- */
-struct GNUNET_PeerIdentity GST_my_identity;
-
-/**
- * Handle to peerinfo service.
- */
-struct GNUNET_PEERINFO_Handle *GST_peerinfo;
-
-/**
- * Our public key.
- */
-struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded GST_my_public_key;
-
-/**
- * Our private key.
- */
-struct GNUNET_CRYPTO_RsaPrivateKey *GST_my_private_key;
-
-/**
- * ATS handle.
- */
-struct GNUNET_ATS_Handle *GST_ats;
-
-
-/**
- * Transmit our HELLO message to the given (connected) neighbour.
- *
- * @param cls the 'HELLO' message
- * @param target a connected neighbour
- * @param ats performance information (unused)
- * @param ats_count number of records in ats (unused)
- */
-static void
-transmit_our_hello (void *cls, const struct GNUNET_PeerIdentity *target,
-                    const struct GNUNET_TRANSPORT_ATS_Information *ats,
-                    uint32_t ats_count)
-{
-  const struct GNUNET_MessageHeader *hello = cls;
-
-  GST_neighbours_send (target, (const char *) hello, ntohs (hello->size),
-                       GST_HELLO_ADDRESS_EXPIRATION, NULL, NULL);
-}
-
-
-/**
- * My HELLO has changed. Tell everyone who should know.
- *
- * @param cls unused
- * @param hello new HELLO
- */
-static void
-process_hello_update (void *cls, const struct GNUNET_MessageHeader *hello)
-{
-  GST_clients_broadcast (hello, GNUNET_NO);
-  GST_neighbours_iterate (&transmit_our_hello, (void *) hello);
-}
-
-
-/**
- * Try to initiate a connection to the given peer if the blacklist
- * allowed it.
- *
- * @param cls closure (unused, NULL)
- * @param peer identity of peer that was tested
- * @param result GNUNET_OK if the connection is allowed,
- *               GNUNET_NO if not
- */
-static void
-try_connect_if_allowed (void *cls, const struct GNUNET_PeerIdentity *peer,
-                        int result)
-{
-  if (GNUNET_OK != result)
-    return;                     /* not allowed */
-  GST_neighbours_try_connect (peer);
-}
-
-
-/**
- * Function called by the transport for each received message.
- * This function should also be called with "NULL" for the
- * message to signal that the other peer disconnected.
- *
- * @param cls closure, const char* with the name of the plugin we received the 
message from
- * @param peer (claimed) identity of the other peer
- * @param message the message, NULL if we only care about
- *                learning about the delay until we should receive again -- 
FIXME!
- * @param ats performance information
- * @param ats_count number of records in ats
- * @param session identifier used for this session (NULL for plugins
- *                that do not offer bi-directional communication to the sender
- *                using the same "connection")
- * @param sender_address binary address of the sender (if we established the
- *                connection or are otherwise sure of it; should be NULL
- *                for inbound TCP/UDP connections since it it not clear
- *                that we could establish ourselves a connection to that
- *                IP address and get the same system)
- * @param sender_address_len number of bytes in sender_address
- * @return how long the plugin should wait until receiving more data
- *         (plugins that do not support this, can ignore the return value)
- */
-static struct GNUNET_TIME_Relative
-plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
-                             const struct GNUNET_MessageHeader *message,
-                             const struct GNUNET_TRANSPORT_ATS_Information 
*ats,
-                             uint32_t ats_count, struct Session *session,
-                             const char *sender_address,
-                             uint16_t sender_address_len)
-{
-  const char *plugin_name = cls;
-  int do_forward;
-  struct GNUNET_TIME_Relative ret;
-  uint16_t type;
-
-  ret = GNUNET_TIME_UNIT_ZERO;
-  if (NULL != message)
-  {
-    type = ntohs (message->type);
-    switch (type)
-    {
-    case GNUNET_MESSAGE_TYPE_HELLO:
-      GST_validation_handle_hello (message);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-                  "Processing `%s' from `%s'\n", "PING",
-                  (sender_address != NULL) ? GST_plugins_a2s (plugin_name,
-                                                              sender_address,
-                                                              
sender_address_len)
-                  : "<inbound>");
-#endif
-      GST_validation_handle_ping (peer, message, plugin_name, session,
-                                  sender_address, sender_address_len);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-                  "Processing `%s' from `%s'\n", "PONG",
-                  (sender_address != NULL) ? GST_plugins_a2s (plugin_name,
-                                                              sender_address,
-                                                              
sender_address_len)
-                  : "<inbound>");
-#endif
-      GST_validation_handle_pong (peer, message);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT:
-      (void) GST_blacklist_test_allowed (peer, NULL, &try_connect_if_allowed,
-                                         NULL);
-      /* TODO: if 'session != NULL', and timestamp more recent than the
-       * previous one, maybe notify ATS that this is now the preferred
-       * * way to communicate with this peer (other peer switched transport) */
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT:
-      /* TODO: do some validation to prevent an attacker from sending
-       * a fake disconnect message... */
-      GST_neighbours_force_disconnect (peer);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE:
-      GST_neighbours_keepalive (peer);
-      break;
-    default:
-      /* should be payload */
-      do_forward = GNUNET_SYSERR;
-      ret =
-          GST_neighbours_calculate_receive_delay (peer,
-                                                  (message ==
-                                                   NULL) ? 0 :
-                                                  ntohs (message->size),
-                                                  &do_forward);
-      if (do_forward == GNUNET_YES)
-      {
-        struct InboundMessage *im;
-        size_t size = sizeof (struct InboundMessage) + ntohs (message->size);
-
-        im = GNUNET_malloc (size);
-        im->header.size = htons (size);
-        im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
-        im->ats_count = htonl (0);
-        memcpy (&(im->peer), peer, sizeof (struct GNUNET_PeerIdentity));
-        memcpy (&im[1], message, ntohs (message->size));
-
-        GST_clients_broadcast ((const struct GNUNET_MessageHeader *) im,
-                               GNUNET_YES);
-
-        GNUNET_free (im);
-      }
-      break;
-    }
-  }
-
-  GNUNET_assert ((ats_count > 0) && (ats != NULL));
-
-  GNUNET_ATS_address_update (GST_ats, peer, GNUNET_TIME_absolute_get (),       
 /* valid at least until right now... */
-                             plugin_name, session, sender_address,
-                             sender_address_len, ats, ats_count);
-
-  return ret;
-}
-
-
-/**
- * Function that will be called for each address the transport
- * is aware that it might be reachable under.  Update our HELLO.
- *
- * @param cls name of the plugin (const char*)
- * @param add_remove should the address added (YES) or removed (NO) from the
- *                   set of valid addresses?
- * @param addr one of the addresses of the host
- *        the specific address format depends on the transport
- * @param addrlen length of the address
- */
-static void
-plugin_env_address_change_notification (void *cls, int add_remove,
-                                        const void *addr, size_t addrlen)
-{
-  const char *plugin_name = cls;
-
-  GST_hello_modify_addresses (add_remove, plugin_name, addr, addrlen);
-}
-
-
-/**
- * Function that will be called whenever the plugin internally
- * cleans up a session pointer and hence the service needs to
- * discard all of those sessions as well.  Plugins that do not
- * use sessions can simply omit calling this function and always
- * use NULL wherever a session pointer is needed.  This function
- * should be called BEFORE a potential "TransmitContinuation"
- * from the "TransmitFunction".
- *
- * @param cls closure
- * @param peer which peer was the session for
- * @param session which session is being destoyed
- */
-static void
-plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
-                        struct Session *session)
-{
-  GST_neighbours_session_terminated (peer, session);
-}
-
-
-/**
- * Function called by ATS to notify the callee that the
- * assigned bandwidth or address for a given peer was changed.  If the
- * callback is called with address/bandwidth assignments of zero, the
- * ATS disconnect function will still be called once the disconnect
- * actually happened.
- *
- * @param cls closure
- * @param peer identity of the peer
- * @param plugin_name name of the transport plugin, NULL to disconnect
- * @param session session to use (if available)
- * @param plugin_addr address to use (if available)
- * @param plugin_addr_len number of bytes in addr
- * @param bandwidth assigned outbound bandwidth for the connection
- */
-static void
-ats_request_address_change (void *cls, const struct GNUNET_PeerIdentity *peer,
-                            const char *plugin_name, struct Session *session,
-                            const void *plugin_addr, size_t plugin_addr_len,
-                            struct GNUNET_BANDWIDTH_Value32NBO bandwidth)
-{
-  GST_neighbours_switch_to_address (peer, plugin_name, plugin_addr,
-                                    plugin_addr_len, session, NULL, 0);
-  GST_neighbours_set_incoming_quota (peer, bandwidth);
-}
-
-
-/**
- * Function called to notify transport users that another
- * peer connected to us.
- *
- * @param cls closure
- * @param peer the peer that connected
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
- */
-static void
-neighbours_connect_notification (void *cls,
-                                 const struct GNUNET_PeerIdentity *peer,
-                                 const struct GNUNET_TRANSPORT_ATS_Information
-                                 *ats, uint32_t ats_count)
-{
-  char buf[sizeof (struct ConnectInfoMessage) +
-           ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)];
-  struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf;
-  struct GNUNET_TRANSPORT_ATS_Information *atsm = &connect_msg->ats;
-
-  connect_msg->header.size = htons (sizeof (buf));
-  connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
-  connect_msg->ats_count = htonl (ats_count);
-  connect_msg->id = *peer;
-  memcpy (&connect_msg->ats, ats,
-          ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
-  atsm[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
-  atsm[ats_count].value = htonl (0);
-  GST_clients_broadcast (&connect_msg->header, GNUNET_NO);
-}
-
-
-/**
- * Function called to notify transport users that another
- * peer disconnected from us.
- *
- * @param cls closure
- * @param peer the peer that disconnected
- */
-static void
-neighbours_disconnect_notification (void *cls,
-                                    const struct GNUNET_PeerIdentity *peer)
-{
-  struct DisconnectInfoMessage disconnect_msg;
-
-  disconnect_msg.header.size = htons (sizeof (struct DisconnectInfoMessage));
-  disconnect_msg.header.type = htons 
(GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
-  disconnect_msg.reserved = htonl (0);
-  disconnect_msg.peer = *peer;
-  GST_clients_broadcast (&disconnect_msg.header, GNUNET_NO);
-}
-
-
-/**
- * Function called when the service shuts down.  Unloads our plugins
- * and cancels pending validations.
- *
- * @param cls closure, unused
- * @param tc task context (unused)
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GST_validation_stop ();
-  GST_plugins_unload ();
-  GST_neighbours_stop ();
-  GNUNET_ATS_shutdown (GST_ats);
-  GST_ats = NULL;
-  GST_clients_stop ();
-  GST_blacklist_stop ();
-  GST_hello_stop ();
-
-  if (GST_peerinfo != NULL)
-  {
-    GNUNET_PEERINFO_disconnect (GST_peerinfo);
-    GST_peerinfo = NULL;
-  }
-  if (GST_stats != NULL)
-  {
-    GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
-    GST_stats = NULL;
-  }
-  if (GST_my_private_key != NULL)
-  {
-    GNUNET_CRYPTO_rsa_key_free (GST_my_private_key);
-    GST_my_private_key = NULL;
-  }
-}
-
-
-/**
- * Initiate transport service.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  char *keyfile;
-
-  /* setup globals */
-  GST_cfg = c;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
-                                               &keyfile))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("Transport service is lacking key configuration settings.  
Exiting.\n"));
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GST_my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
-  GNUNET_free (keyfile);
-  if (GST_my_private_key == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Transport service could not access hostkey.  Exiting.\n"));
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  GST_stats = GNUNET_STATISTICS_create ("transport", c);
-  GST_peerinfo = GNUNET_PEERINFO_connect (c);
-  GNUNET_CRYPTO_rsa_key_get_public (GST_my_private_key, &GST_my_public_key);
-  GNUNET_CRYPTO_hash (&GST_my_public_key, sizeof (GST_my_public_key),
-                      &GST_my_identity.hashPubKey);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
-                                NULL);
-  if (GST_peerinfo == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Could not access PEERINFO service.  Exiting.\n"));
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
-  /* start subsystems */
-  GST_hello_start (&process_hello_update, NULL);
-  GST_blacklist_start (server);
-  GST_plugins_load (&plugin_env_receive_callback,
-                    &plugin_env_address_change_notification,
-                    &plugin_env_session_end);
-  GST_ats = GNUNET_ATS_init (GST_cfg, &ats_request_address_change, NULL);
-  GST_neighbours_start (NULL, &neighbours_connect_notification,
-                        &neighbours_disconnect_notification);
-  GST_clients_start (server);
-  GST_validation_start ();
-}
-
-
-/**
- * The main function for the transport service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  return (GNUNET_OK ==
-          GNUNET_SERVICE_run (argc, argv, "transport",
-                              GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
-}
-
-/* end of file gnunet-service-transport-new.c */

Deleted: gnunet/src/transport/gnunet-service-transport.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport.c     2011-09-13 12:25:52 UTC 
(rev 16807)
+++ gnunet/src/transport/gnunet-service-transport.c     2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -1,6533 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file transport/gnunet-service-transport.c
- * @brief low-level P2P messaging
- * @author Christian Grothoff
- *
- */
-#include "platform.h"
-#include "gnunet_client_lib.h"
-#include "gnunet_container_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_hello_lib.h"
-#include "gnunet_os_lib.h"
-#include "gnunet_peerinfo_service.h"
-#include "gnunet_plugin_lib.h"
-#include "gnunet_protocols.h"
-#include "gnunet_service_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_transport_plugin.h"
-#include "gnunet-service-transport_ats.h"
-#include "transport.h"
-
-
-
-#define DEBUG_BLACKLIST GNUNET_NO
-
-#define DEBUG_PING_PONG GNUNET_NO
-
-#define DEBUG_TRANSPORT_HELLO GNUNET_NO
-
-#define DEBUG_INBOUND GNUNET_NO
-
-/**
- * Should we do some additional checks (to validate behavior
- * of clients)?
- */
-#define EXTRA_CHECKS GNUNET_YES
-
-/**
- * How many messages can we have pending for a given client process
- * before we start to drop incoming messages?  We typically should
- * have only one client and so this would be the primary buffer for
-  * messages, so the number should be chosen rather generously.
- *
- * The expectation here is that most of the time the queue is large
- * enough so that a drop is virtually never required.  Note that
- * this value must be about as large as 'TOTAL_MSGS' in the
- * 'test_transport_api_reliability.c', otherwise that testcase may
- * fail.
- */
-#define MAX_PENDING (128 * 1024)
-
-/**
- * Size of the per-transport blacklist hash maps.
- */
-#define TRANSPORT_BLACKLIST_HT_SIZE 16
-
-/**
- * How often should we try to reconnect to a peer using a particular
- * transport plugin before giving up?  Note that the plugin may be
- * added back to the list after PLUGIN_RETRY_FREQUENCY expires.
- */
-#define MAX_CONNECT_RETRY 3
-
-/**
- * Limit on the number of ready-to-run tasks when validating
- * HELLOs.  If more tasks are ready to run, we will drop
- * HELLOs instead of validating them.
- */
-#define MAX_HELLO_LOAD 4
-
-/**
- * How often must a peer violate bandwidth quotas before we start
- * to simply drop its messages?
- */
-#define QUOTA_VIOLATION_DROP_THRESHOLD 10
-
-/**
- * How long until a HELLO verification attempt should time out?
- * Must be rather small, otherwise a partially successful HELLO
- * validation (some addresses working) might not be available
- * before a client's request for a connection fails for good.
- * Besides, if a single request to an address takes a long time,
- * then the peer is unlikely worthwhile anyway.
- */
-#define HELLO_VERIFICATION_TIMEOUT GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 15)
-
-/**
- * How long is a PONG signature valid?  We'll recycle a signature until
- * 1/4 of this time is remaining.  PONGs should expire so that if our
- * external addresses change an adversary cannot replay them indefinitely.
- * OTOH, we don't want to spend too much time generating PONG signatures,
- * so they must have some lifetime to reduce our CPU usage.
- */
-#define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_HOURS, 1)
-
-/**
- * Priority to use for PONG messages.
- */
-#define TRANSPORT_PONG_PRIORITY 4
-
-/**
- * How often do we re-add (cheaper) plugins to our list of plugins
- * to try for a given connected peer?
- */
-#define PLUGIN_RETRY_FREQUENCY GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 15)
-
-/**
- * After how long do we expire an address in a HELLO that we just
- * validated?  This value is also used for our own addresses when we
- * create a HELLO.
- */
-#define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_HOURS, 12)
-
-
-/**
- * How long before an existing address expires should we again try to
- * validate it?  Must be (significantly) smaller than
- * HELLO_ADDRESS_EXPIRATION.
- */
-#define HELLO_REVALIDATION_START_TIME GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_HOURS, 1)
-
-/**
- * List of addresses of other peers
- */
-struct ForeignAddressList
-{
-  /**
-   * This is a linked list.
-   */
-  struct ForeignAddressList *next;
-
-  /**
-   * Which ready list does this entry belong to.
-   */
-  struct ReadyList *ready_list;
-
-  /**
-   * How long until we auto-expire this address (unless it is
-   * re-confirmed by the transport)?
-   */
-  struct GNUNET_TIME_Absolute expires;
-
-  /**
-   * Task used to re-validate addresses, updates latencies and
-   * verifies liveness.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier revalidate_task;
-
-  /**
-   * The address.
-   */
-  const void *addr;
-
-  /**
-   * Session (or NULL if no valid session currently exists or if the
-   * plugin does not use sessions).
-   */
-  struct Session *session;
-
-  struct ATS_ressource_entry *ressources;
-
-  struct ATS_quality_entry *quality;
-
-  /**
-   * What was the last latency observed for this address, plugin and peer?
-   */
-  struct GNUNET_TIME_Relative latency;
-
-  /**
-   * If we did not successfully transmit a message to the given peer
-   * via this connection during the specified time, we should consider
-   * the connection to be dead.  This is used in the case that a TCP
-   * transport simply stalls writing to the stream but does not
-   * formerly get a signal that the other peer died.
-   */
-  struct GNUNET_TIME_Absolute timeout;
-
-  /**
-   * How often have we tried to connect using this plugin?  Used to
-   * discriminate against addresses that do not work well.
-   * FIXME: not yet used, but should be!
-   */
-  unsigned int connect_attempts;
-
-  /**
-   * DV distance to this peer (1 if no DV is used).
-   * FIXME: need to set this from transport plugins!
-   */
-  uint32_t distance;
-
-  /**
-   * Length of addr.
-   */
-  uint16_t addrlen;
-
-  /**
-   * Have we ever estimated the latency of this address?  Used to
-   * ensure that the first time we add an address, we immediately
-   * probe its latency.
-   */
-  int8_t estimated;
-
-  /**
-   * Are we currently connected via this address?  The first time we
-   * successfully transmit or receive data to a peer via a particular
-   * address, we set this to GNUNET_YES.  If we later get an error
-   * (disconnect notification, transmission failure, timeout), we set
-   * it back to GNUNET_NO.
-   */
-  int8_t connected;
-
-  /**
-   * Is this plugin currently busy transmitting to the specific target?
-   * GNUNET_NO if not (initial, default state is GNUNET_NO).   Internal
-   * messages do not count as 'in transmit'.
-   */
-  int8_t in_transmit;
-
-  /**
-   * Has this address been validated yet?
-   */
-  int8_t validated;
-
-};
-
-
-/**
- * Entry in linked list of network addresses for ourselves.  Also
- * includes a cached signature for 'struct TransportPongMessage's.
- */
-struct OwnAddressList
-{
-  /**
-   * This is a linked list.
-   */
-  struct OwnAddressList *next;
-
-  /**
-   * How long until the current signature expires? (ZERO if the
-   * signature was never created).
-   */
-  struct GNUNET_TIME_Absolute pong_sig_expires;
-
-  /**
-   * Signature for a 'struct TransportPongMessage' for this address.
-   */
-  struct GNUNET_CRYPTO_RsaSignature pong_signature;
-
-  /**
-   * Length of addr.
-   */
-  uint32_t addrlen;
-
-};
-
-
-/**
- * Entry in linked list of all of our plugins.
- */
-struct TransportPlugin
-{
-  /**
-   * This is a linked list.
-   */
-  struct TransportPlugin *next;
-
-  /**
-   * API of the transport as returned by the plugin's
-   * initialization function.
-   */
-  struct GNUNET_TRANSPORT_PluginFunctions *api;
-
-  /**
-   * Short name for the plugin (i.e. "tcp").
-   */
-  char *short_name;
-
-  /**
-   * Name of the library (i.e. "gnunet_plugin_transport_tcp").
-   */
-  char *lib_name;
-
-  /**
-   * List of our known addresses for this transport.
-   */
-  struct OwnAddressList *addresses;
-
-  /**
-   * Environment this transport service is using
-   * for this plugin.
-   */
-  struct GNUNET_TRANSPORT_PluginEnvironment env;
-
-  /**
-   * ID of task that is used to clean up expired addresses.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier address_update_task;
-
-  /**
-   * Set to GNUNET_YES if we need to scrap the existing list of
-   * "addresses" and start fresh when we receive the next address
-   * update from a transport.  Set to GNUNET_NO if we should just add
-   * the new address to the list and wait for the commit call.
-   */
-  int rebuild;
-
-  struct ATS_plugin *rc;
-
-  /**
-   * Hashmap of blacklisted peers for this particular transport.
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *blacklist;
-};
-
-struct NeighbourMapEntry;
-
-/**
- * For each neighbour we keep a list of messages
- * that we still want to transmit to the neighbour.
- */
-struct MessageQueue
-{
-
-  /**
-   * This is a doubly linked list.
-   */
-  struct MessageQueue *next;
-
-  /**
-   * This is a doubly linked list.
-   */
-  struct MessageQueue *prev;
-
-  /**
-   * The message(s) we want to transmit, GNUNET_MessageHeader(s)
-   * stuck together in memory.  Allocated at the end of this struct.
-   */
-  const char *message_buf;
-
-  /**
-   * Size of the message buf
-   */
-  size_t message_buf_size;
-
-  /**
-   * Client responsible for queueing the message;
-   * used to check that a client has no two messages
-   * pending for the same target.  Can be NULL.
-   */
-  struct TransportClient *client;
-
-  /**
-   * Using which specific address should we send this message?
-   */
-  struct ForeignAddressList *specific_address;
-
-  /**
-   * Peer ID of the Neighbour this entry belongs to.
-   */
-  struct GNUNET_PeerIdentity neighbour_id;
-
-  /**
-   * Plugin that we used for the transmission.
-   * NULL until we scheduled a transmission.
-   */
-  struct TransportPlugin *plugin;
-
-  /**
-   * At what time should we fail?
-   */
-  struct GNUNET_TIME_Absolute timeout;
-
-  /**
-   * Internal message of the transport system that should not be
-   * included in the usual SEND-SEND_OK transmission confirmation
-   * traffic management scheme.  Typically, "internal_msg" will
-   * be set whenever "client" is NULL (but it is not strictly
-   * required).
-   */
-  int internal_msg;
-
-  /**
-   * How important is the message?
-   */
-  unsigned int priority;
-
-};
-
-
-/**
- * For a given Neighbour, which plugins are available
- * to talk to this peer and what are their costs?
- */
-struct ReadyList
-{
-  /**
-   * This is a linked list.
-   */
-  struct ReadyList *next;
-
-  /**
-   * Which of our transport plugins does this entry
-   * represent?
-   */
-  struct TransportPlugin *plugin;
-
-  /**
-   * Transport addresses, latency, and readiness for
-   * this particular plugin.
-   */
-  struct ForeignAddressList *addresses;
-
-  /**
-   * To which neighbour does this ready list belong to?
-   */
-  struct NeighbourMapEntry *neighbour;
-};
-
-
-/**
- * Entry in neighbours.
- */
-struct NeighbourMapEntry
-{
-
-  /**
-   * Which of our transports is connected to this peer
-   * and what is their status?
-   */
-  struct ReadyList *plugins;
-
-  /**
-   * Head of list of messages we would like to send to this peer;
-   * must contain at most one message per client.
-   */
-  struct MessageQueue *messages_head;
-
-  /**
-   * Tail of list of messages we would like to send to this peer; must
-   * contain at most one message per client.
-   */
-  struct MessageQueue *messages_tail;
-
-  /**
-   * Head of list of messages of messages we expected the continuation
-   * to be called to destroy the message
-   */
-  struct MessageQueue *cont_head;
-
-  /**
-   * Tail of list of messages of messages we expected the continuation
-   * to be called to destroy the message
-   */
-  struct MessageQueue *cont_tail;
-
-  /**
-   * Buffer for at most one payload message used when we receive
-   * payload data before our PING-PONG has succeeded.  We then
-   * store such messages in this intermediary buffer until the
-   * connection is fully up.
-   */
-  struct GNUNET_MessageHeader *pre_connect_message_buffer;
-
-  /**
-   * Context for peerinfo iteration.
-   * NULL after we are done processing peerinfo's information.
-   */
-  struct GNUNET_PEERINFO_IteratorContext *piter;
-
-  /**
-   * Public key for this peer.   Valid only if the respective flag is set 
below.
-   */
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
-
-  /**
-   * Identity of this neighbour.
-   */
-  struct GNUNET_PeerIdentity id;
-
-  /**
-   * ID of task scheduled to run when this peer is about to
-   * time out (will free resources associated with the peer).
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-  /**
-   * ID of task scheduled to run when we should retry transmitting
-   * the head of the message queue.  Actually triggered when the
-   * transmission is timing out (we trigger instantly when we have
-   * a chance of success).
-   */
-  GNUNET_SCHEDULER_TaskIdentifier retry_task;
-
-  /**
-   * How long until we should consider this peer dead
-   * (if we don't receive another message in the
-   * meantime)?
-   */
-  struct GNUNET_TIME_Absolute peer_timeout;
-
-  /**
-   * Tracker for inbound bandwidth.
-   */
-  struct GNUNET_BANDWIDTH_Tracker in_tracker;
-
-  /**
-   * The latency we have seen for this particular address for
-   * this particular peer.  This latency may have been calculated
-   * over multiple transports.  This value reflects how long it took
-   * us to receive a response when SENDING via this particular
-   * transport/neighbour/address combination!
-   *
-   * FIXME: we need to periodically send PINGs to update this
-   * latency (at least more often than the current "huge" (11h?)
-   * update interval).
-   */
-  struct GNUNET_TIME_Relative latency;
-
-  /**
-   * How often has the other peer (recently) violated the
-   * inbound traffic limit?  Incremented by 10 per violation,
-   * decremented by 1 per non-violation (for each
-   * time interval).
-   */
-  unsigned int quota_violation_count;
-
-  /**
-   * DV distance to this peer (1 if no DV is used).
-   */
-  uint32_t distance;
-
-  /**
-   * Have we seen an PONG from this neighbour in the past (and
-   * not had a disconnect since)?
-   */
-  int received_pong;
-
-  /**
-   * Do we have a valid public key for this neighbour?
-   */
-  int public_key_valid;
-
-  /**
-   * Are we already in the process of disconnecting this neighbour?
-   */
-  int in_disconnect;
-
-  /**
-   * Performance data for the peer.
-   */
-  struct GNUNET_TRANSPORT_ATS_Information *ats;
-};
-
-/**
- * Message used to ask a peer to validate receipt (to check an address
- * from a HELLO).  Followed by the address we are trying to validate,
- * or an empty address if we are just sending a PING to confirm that a
- * connection which the receiver (of the PING) initiated is still valid.
- */
-struct TransportPingMessage
-{
-
-  /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Challenge code (to ensure fresh reply).
-   */
-  uint32_t challenge GNUNET_PACKED;
-
-  /**
-   * Who is the intended recipient?
-   */
-  struct GNUNET_PeerIdentity target;
-
-};
-
-
-/**
- * Message used to validate a HELLO.  The challenge is included in the
- * confirmation to make matching of replies to requests possible.  The
- * signature signs our public key, an expiration time and our address.<p>
- *
- * This message is followed by our transport address that the PING tried
- * to confirm (if we liked it).  The address can be empty (zero bytes)
- * if the PING had not address either (and we received the request via
- * a connection that we initiated).
- */
-struct TransportPongMessage
-{
-
-  /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Challenge code from PING (showing freshness).  Not part of what
-   * is signed so that we can re-use signatures.
-   */
-  uint32_t challenge GNUNET_PACKED;
-
-  /**
-   * Signature.
-   */
-  struct GNUNET_CRYPTO_RsaSignature signature;
-
-  /**
-   * What are we signing and why?  Two possible reason codes can be here:
-   * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a
-   * plausible address for this peer (pid is set to identity of signer); or
-   * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING to confirm that this is
-   * an address we used to connect to the peer with the given pid.
-   */
-  struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
-
-  /**
-   * When does this signature expire?
-   */
-  struct GNUNET_TIME_AbsoluteNBO expiration;
-
-  /**
-   * Either the identity of the peer Who signed this message, or the
-   * identity of the peer that we're connected to using the given
-   * address (depending on purpose.type).
-   */
-  struct GNUNET_PeerIdentity pid;
-
-  /**
-   * Size of address appended to this message (part of what is
-   * being signed, hence not redundant).
-   */
-  uint32_t addrlen;
-
-};
-
-
-/**
- * Linked list of messages to be transmitted to the client.  Each
- * entry is followed by the actual message.
- */
-struct ClientMessageQueueEntry
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct ClientMessageQueueEntry *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct ClientMessageQueueEntry *prev;
-};
-
-
-/**
- * Client connected to the transport service.
- */
-struct TransportClient
-{
-
-  /**
-   * This is a linked list.
-   */
-  struct TransportClient *next;
-
-  /**
-   * Handle to the client.
-   */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Linked list of messages yet to be transmitted to
-   * the client.
-   */
-  struct ClientMessageQueueEntry *message_queue_head;
-
-  /**
-   * Tail of linked list of messages yet to be transmitted to the
-   * client.
-   */
-  struct ClientMessageQueueEntry *message_queue_tail;
-
-  /**
-   * Current transmit request handle.
-   */
-  struct GNUNET_CONNECTION_TransmitHandle *th;
-
-  /**
-   * Is a call to "transmit_send_continuation" pending?  If so, we
-   * must not free this struct (even if the corresponding client
-   * disconnects) and instead only remove it from the linked list and
-   * set the "client" field to NULL.
-   */
-  int tcs_pending;
-
-  /**
-   * Length of the list of messages pending for this client.
-   */
-  unsigned int message_count;
-
-};
-
-
-/**
- * Context of currently active requests to peerinfo
- * for validation of HELLOs.
- */
-struct CheckHelloValidatedContext;
-
-
-/**
- * Entry in map of all HELLOs awaiting validation.
- */
-struct ValidationEntry
-{
-
-  /**
-   * NULL if this entry is not part of a larger HELLO validation.
-   */
-  struct CheckHelloValidatedContext *chvc;
-
-  /**
-   * The address, actually a pointer to the end
-   * of this struct.  Do not free!
-   */
-  const void *addr;
-
-  /**
-   * Name of the transport.
-   */
-  char *transport_name;
-
-  /**
-   * The public key of the peer.
-   */
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
-
-  /**
-   * ID of task that will clean up this entry if we don't succeed
-   * with the validation first.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-  /**
-   * At what time did we send this validation?
-   */
-  struct GNUNET_TIME_Absolute send_time;
-
-  /**
-   * Session being validated (or NULL for none).
-   */
-  struct Session *session;
-
-  /**
-   * Challenge number we used.
-   */
-  uint32_t challenge;
-
-  /**
-   * Length of addr.
-   */
-  uint16_t addrlen;
-
-};
-
-
-/**
- * Context of currently active requests to peerinfo
- * for validation of HELLOs.
- */
-struct CheckHelloValidatedContext
-{
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct CheckHelloValidatedContext *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct CheckHelloValidatedContext *prev;
-
-  /**
-   * Hello that we are validating.
-   */
-  const struct GNUNET_HELLO_Message *hello;
-
-  /**
-   * Context for peerinfo iteration.
-   * NULL after we are done processing peerinfo's information.
-   */
-  struct GNUNET_PEERINFO_IteratorContext *piter;
-
-  /**
-   * Was a HELLO known for this peer to peerinfo?
-   */
-  int hello_known;
-
-  /**
-   * Number of validation entries currently referring to this
-   * CHVC.
-   */
-  unsigned int ve_count;
-};
-
-
-/**
- * All zero hash for comparison.
- */
-static GNUNET_HashCode null_hash;
-
-/**
- * Our HELLO message.
- */
-static struct GNUNET_HELLO_Message *our_hello;
-
-/**
- * Our public key.
- */
-static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
-
-/**
- * Our identity.
- */
-static struct GNUNET_PeerIdentity my_identity;
-
-/**
- * Our private key.
- */
-static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
-
-/**
- * Our configuration.
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Linked list of all clients to this service.
- */
-static struct TransportClient *clients;
-
-/**
- * All loaded plugins.
- */
-static struct TransportPlugin *plugins;
-
-/**
- * Handle to peerinfo service.
- */
-static struct GNUNET_PEERINFO_Handle *peerinfo;
-
-/**
- * All known neighbours and their HELLOs.
- */
-static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
-
-/**
- * Number of neighbours we'd like to have.
- */
-static uint32_t max_connect_per_transport;
-
-/**
- * Head of linked list.
- */
-static struct CheckHelloValidatedContext *chvc_head;
-
-/**
- * Tail of linked list.
- */
-static struct CheckHelloValidatedContext *chvc_tail;
-
-/**
- * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
- * of the given peer that we are currently validating).
- */
-static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
-
-/**
- * Handle for reporting statistics.
- */
-static struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Identifier of 'refresh_hello' task.
- */
-static GNUNET_SCHEDULER_TaskIdentifier hello_task;
-
-/**
- * Identifier of ats scheduler task.
- */
-static GNUNET_SCHEDULER_TaskIdentifier ats_task;
-
-/**
- * Is transport service shutting down ?
- */
-static int shutdown_in_progress;
-
-/**
- * Handle for ats information
- */
-static struct ATS_Handle *ats;
-
-/**
- * Time of last ats execution
- */
-struct GNUNET_TIME_Absolute last_ats_execution;
-
-/**
- * Minimum interval between two ATS executions
- */
-struct GNUNET_TIME_Relative ats_minimum_interval;
-
-/**
- * Regular interval when ATS execution is triggered
- */
-struct GNUNET_TIME_Relative ats_regular_interval;
-
-/**
- * The peer specified by the given neighbour has timed-out or a plugin
- * has disconnected.  We may either need to do nothing (other plugins
- * still up), or trigger a full disconnect and clean up.  This
- * function updates our state and do the necessary notifications.
- * Also notifies our clients that the neighbour is now officially
- * gone.
- *
- * @param n the neighbour list entry for the peer
- * @param check should we just check if all plugins
- *        disconnected or must we ask all plugins to
- *        disconnect?
- */
-static void
-disconnect_neighbour (struct NeighbourMapEntry *n, int check);
-
-/**
- * Check the ready list for the given neighbour and if a plugin is
- * ready for transmission (and if we have a message), do so!
- *
- * @param nexi target peer for which to transmit
- */
-static void
-try_transmission_to_peer (struct NeighbourMapEntry *n);
-
-struct ForeignAddressList *
-get_preferred_ats_address (struct NeighbourMapEntry *n);
-
-/**
- * Find an entry in the neighbour list for a particular peer.
- *
- * @return NULL if not found.
- */
-static struct NeighbourMapEntry *
-find_neighbour (const struct GNUNET_PeerIdentity *key)
-{
-  return GNUNET_CONTAINER_multihashmap_get (neighbours, &key->hashPubKey);
-}
-
-static int
-update_addr_value (struct ForeignAddressList *fal, uint32_t value,
-                   int ats_index)
-{
-  int c;
-  int set = GNUNET_NO;
-
-  for (c = 0; c < available_quality_metrics; c++)
-  {
-    if (ats_index == qm[c].atis_index)
-    {
-      fal->quality[c].values[0] = fal->quality[c].values[1];
-      fal->quality[c].values[1] = fal->quality[c].values[2];
-      fal->quality[c].values[2] = value;
-      set = GNUNET_YES;
-#if HAVE_LIBGLPK
-      ats_modify_problem_state (ats, ATS_QUALITY_UPDATED);
-#endif
-    }
-  }
-  if (set == GNUNET_NO)
-  {
-    for (c = 0; c < available_ressources; c++)
-    {
-      if (ats_index == ressources[c].atis_index)
-      {
-        fal->ressources[c].c = value;
-        set = GNUNET_YES;
-#if HAVE_LIBGLPK
-        ats_modify_problem_state (ats, ATS_COST_UPDATED);
-#endif
-      }
-    }
-  }
-  return set;
-}
-
-static int
-update_addr_ats (struct ForeignAddressList *fal,
-                 const struct GNUNET_TRANSPORT_ATS_Information *ats_data,
-                 int ats_count)
-{
-  int c1, set;
-
-  set = GNUNET_NO;
-  for (c1 = 0; c1 < ats_count; c1++)
-  {
-    set =
-        update_addr_value (fal, ntohl (ats_data[c1].value),
-                           ntohl (ats_data[c1].type));
-  }
-  return set;
-}
-
-/**
- * Find an entry in the transport list for a particular transport.
- *
- * @return NULL if not found.
- */
-static struct TransportPlugin *
-find_transport (const char *short_name)
-{
-  struct TransportPlugin *head = plugins;
-
-  while ((head != NULL) && (0 != strcmp (short_name, head->short_name)))
-    head = head->next;
-  return head;
-}
-
-/**
- * Is a particular peer blacklisted for a particular transport?
- *
- * @param peer the peer to check for
- * @param plugin the plugin used to connect to the peer
- *
- * @return GNUNET_YES if the peer is blacklisted, GNUNET_NO if not
- */
-static int
-is_blacklisted (const struct GNUNET_PeerIdentity *peer,
-                struct TransportPlugin *plugin)
-{
-
-  if (plugin->blacklist != NULL)
-  {
-    if (GNUNET_CONTAINER_multihashmap_contains
-        (plugin->blacklist, &peer->hashPubKey) == GNUNET_YES)
-    {
-#if DEBUG_BLACKLIST
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s:%s' is blacklisted!\n",
-                  plugin->short_name, GNUNET_i2s (peer));
-#endif
-      if (stats != NULL)
-        GNUNET_STATISTICS_update (stats, "# blacklisted peers refused", 1,
-                                  GNUNET_NO);
-      return GNUNET_YES;
-    }
-  }
-
-  return GNUNET_NO;
-}
-
-
-static void
-add_peer_to_blacklist (struct GNUNET_PeerIdentity *peer, char *transport_name)
-{
-  struct TransportPlugin *plugin;
-
-  plugin = find_transport (transport_name);
-  if (plugin == NULL)           /* Nothing to do */
-    return;
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Adding peer `%s' with plugin `%s' to blacklist\n",
-              GNUNET_i2s (peer), transport_name);
-#endif
-  if (plugin->blacklist == NULL)
-    plugin->blacklist =
-        GNUNET_CONTAINER_multihashmap_create (TRANSPORT_BLACKLIST_HT_SIZE);
-  GNUNET_assert (plugin->blacklist != NULL);
-  GNUNET_CONTAINER_multihashmap_put (plugin->blacklist, &peer->hashPubKey, 
NULL,
-                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-}
-
-
-/**
- * Read the blacklist file, containing transport:peer entries.
- * Provided the transport is loaded, set up hashmap with these
- * entries to blacklist peers by transport.
- *
- */
-static void
-read_blacklist_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  char *fn;
-  char *data;
-  size_t pos;
-  size_t colon_pos;
-  int tsize;
-  struct GNUNET_PeerIdentity pid;
-  struct stat frstat;
-  struct GNUNET_CRYPTO_HashAsciiEncoded enc;
-  unsigned int entries_found;
-  char *transport_name;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (cfg, "TRANSPORT",
-                                               "BLACKLIST_FILE", &fn))
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Option `%s' in section `%s' not specified!\n",
-                "BLACKLIST_FILE", "TRANSPORT");
-#endif
-    return;
-  }
-  if (GNUNET_OK != GNUNET_DISK_file_test (fn))
-    GNUNET_DISK_fn_write (fn, NULL, 0,
-                          GNUNET_DISK_PERM_USER_READ |
-                          GNUNET_DISK_PERM_USER_WRITE);
-  if (0 != STAT (fn, &frstat))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Could not read blacklist file `%s'\n"), fn);
-    GNUNET_free (fn);
-    return;
-  }
-  if (frstat.st_size == 0)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Blacklist file `%s' is empty.\n"),
-                fn);
-#endif
-    GNUNET_free (fn);
-    return;
-  }
-  /* FIXME: use mmap */
-  data = GNUNET_malloc_large (frstat.st_size);
-  GNUNET_assert (data != NULL);
-  if (frstat.st_size != GNUNET_DISK_fn_read (fn, data, frstat.st_size))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Failed to read blacklist from `%s'\n"), fn);
-    GNUNET_free (fn);
-    GNUNET_free (data);
-    return;
-  }
-  entries_found = 0;
-  pos = 0;
-  while ((pos < frstat.st_size) && isspace ((unsigned char) data[pos]))
-    pos++;
-  while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
-         (pos <=
-          frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
-  {
-    colon_pos = pos;
-    while ((colon_pos < frstat.st_size) && (data[colon_pos] != ':') &&
-           !isspace ((unsigned char) data[colon_pos]))
-      colon_pos++;
-
-    if (colon_pos >= frstat.st_size)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Syntax error in blacklist file at offset %llu, giving 
up!\n"),
-                  (unsigned long long) colon_pos);
-      GNUNET_free (fn);
-      GNUNET_free (data);
-      return;
-    }
-
-    if (isspace ((unsigned char) data[colon_pos]))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Syntax error in blacklist file at offset %llu, skipping 
bytes.\n"),
-                  (unsigned long long) colon_pos);
-      pos = colon_pos;
-      while ((pos < frstat.st_size) && isspace ((unsigned char) data[pos]))
-        pos++;
-      continue;
-    }
-    tsize = colon_pos - pos;
-    if ((pos >= frstat.st_size) || (pos + tsize >= frstat.st_size) ||
-        (tsize == 0))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Syntax error in blacklist file at offset %llu, giving 
up!\n"),
-                  (unsigned long long) colon_pos);
-      GNUNET_free (fn);
-      GNUNET_free (data);
-      return;
-    }
-
-    if (tsize < 1)
-      continue;
-
-    transport_name = GNUNET_malloc (tsize + 1);
-    memcpy (transport_name, &data[pos], tsize);
-    pos = colon_pos + 1;
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Read transport name %s in blacklist file.\n", transport_name);
-#endif
-    memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
-    if (!isspace
-        ((unsigned char)
-         enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Syntax error in blacklist file at offset %llu, skipping 
bytes.\n"),
-                  (unsigned long long) pos);
-      pos++;
-      while ((pos < frstat.st_size) && (!isspace ((unsigned char) data[pos])))
-        pos++;
-      GNUNET_free_non_null (transport_name);
-      continue;
-    }
-    enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Syntax error in blacklist file at offset %llu, skipping 
bytes `%s'.\n"),
-                  (unsigned long long) pos, &enc);
-    }
-    else
-    {
-      if (0 != memcmp (&pid, &my_identity, sizeof (struct 
GNUNET_PeerIdentity)))
-      {
-        entries_found++;
-        add_peer_to_blacklist (&pid, transport_name);
-      }
-      else
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    _("Found myself `%s' in blacklist (useless, ignored)\n"),
-                    GNUNET_i2s (&pid));
-      }
-    }
-    pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
-    GNUNET_free_non_null (transport_name);
-    while ((pos < frstat.st_size) && isspace ((unsigned char) data[pos]))
-      pos++;
-  }
-  GNUNET_STATISTICS_update (stats, "# Transport entries blacklisted",
-                            entries_found, GNUNET_NO);
-  GNUNET_free (data);
-  GNUNET_free (fn);
-}
-
-
-/**
- * Function called to notify a client about the socket being ready to
- * queue more data.  "buf" will be NULL and "size" zero if the socket
- * was closed for writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_to_client_callback (void *cls, size_t size, void *buf)
-{
-  struct TransportClient *client = cls;
-  struct ClientMessageQueueEntry *q;
-  uint16_t msize;
-  size_t tsize;
-  const struct GNUNET_MessageHeader *msg;
-  char *cbuf;
-
-  client->th = NULL;
-  if (buf == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Transmission to client failed, closing connection.\n");
-#endif
-    /* fatal error with client, free message queue! */
-    while (NULL != (q = client->message_queue_head))
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# bytes discarded (could not transmit to 
client)"),
-                                ntohs (((const struct GNUNET_MessageHeader *)
-                                        &q[1])->size), GNUNET_NO);
-      GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
-                                   client->message_queue_tail, q);
-      GNUNET_free (q);
-    }
-    client->message_count = 0;
-    return 0;
-  }
-  cbuf = buf;
-  tsize = 0;
-  while (NULL != (q = client->message_queue_head))
-  {
-    msg = (const struct GNUNET_MessageHeader *) &q[1];
-    msize = ntohs (msg->size);
-    if (msize + tsize > size)
-      break;
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Transmitting message of type %u to client.\n",
-                ntohs (msg->type));
-#endif
-    GNUNET_CONTAINER_DLL_remove (client->message_queue_head,
-                                 client->message_queue_tail, q);
-    memcpy (&cbuf[tsize], msg, msize);
-    tsize += msize;
-    GNUNET_free (q);
-    client->message_count--;
-  }
-  if (NULL != q)
-  {
-    GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
-    client->th =
-        GNUNET_SERVER_notify_transmit_ready (client->client, msize,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &transmit_to_client_callback,
-                                             client);
-    GNUNET_assert (client->th != NULL);
-  }
-  return tsize;
-}
-
-
-/**
- * Convert an address to a string.
- *
- * @param plugin name of the plugin responsible for the address
- * @param addr binary address
- * @param addr_len number of bytes in addr
- * @return NULL on error, otherwise address string
- */
-static const char *
-a2s (const char *plugin, const void *addr, uint16_t addr_len)
-{
-  struct TransportPlugin *p;
-
-  if (plugin == NULL)
-    return NULL;
-  p = find_transport (plugin);
-  if ((p == NULL) || (addr_len == 0) || (addr == NULL))
-    return NULL;
-  return p->api->address_to_string (NULL, addr, addr_len);
-}
-
-
-
-
-/**
- * Iterator to free entries in the validation_map.
- *
- * @param cls closure (unused)
- * @param key current key code
- * @param value value in the hash map (validation to abort)
- * @return GNUNET_YES (always)
- */
-static int
-abort_validation (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct ValidationEntry *va = value;
-
-  if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
-    GNUNET_SCHEDULER_cancel (va->timeout_task);
-  GNUNET_free (va->transport_name);
-  if (va->chvc != NULL)
-  {
-    va->chvc->ve_count--;
-    if (va->chvc->ve_count == 0)
-    {
-      GNUNET_CONTAINER_DLL_remove (chvc_head, chvc_tail, va->chvc);
-      GNUNET_free (va->chvc);
-    }
-    va->chvc = NULL;
-  }
-  GNUNET_free (va);
-  return GNUNET_YES;
-}
-
-
-/**
- * HELLO validation cleanup task (validation failed).
- *
- * @param cls the 'struct ValidationEntry' that failed
- * @param tc scheduler context (unused)
- */
-static void
-timeout_hello_validation (void *cls,
-                          const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ValidationEntry *va = cls;
-  struct GNUNET_PeerIdentity pid;
-
-  va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# address validation timeouts"), 1,
-                            GNUNET_NO);
-  GNUNET_CRYPTO_hash (&va->publicKey,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &pid.hashPubKey);
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONTAINER_multihashmap_remove (validation_map,
-                                                      &pid.hashPubKey, va));
-  abort_validation (NULL, NULL, va);
-}
-
-
-
-/**
- * Send the specified message to the specified client.  Since multiple
- * messages may be pending for the same client at a time, this code
- * makes sure that no message is lost.
- *
- * @param client client to transmit the message to
- * @param msg the message to send
- * @param may_drop can this message be dropped if the
- *        message queue for this client is getting far too large?
- */
-static void
-transmit_to_client (struct TransportClient *client,
-                    const struct GNUNET_MessageHeader *msg, int may_drop)
-{
-  struct ClientMessageQueueEntry *q;
-  uint16_t msize;
-
-  /* Client==NULL when GNUNET_SERVER_Client disconnected and was
-   * freed in client_disconnect_notification
-   */
-  if (client->client == NULL)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if ((client->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _
-                ("Dropping message of type %u and size %u, have %u messages 
pending (%u is the soft limit)\n"),
-                ntohs (msg->type), ntohs (msg->size), client->message_count,
-                MAX_PENDING);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# messages dropped due to slow client"), 1,
-                              GNUNET_NO);
-    return;
-  }
-  msize = ntohs (msg->size);
-  GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
-  q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
-  memcpy (&q[1], msg, msize);
-  GNUNET_CONTAINER_DLL_insert_tail (client->message_queue_head,
-                                    client->message_queue_tail, q);
-  client->message_count++;
-  if (client->th == NULL)
-  {
-    client->th =
-        GNUNET_SERVER_notify_transmit_ready (client->client, msize,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &transmit_to_client_callback,
-                                             client);
-    GNUNET_assert (client->th != NULL);
-  }
-}
-
-
-/**
- * Transmit a 'SEND_OK' notification to the given client for the
- * given neighbour.
- *
- * @param client who to notify
- * @param n neighbour to notify about, can be NULL (on failure)
- * @param target target of the transmission
- * @param result status code for the transmission request
- */
-static void
-transmit_send_ok (struct TransportClient *client, struct NeighbourMapEntry *n,
-                  const struct GNUNET_PeerIdentity *target, int result)
-{
-  struct SendOkMessage send_ok_msg;
-
-  send_ok_msg.header.size = htons (sizeof (send_ok_msg));
-  send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
-  send_ok_msg.success = htonl (result);
-  if (n != NULL)
-    send_ok_msg.latency = GNUNET_TIME_relative_hton (n->latency);
-  else
-    send_ok_msg.latency =
-        GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL);
-  send_ok_msg.peer = *target;
-  transmit_to_client (client, &send_ok_msg.header, GNUNET_NO);
-}
-
-
-/**
- * Mark the given FAL entry as 'connected' (and hence preferred for
- * sending); also mark all others for the same peer as 'not connected'
- * (since only one can be preferred).
- *
- * @param fal address to set to 'connected'
- */
-static void
-mark_address_connected (struct ForeignAddressList *fal);
-
-
-
-/**
- * We should re-try transmitting to the given peer,
- * hopefully we've learned something in the meantime.
- */
-static void
-retry_transmission_task (void *cls,
-                         const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct NeighbourMapEntry *n = cls;
-
-  n->retry_task = GNUNET_SCHEDULER_NO_TASK;
-  try_transmission_to_peer (n);
-}
-
-
-/**
- * Function called by the GNUNET_TRANSPORT_TransmitFunction
- * upon "completion" of a send request.  This tells the API
- * that it is now legal to send another message to the given
- * peer.
- *
- * @param cls closure, identifies the entry on the
- *            message queue that was transmitted and the
- *            client responsible for queuing the message
- * @param target the peer receiving the message
- * @param result GNUNET_OK on success, if the transmission
- *           failed, we should not tell the client to transmit
- *           more messages
- */
-static void
-transmit_send_continuation (void *cls, const struct GNUNET_PeerIdentity 
*target,
-                            int result)
-{
-  struct MessageQueue *mq = cls;
-  struct NeighbourMapEntry *n;
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# bytes pending with plugins"),
-                            -(int64_t) mq->message_buf_size, GNUNET_NO);
-  if (result == GNUNET_OK)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# bytes successfully transmitted by plugins"),
-                              mq->message_buf_size, GNUNET_NO);
-  }
-  else
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# bytes with transmission failure by plugins"),
-                              mq->message_buf_size, GNUNET_NO);
-  }
-  if (mq->specific_address != NULL)
-  {
-    if (result == GNUNET_OK)
-    {
-      mq->specific_address->timeout =
-          GNUNET_TIME_relative_to_absolute
-          (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-      if (mq->specific_address->validated == GNUNET_YES)
-        mark_address_connected (mq->specific_address);
-    }
-    else
-    {
-      if (mq->specific_address->connected == GNUNET_YES)
-      {
-#if DEBUG_TRANSPORT
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Marking address `%s' as no longer connected (due to 
transmission problem)\n",
-                    a2s (mq->specific_address->ready_list->plugin->short_name,
-                         mq->specific_address->addr,
-                         mq->specific_address->addrlen));
-#endif
-        GNUNET_STATISTICS_update (stats, gettext_noop ("# connected 
addresses"),
-                                  -1, GNUNET_NO);
-        mq->specific_address->connected = GNUNET_NO;
-      }
-    }
-    if (!mq->internal_msg)
-      mq->specific_address->in_transmit = GNUNET_NO;
-  }
-  n = find_neighbour (&mq->neighbour_id);
-  if (n != NULL)
-  {
-    if (mq->client != NULL)
-      transmit_send_ok (mq->client, n, target, result);
-    GNUNET_CONTAINER_DLL_remove (n->cont_head, n->cont_tail, mq);
-    if (result == GNUNET_OK)
-      try_transmission_to_peer (n);
-    else if (GNUNET_SCHEDULER_NO_TASK == n->retry_task)
-      n->retry_task = GNUNET_SCHEDULER_add_now (&retry_transmission_task, n);
-  }
-  else
-    GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "transmit_send_continuation",
-                     "Neighbour `%s' no longer exists\n",
-                     GNUNET_i2s (&mq->neighbour_id));
-  GNUNET_free (mq);
-}
-
-
-/**
- * Check the ready list for the given neighbour and if a plugin is
- * ready for transmission (and if we have a message), do so!
- *
- * @param neighbour target peer for which to transmit
- */
-static void
-try_transmission_to_peer (struct NeighbourMapEntry *n)
-{
-  struct ReadyList *rl;
-  struct MessageQueue *mq;
-  struct GNUNET_TIME_Relative timeout;
-  ssize_t ret;
-  int force_address;
-
-  if (n->messages_head == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Transmission queue for `%4s' is empty\n", GNUNET_i2s 
(&n->id));
-#endif
-    return;                     /* nothing to do */
-  }
-  rl = NULL;
-  mq = n->messages_head;
-  force_address = GNUNET_YES;
-  if (mq->specific_address == NULL)
-  {
-    /* TODO: ADD ATS */
-    mq->specific_address = get_preferred_ats_address (n);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# transport selected peer address freely"), 1,
-                              GNUNET_NO);
-    force_address = GNUNET_NO;
-  }
-  if (mq->specific_address == NULL)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# transport failed to selected peer address"),
-                              1, GNUNET_NO);
-    timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
-    if (timeout.rel_value == 0)
-    {
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "No destination address available to transmit message of 
size %u to peer `%4s'\n",
-                  mq->message_buf_size, GNUNET_i2s (&mq->neighbour_id));
-#endif
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# bytes in message queue for other peers"),
-                                -(int64_t) mq->message_buf_size, GNUNET_NO);
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# bytes discarded (no destination address 
available)"),
-                                mq->message_buf_size, GNUNET_NO);
-      if (mq->client != NULL)
-        transmit_send_ok (mq->client, n, &n->id, GNUNET_NO);
-      GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
-      GNUNET_free (mq);
-      return;                   /* nobody ready */
-    }
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# message delivery deferred (no address)"), 1,
-                              GNUNET_NO);
-    if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
-      GNUNET_SCHEDULER_cancel (n->retry_task);
-    n->retry_task =
-        GNUNET_SCHEDULER_add_delayed (timeout, &retry_transmission_task, n);
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No validated destination address available to transmit 
message of size %u to peer `%4s', will wait %llums to find an address.\n",
-                mq->message_buf_size, GNUNET_i2s (&mq->neighbour_id),
-                timeout.rel_value);
-#endif
-    /* FIXME: might want to trigger peerinfo lookup here
-     * (unless that's already pending...) */
-    return;
-  }
-  GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
-  if (mq->specific_address->connected == GNUNET_NO)
-    mq->specific_address->connect_attempts++;
-  rl = mq->specific_address->ready_list;
-  mq->plugin = rl->plugin;
-  if (!mq->internal_msg)
-    mq->specific_address->in_transmit = GNUNET_YES;
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
-              mq->message_buf_size, GNUNET_i2s (&n->id),
-              (mq->specific_address->addr !=
-               NULL) ? a2s (mq->plugin->short_name, mq->specific_address->addr,
-                            mq->specific_address->addrlen) : "<inbound>",
-              rl->plugin->short_name);
-#endif
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# bytes in message queue for other peers"),
-                            -(int64_t) mq->message_buf_size, GNUNET_NO);
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# bytes pending with plugins"),
-                            mq->message_buf_size, GNUNET_NO);
-
-  GNUNET_CONTAINER_DLL_insert (n->cont_head, n->cont_tail, mq);
-
-  ret =
-      rl->plugin->api->send (rl->plugin->api->cls, &mq->neighbour_id,
-                             mq->message_buf, mq->message_buf_size,
-                             mq->priority,
-                             GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
-                             mq->specific_address->session,
-                             mq->specific_address->addr,
-                             mq->specific_address->addrlen, force_address,
-                             &transmit_send_continuation, mq);
-  if (ret == -1)
-  {
-    /* failure, but 'send' would not call continuation in this case,
-     * so we need to do it here! */
-    transmit_send_continuation (mq, &mq->neighbour_id, GNUNET_SYSERR);
-  }
-}
-
-
-/**
- * Send the specified message to the specified peer.
- *
- * @param client source of the transmission request (can be NULL)
- * @param peer_address ForeignAddressList where we should send this message
- * @param priority how important is the message
- * @param timeout how long do we have to transmit?
- * @param message_buf message(s) to send GNUNET_MessageHeader(s)
- * @param message_buf_size total size of all messages in message_buf
- * @param is_internal is this an internal message; these are pre-pended and
- *                    also do not count for plugins being "ready" to transmit
- * @param neighbour handle to the neighbour for transmission
- */
-static void
-transmit_to_peer (struct TransportClient *client,
-                  struct ForeignAddressList *peer_address,
-                  unsigned int priority, struct GNUNET_TIME_Relative timeout,
-                  const char *message_buf, size_t message_buf_size,
-                  int is_internal, struct NeighbourMapEntry *neighbour)
-{
-  struct MessageQueue *mq;
-
-#if EXTRA_CHECKS
-  if (client != NULL)
-  {
-    /* check for duplicate submission */
-    mq = neighbour->messages_head;
-    while (NULL != mq)
-    {
-      if (mq->client == client)
-      {
-        /* client transmitted to same peer twice
-         * before getting SEND_OK! */
-        GNUNET_break (0);
-        return;
-      }
-      mq = mq->next;
-    }
-  }
-#endif
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# bytes in message queue for other peers"),
-                            message_buf_size, GNUNET_NO);
-  mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
-  mq->specific_address = peer_address;
-  mq->client = client;
-  /* FIXME: this memcpy can be up to 7% of our total runtime! */
-  memcpy (&mq[1], message_buf, message_buf_size);
-  mq->message_buf = (const char *) &mq[1];
-  mq->message_buf_size = message_buf_size;
-  memcpy (&mq->neighbour_id, &neighbour->id,
-          sizeof (struct GNUNET_PeerIdentity));
-  mq->internal_msg = is_internal;
-  mq->priority = priority;
-  mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  if (is_internal)
-    GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
-                                 neighbour->messages_tail, mq);
-  else
-    GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
-                                       neighbour->messages_tail,
-                                       neighbour->messages_tail, mq);
-  try_transmission_to_peer (neighbour);
-}
-
-
-/**
- * Send a plain PING (without address or our HELLO) to the given
- * foreign address to try to establish a connection (and validate
- * that the other peer is really who he claimed he is).
- *
- * @param n neighbour to PING
- */
-static void
-transmit_plain_ping (struct NeighbourMapEntry *n)
-{
-  struct ValidationEntry *ve;
-  struct TransportPingMessage ping;
-  struct ReadyList *rl;
-  struct TransportPlugin *plugin;
-  struct ForeignAddressList *fal;
-
-  if (!n->public_key_valid)
-  {
-    /* This should not happen since the other peer
-     * should send us a HELLO prior to sending his
-     * PING */
-    GNUNET_break_op (0);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Could not transmit plain PING to `%s': public key not 
known\n",
-                GNUNET_i2s (&n->id));
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Looking for addresses to transmit plain PING to `%s'\n",
-              GNUNET_i2s (&n->id));
-  for (rl = n->plugins; rl != NULL; rl = rl->next)
-  {
-    plugin = rl->plugin;
-    for (fal = rl->addresses; fal != NULL; fal = fal->next)
-    {
-      if (!fal->connected)
-        continue;
-      ve = GNUNET_malloc (sizeof (struct ValidationEntry));
-      ve->transport_name = GNUNET_strdup (plugin->short_name);
-      ve->challenge =
-          GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT_MAX);
-      ve->send_time = GNUNET_TIME_absolute_get ();
-      ve->session = fal->session;
-      memcpy (&ve->publicKey, &n->publicKey,
-              sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
-      ve->timeout_task =
-          GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
-                                        &timeout_hello_validation, ve);
-      GNUNET_CONTAINER_multihashmap_put (validation_map, &n->id.hashPubKey, ve,
-                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-      ping.header.size = htons (sizeof (struct TransportPingMessage));
-      ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
-      ping.challenge = htonl (ve->challenge);
-      memcpy (&ping.target, &n->id, sizeof (struct GNUNET_PeerIdentity));
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# PING without HELLO messages sent"), 1,
-                                GNUNET_NO);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting plain PING to `%s'\n",
-                  GNUNET_i2s (&n->id));
-      transmit_to_peer (NULL, fal, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                        HELLO_VERIFICATION_TIMEOUT, (const char *) &ping,
-                        sizeof (ping), GNUNET_YES, n);
-    }
-  }
-}
-
-
-/**
- * Mark the given FAL entry as 'connected' (and hence preferred for
- * sending); also mark all others for the same peer as 'not connected'
- * (since only one can be preferred).
- *
- * @param fal address to set to 'connected'
- */
-static void
-mark_address_connected (struct ForeignAddressList *fal)
-{
-  struct ForeignAddressList *pos;
-  struct ForeignAddressList *inbound;
-  struct ForeignAddressList *outbound;
-
-  GNUNET_assert (GNUNET_YES == fal->validated);
-  if (fal->connected == GNUNET_YES)
-    return;                     /* nothing to do */
-  inbound = NULL;
-  outbound = NULL;
-
-  pos = fal->ready_list->addresses;
-  while (pos != NULL)
-  {
-    /* Already have inbound address, and this is also an inbound address, 
don't switch!! */
-    if ((GNUNET_YES == pos->connected) && (0 == pos->addrlen) &&
-        (0 == fal->addrlen))
-      return;
-    if ((0 == pos->addrlen) && (GNUNET_YES == pos->connected))
-      inbound = pos;
-    pos = pos->next;
-  }
-
-  pos = fal->ready_list->addresses;
-  while (pos != NULL)
-  {
-    /* Already have outbound address, and this is also an outbound address, 
don't switch!! */
-    if ((GNUNET_YES == pos->connected) && (0 < pos->addrlen) &&
-        (0 < fal->addrlen))
-      return;
-    if ((0 < pos->addrlen) && (GNUNET_YES == pos->connected))
-      outbound = pos;
-    pos = pos->next;
-  }
-
-#if DEBUG_INBOUND
-  if (inbound != NULL)
-    fprintf (stderr, "Peer: %s, have inbound connection.\n",
-             GNUNET_i2s (&my_identity));
-  if (outbound != NULL)
-    fprintf (stderr, "Peer: %s, have outbound connection.\n",
-             GNUNET_i2s (&my_identity));
-#endif
-
-  /* Have an inbound connection to this peer which is valid; our id is lower, 
ignore outbound connection! */
-  if ((inbound != NULL) && (0 != fal->addrlen) &&
-      (1 ==
-       GNUNET_CRYPTO_hash_xorcmp (&inbound->ready_list->neighbour->id.
-                                  hashPubKey, &my_identity.hashPubKey,
-                                  &null_hash)))
-  {
-#if DEBUG_INBOUND
-    fprintf (stderr, "Peer: %s, had inbound connection, ignoring outbound!\n",
-             GNUNET_i2s (&my_identity));
-#endif
-    return;
-  }
-  else if ((outbound != NULL) && (0 == fal->addrlen) &&
-           ((-1 ==
-             GNUNET_CRYPTO_hash_xorcmp (&outbound->ready_list->neighbour->
-                                        id.hashPubKey, &my_identity.hashPubKey,
-                                        &null_hash))))
-  {
-#if DEBUG_INBOUND
-    fprintf (stderr, "Peer: %s, have outbound connection, ignoring inbound!\n",
-             GNUNET_i2s (&my_identity));
-#endif
-    return;
-  }
-
-  pos = fal->ready_list->addresses;
-  while (pos != NULL)
-  {
-    if ((GNUNET_YES == pos->connected) && (0 < pos->addrlen))
-    {
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Marking address `%s' as no longer connected (due to connect 
on other address)\n",
-                  a2s (pos->ready_list->plugin->short_name, pos->addr,
-                       pos->addrlen));
-#endif
-#if DEBUG_INBOUND
-      fprintf (stderr, "Peer: %s, setting %s connection to disconnected.\n",
-               GNUNET_i2s (&my_identity),
-               (0 == pos->addrlen) ? "INBOUND" : "OUTBOUND");
-#endif
-      pos->connected = GNUNET_NO;
-      GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"),
-                                -1, GNUNET_NO);
-    }
-    pos = pos->next;
-  }
-  GNUNET_assert (GNUNET_NO == fal->connected);
-  fal->connected = GNUNET_YES;
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"), 1,
-                            GNUNET_NO);
-}
-
-
-/**
- * Find an address in any of the available transports for
- * the given neighbour that would be good for message
- * transmission.  This is essentially the transport selection
- * routine.
- *
- * @param neighbour for whom to select an address
- * @return selected address, NULL if we have none
- */
-struct ForeignAddressList *
-find_ready_address (struct NeighbourMapEntry *neighbour)
-{
-  struct ReadyList *head = neighbour->plugins;
-  struct ForeignAddressList *addresses;
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  struct ForeignAddressList *best_address;
-
-  /* Hack to prefer unix domain sockets */
-  struct ForeignAddressList *unix_address = NULL;
-
-  best_address = NULL;
-  while (head != NULL)
-  {
-    addresses = head->addresses;
-    while (addresses != NULL)
-    {
-      if ((addresses->timeout.abs_value < now.abs_value) &&
-          (addresses->connected == GNUNET_YES))
-      {
-#if DEBUG_TRANSPORT
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Marking long-time inactive connection to `%4s' as 
down.\n",
-                    GNUNET_i2s (&neighbour->id));
-#endif
-        GNUNET_STATISTICS_update (stats, gettext_noop ("# connected 
addresses"),
-                                  -1, GNUNET_NO);
-        addresses->connected = GNUNET_NO;
-      }
-      addresses = addresses->next;
-    }
-
-    addresses = head->addresses;
-    while (addresses != NULL)
-    {
-#if DEBUG_TRANSPORT
-      if (addresses->addr != NULL)
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, 
%llums, %u)\n",
-                    a2s (head->plugin->short_name, addresses->addr,
-                         addresses->addrlen), GNUNET_i2s (&neighbour->id),
-                    addresses->connected, addresses->in_transmit,
-                    addresses->validated, addresses->connect_attempts,
-                    (unsigned long long) addresses->timeout.abs_value,
-                    (unsigned int) addresses->distance);
-#endif
-      if (0 == strcmp (head->plugin->short_name, "unix"))
-      {
-        if ((unix_address == NULL) ||
-            ((unix_address != NULL) &&
-             (addresses->latency.rel_value < unix_address->latency.rel_value)))
-          unix_address = addresses;
-      }
-      if (((best_address == NULL) || (addresses->connected == GNUNET_YES) ||
-           (best_address->connected == GNUNET_NO)) &&
-          (addresses->in_transmit == GNUNET_NO) && ((best_address == NULL) ||
-                                                    (addresses->
-                                                     latency.rel_value <
-                                                     best_address->
-                                                     latency.rel_value)))
-        best_address = addresses;
-      /* FIXME: also give lower-latency addresses that are not
-       * connected a chance some times... */
-      addresses = addresses->next;
-    }
-    if (unix_address != NULL)
-      break;
-    head = head->next;
-  }
-  if (unix_address != NULL)
-  {
-    best_address = unix_address;
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Found UNIX address, forced this address\n");
-#endif
-  }
-  if (best_address != NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Best address found (`%s') has latency of %llu ms.\n",
-                (best_address->addrlen >
-                 0) ? a2s (best_address->ready_list->plugin->short_name,
-                           best_address->addr,
-                           best_address->addrlen) : "<inbound>",
-                best_address->latency.rel_value);
-#endif
-  }
-  else
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# transmission attempts failed (no address)"),
-                              1, GNUNET_NO);
-  }
-
-  return best_address;
-}
-
-
-/**
- * FIXME: document.
- */
-struct GeneratorContext
-{
-  struct TransportPlugin *plug_pos;
-  struct OwnAddressList *addr_pos;
-  struct GNUNET_TIME_Absolute expiration;
-};
-
-
-/**
- * FIXME: document.
- */
-static size_t
-address_generator (void *cls, size_t max, void *buf)
-{
-  struct GeneratorContext *gc = cls;
-  size_t ret;
-
-  while ((gc->addr_pos == NULL) && (gc->plug_pos != NULL))
-  {
-    gc->plug_pos = gc->plug_pos->next;
-    gc->addr_pos = (gc->plug_pos != NULL) ? gc->plug_pos->addresses : NULL;
-  }
-  if (NULL == gc->plug_pos)
-  {
-
-    return 0;
-  }
-  ret =
-      GNUNET_HELLO_add_address (gc->plug_pos->short_name, gc->expiration,
-                                &gc->addr_pos[1], gc->addr_pos->addrlen, buf,
-                                max);
-  gc->addr_pos = gc->addr_pos->next;
-  return ret;
-}
-
-
-
-static int
-transmit_our_hello_if_pong (void *cls, const GNUNET_HashCode * key, void 
*value)
-{
-  struct NeighbourMapEntry *npos = value;
-
-  if (GNUNET_YES != npos->received_pong)
-    return GNUNET_OK;
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-              "Transmitting updated `%s' to neighbour `%4s'\n", "HELLO",
-              GNUNET_i2s (&npos->id));
-#endif
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# transmitted my HELLO to other peers"), 1,
-                            GNUNET_NO);
-  transmit_to_peer (NULL, NULL, 0, HELLO_ADDRESS_EXPIRATION,
-                    (const char *) our_hello, GNUNET_HELLO_size (our_hello),
-                    GNUNET_NO, npos);
-  return GNUNET_OK;
-}
-
-
-/**
- * Construct our HELLO message from all of the addresses of
- * all of the transports.
- *
- * @param cls unused
- * @param tc scheduler context
- */
-static void
-refresh_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_HELLO_Message *hello;
-  struct TransportClient *cpos;
-  struct GeneratorContext gc;
-
-  hello_task = GNUNET_SCHEDULER_NO_TASK;
-  gc.plug_pos = plugins;
-  gc.addr_pos = plugins != NULL ? plugins->addresses : NULL;
-  gc.expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
-  hello = GNUNET_HELLO_create (&my_public_key, &address_generator, &gc);
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-              "Refreshed my `%s', new size is %d\n", "HELLO",
-              GNUNET_HELLO_size (hello));
-#endif
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# refreshed my HELLO"), 1,
-                            GNUNET_NO);
-  cpos = clients;
-  while (cpos != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting my HELLO to client!\n");
-    transmit_to_client (cpos, (const struct GNUNET_MessageHeader *) hello,
-                        GNUNET_NO);
-    cpos = cpos->next;
-  }
-
-  GNUNET_free_non_null (our_hello);
-  our_hello = hello;
-  GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours,
-                                         &transmit_our_hello_if_pong, NULL);
-}
-
-
-/**
- * Schedule task to refresh hello (unless such a
- * task exists already).
- */
-static void
-refresh_hello ()
-{
-#if DEBUG_TRANSPORT_HELLO
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "refresh_hello() called!\n");
-#endif
-  if (hello_task != GNUNET_SCHEDULER_NO_TASK)
-    return;
-  hello_task = GNUNET_SCHEDULER_add_now (&refresh_hello_task, NULL);
-}
-
-
-/**
- * Iterator over hash map entries that NULLs the session of validation
- * entries that match the given session.
- *
- * @param cls closure (the 'struct Session*' to match against)
- * @param key current key code (peer ID, not used)
- * @param value value in the hash map ('struct ValidationEntry*')
- * @return GNUNET_YES (we should continue to iterate)
- */
-static int
-remove_session_validations (void *cls, const GNUNET_HashCode * key, void 
*value)
-{
-  struct Session *session = cls;
-  struct ValidationEntry *ve = value;
-
-  if (session == ve->session)
-    ve->session = NULL;
-  return GNUNET_YES;
-}
-
-
-/**
- * We've been disconnected from the other peer (for some
- * connection-oriented transport).  Either quickly
- * re-establish the connection or signal the disconnect
- * to the CORE.
- *
- * Only signal CORE level disconnect if ALL addresses
- * for the peer are exhausted.
- *
- * @param p overall plugin context
- * @param nl neighbour that was disconnected
- */
-static void
-try_fast_reconnect (struct TransportPlugin *p, struct NeighbourMapEntry *nl)
-{
-  /* FIXME-MW: fast reconnect / transport switching not implemented... */
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "try_fast_reconnect not implemented!\n");
-  /* Note: the idea here is to hide problems with transports (or
-   * switching between plugins) from the core to eliminate the need to
-   * re-negotiate session keys and the like; OTOH, we should tell core
-   * quickly (much faster than timeout) `if a connection was lost and
-   * could not be re-established (i.e. other peer went down or is
-   * unable / refuses to communicate);
-   *
-   * So we should consider:
-   * 1) ideally: our own willingness / need to connect
-   * 2) prior failures to connect to this peer (by plugin)
-   * 3) ideally: reasons why other peer terminated (as far as knowable)
-   *
-   * Most importantly, it must be POSSIBLE for another peer to terminate
-   * a connection for a while (without us instantly re-establishing it).
-   * Similarly, if another peer is gone we should quickly notify CORE.
-   * OTOH, if there was a minor glitch (i.e. crash of gnunet-service-transport
-   * on the other end), we should reconnect in such a way that BOTH CORE
-   * services never even notice.
-   * Furthermore, the same mechanism (or small variation) could be used
-   * to switch to a better-performing plugin (ATS).
-   *
-   * Finally, this needs to be tested throughly... */
-
-  /*
-   * GNUNET_NO in the call below makes transport disconnect the peer,
-   * even if only a single address (out of say, six) went away.  This
-   * function must be careful to ONLY disconnect if the peer is gone,
-   * not just a specific address.
-   *
-   * More specifically, half the places it was used had it WRONG.
-   */
-
-  /* No reconnect, signal disconnect instead! */
-#if DEBUG_TRANSPORT
-#endif
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
-              GNUNET_i2s (&nl->id), "try_fast_reconnect");
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# disconnects due to try_fast_reconnect"), 1,
-                            GNUNET_NO);
-#if DISCONNECT || 1
-  disconnect_neighbour (nl, GNUNET_YES);
-#endif
-}
-
-
-/**
- * Function that will be called whenever the plugin internally
- * cleans up a session pointer and hence the service needs to
- * discard all of those sessions as well.  Plugins that do not
- * use sessions can simply omit calling this function and always
- * use NULL wherever a session pointer is needed.
- *
- * @param cls closure
- * @param peer which peer was the session for
- * @param session which session is being destoyed
- */
-static void
-plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
-                        struct Session *session)
-{
-  struct TransportPlugin *p = cls;
-  struct NeighbourMapEntry *nl;
-  struct ReadyList *rl;
-  struct ForeignAddressList *pos;
-  struct ForeignAddressList *prev;
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session ended with peer `%4s', %s\n",
-              GNUNET_i2s (peer), "plugin_env_session_end");
-#endif
-  GNUNET_CONTAINER_multihashmap_iterate (validation_map,
-                                         &remove_session_validations, session);
-  nl = find_neighbour (peer);
-  if (nl == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No neighbour record found for peer `%4s'\n",
-                GNUNET_i2s (peer));
-#endif
-    return;                     /* was never marked as connected */
-  }
-  rl = nl->plugins;
-  while (rl != NULL)
-  {
-    if (rl->plugin == p)
-      break;
-    rl = rl->next;
-  }
-  if (rl == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Plugin was associated with peer `%4s'\n", GNUNET_i2s (peer));
-#endif
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# disconnects due to session 
end"),
-                              1, GNUNET_NO);
-    disconnect_neighbour (nl, GNUNET_YES);
-    return;
-  }
-  prev = NULL;
-  pos = rl->addresses;
-  while ((pos != NULL) && (pos->session != session))
-  {
-    prev = pos;
-    pos = pos->next;
-  }
-  if (pos == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Session was never marked as ready for peer `%4s'\n",
-                GNUNET_i2s (peer));
-#endif
-
-    int validations_pending =
-        GNUNET_CONTAINER_multihashmap_contains (validation_map,
-                                                &peer->hashPubKey);
-
-    /* No session was marked as ready, but we have pending validations so do 
not disconnect from neighbour */
-    if (validations_pending == GNUNET_YES)
-    {
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Not disconnecting from peer `%4s due to pending address 
validations\n",
-                  GNUNET_i2s (peer));
-#endif
-      return;
-    }
-
-    //FIXME: This conflicts with inbound tcp connections and tcp nat ... 
debugging in progress
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# disconnects due to unready session"), 1,
-                              GNUNET_NO);
-
-    disconnect_neighbour (nl, GNUNET_YES);
-    return;                     /* was never marked as connected */
-  }
-  pos->session = NULL;
-  if (GNUNET_YES == pos->connected)
-  {
-    pos->connected = GNUNET_NO;
-    GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"), 
-1,
-                              GNUNET_NO);
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != pos->revalidate_task)
-  {
-    GNUNET_SCHEDULER_cancel (pos->revalidate_task);
-    pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-
-  if (pos->addrlen != 0)
-  {
-    if (nl->received_pong != GNUNET_NO)
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# try_fast_reconnect thanks to 
plugin_env_session_end"),
-                                1, GNUNET_NO);
-      if (GNUNET_YES == pos->connected)
-        try_fast_reconnect (p, nl);
-    }
-    else
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# disconnects due to missing pong"), 1,
-                                GNUNET_NO);
-      /* FIXME this is never true?! See: line 2416 */
-      if (GNUNET_YES == pos->connected)
-        disconnect_neighbour (nl, GNUNET_YES);
-    }
-    return;
-  }
-
-  /* was inbound connection, free 'pos' */
-  if (prev == NULL)
-    rl->addresses = pos->next;
-  else
-    prev->next = pos->next;
-  if (GNUNET_SCHEDULER_NO_TASK != pos->revalidate_task)
-  {
-    GNUNET_SCHEDULER_cancel (pos->revalidate_task);
-    pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_free_non_null (pos->ressources);
-  GNUNET_free_non_null (pos->quality);
-#if HAVE_LIBGLPK
-  ats_modify_problem_state (ats, ATS_MODIFIED);
-#endif
-  if (GNUNET_YES != pos->connected)
-  {
-    /* nothing else to do, connection was never up... */
-    GNUNET_free (pos);
-    return;
-  }
-  pos->connected = GNUNET_NO;
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# connected addresses"), -1,
-                            GNUNET_NO);
-  GNUNET_free (pos);
-
-  if (nl->received_pong == GNUNET_NO)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# disconnects due to NO pong"), 1,
-                              GNUNET_NO);
-    disconnect_neighbour (nl, GNUNET_YES);
-    return;                     /* nothing to do, never connected... */
-  }
-  /* check if we have any validated addresses left */
-  pos = rl->addresses;
-  while (pos != NULL)
-  {
-    if (GNUNET_YES == pos->validated)
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# try_fast_reconnect thanks to 
validated_address"),
-                                1, GNUNET_NO);
-      try_fast_reconnect (p, nl);
-      return;
-    }
-    pos = pos->next;
-  }
-  /* no valid addresses left, signal disconnect! */
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
-              GNUNET_i2s (peer), "plugin_env_session_end");
-#endif
-  /* FIXME: This doesn't mean there are no addresses left for this PEER,
-   * it means there aren't any left for this PLUGIN/PEER combination! So
-   * calling disconnect_neighbour here with GNUNET_NO forces disconnect
-   * when it isn't necessary. Using GNUNET_YES at least checks to see
-   * if there are any addresses that work first, so as not to overdo it.
-   * --NE
-   */
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# disconnects due to plugin_env_session_end"), 1,
-                            GNUNET_NO);
-  disconnect_neighbour (nl, GNUNET_YES);
-}
-
-
-/**
- * Function that must be called by each plugin to notify the
- * transport service about the addresses under which the transport
- * provided by the plugin can be reached.
- *
- * @param cls closure
- * @param add_remove GNUNET_YES to add, GNUNET_NO to remove the address
- * @param addr one of the addresses of the host, NULL for the last address
- *        the specific address format depends on the transport
- * @param addrlen length of the address
- */
-static void
-plugin_env_notify_address (void *cls, int add_remove, const void *addr,
-                           size_t addrlen)
-{
-  struct TransportPlugin *p = cls;
-  struct OwnAddressList *al;
-  struct OwnAddressList *prev;
-
-  GNUNET_assert (p->api != NULL);
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              (add_remove ==
-               GNUNET_YES) ? "Adding `%s':%s to the set of our addresses\n" :
-              "Removing `%s':%s from the set of our addresses\n",
-              a2s (p->short_name, addr, addrlen), p->short_name);
-#endif
-  GNUNET_assert (addr != NULL);
-  if (GNUNET_NO == add_remove)
-  {
-    prev = NULL;
-    al = p->addresses;
-    while (al != NULL)
-    {
-      if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
-      {
-        if (prev == NULL)
-          p->addresses = al->next;
-        else
-          prev->next = al->next;
-        GNUNET_free (al);
-        refresh_hello ();
-        return;
-      }
-      prev = al;
-      al = al->next;
-    }
-    GNUNET_break (0);
-    return;
-  }
-  al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
-  al->next = p->addresses;
-  p->addresses = al;
-  al->addrlen = addrlen;
-  memcpy (&al[1], addr, addrlen);
-  refresh_hello ();
-}
-
-
-/**
- * Notify all of our clients about a peer connecting.
- */
-static void
-notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
-                        struct GNUNET_TIME_Relative latency, uint32_t distance)
-{
-  struct ConnectInfoMessage *cim;
-  struct TransportClient *cpos;
-  uint32_t ats_count;
-  size_t size;
-
-  if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_break (0);
-    return;
-  }
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Notifying clients about connection with `%s'\n",
-              GNUNET_i2s (peer));
-#endif
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# peers connected"), 1,
-                            GNUNET_NO);
-
-  ats_count = 2;
-  size =
-      sizeof (struct ConnectInfoMessage) +
-      ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
-  GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
-  cim = GNUNET_malloc (size);
-  cim->header.size = htons (size);
-  cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
-  cim->ats_count = htonl (2);
-  (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
-  (&cim->ats)[0].value = htonl (distance);
-  (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
-  (&cim->ats)[1].value = htonl ((uint32_t) latency.rel_value);
-  (&cim->ats)[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
-  (&cim->ats)[2].value = htonl (0);
-  memcpy (&cim->id, peer, sizeof (struct GNUNET_PeerIdentity));
-
-  /* notify ats about connecting peer */
-  if ((ats != NULL) && (shutdown_in_progress == GNUNET_NO))
-  {
-#if HAVE_LIBGLPK
-    ats_modify_problem_state (ats, ATS_MODIFIED);
-    ats_calculate_bandwidth_distribution (ats);
-#endif
-  }
-  cpos = clients;
-  while (cpos != NULL)
-  {
-    transmit_to_client (cpos, &cim->header, GNUNET_NO);
-    cpos = cpos->next;
-  }
-  GNUNET_free (cim);
-}
-
-
-/**
- * Notify all of our clients about a peer disconnecting.
- */
-static void
-notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
-{
-  struct DisconnectInfoMessage dim;
-  struct TransportClient *cpos;
-
-  if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_break (0);
-    return;
-  }
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Notifying clients about lost connection to `%s'\n",
-              GNUNET_i2s (peer));
-#endif
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# peers connected"), -1,
-                            GNUNET_NO);
-  dim.header.size = htons (sizeof (struct DisconnectInfoMessage));
-  dim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
-  dim.reserved = htonl (0);
-  memcpy (&dim.peer, peer, sizeof (struct GNUNET_PeerIdentity));
-
-  /* notify ats about connecting peer */
-  if ((ats != NULL) && (shutdown_in_progress == GNUNET_NO))
-  {
-#if HAVE_LIBGLPK
-    ats_modify_problem_state (ats, ATS_MODIFIED);
-    ats_calculate_bandwidth_distribution (ats);
-#endif
-  }
-
-  cpos = clients;
-  while (cpos != NULL)
-  {
-    transmit_to_client (cpos, &dim.header, GNUNET_NO);
-    cpos = cpos->next;
-  }
-}
-
-
-/**
- * Find a ForeignAddressList entry for the given neighbour
- * that matches the given address and transport.
- *
- * @param neighbour which peer we care about
- * @param tname name of the transport plugin
- * @param session session to look for, NULL for 'any'; otherwise
- *        can be used for the service to "learn" this session ID
- *        if 'addr' matches
- * @param addr binary address
- * @param addrlen length of addr
- * @return NULL if no such entry exists
- */
-static struct ForeignAddressList *
-find_peer_address (struct NeighbourMapEntry *neighbour, const char *tname,
-                   struct Session *session, const char *addr, uint16_t addrlen)
-{
-  struct ReadyList *head;
-  struct ForeignAddressList *pos;
-
-  head = neighbour->plugins;
-  while (head != NULL)
-  {
-    if (0 == strcmp (tname, head->plugin->short_name))
-      break;
-    head = head->next;
-  }
-  if (head == NULL)
-    return NULL;
-  pos = head->addresses;
-  while ((pos != NULL) &&
-         ((pos->addrlen != addrlen) ||
-          (memcmp (pos->addr, addr, addrlen) != 0)))
-  {
-    if ((session != NULL) && (pos->session == session))
-      return pos;
-    pos = pos->next;
-  }
-  if ((session != NULL) && (pos != NULL))
-    pos->session = session;     /* learn it! */
-  return pos;
-}
-
-
-/**
- * Get the peer address struct for the given neighbour and
- * address.  If it doesn't yet exist, create it.
- *
- * @param neighbour which peer we care about
- * @param tname name of the transport plugin
- * @param session session of the plugin, or NULL for none
- * @param addr binary address
- * @param addrlen length of addr
- * @return NULL if we do not have a transport plugin for 'tname'
- */
-static struct ForeignAddressList *
-add_peer_address (struct NeighbourMapEntry *neighbour, const char *tname,
-                  struct Session *session, const char *addr, uint16_t addrlen)
-{
-  struct ReadyList *head;
-  struct ForeignAddressList *ret;
-  int c;
-
-  ret = find_peer_address (neighbour, tname, session, addr, addrlen);
-  if (ret != NULL)
-    return ret;
-  head = neighbour->plugins;
-
-  while (head != NULL)
-  {
-    if (0 == strcmp (tname, head->plugin->short_name))
-      break;
-    head = head->next;
-  }
-  if (head == NULL)
-    return NULL;
-  ret = GNUNET_malloc (sizeof (struct ForeignAddressList) + addrlen);
-  ret->session = session;
-  if ((addrlen > 0) && (addr != NULL))
-  {
-    ret->addr = (const char *) &ret[1];
-    memcpy (&ret[1], addr, addrlen);
-  }
-  else
-  {
-    ret->addr = NULL;
-  }
-
-  ret->ressources =
-      GNUNET_malloc (available_ressources *
-                     sizeof (struct ATS_ressource_entry));
-  for (c = 0; c < available_ressources; c++)
-  {
-    struct ATS_ressource_entry *r = ret->ressources;
-
-    r[c].index = c;
-    r[c].atis_index = ressources[c].atis_index;
-    if (0 == strcmp (neighbour->plugins->plugin->short_name, "unix"))
-    {
-      r[c].c = ressources[c].c_unix;
-    }
-    else if (0 == strcmp (neighbour->plugins->plugin->short_name, "udp"))
-    {
-      r[c].c = ressources[c].c_udp;
-    }
-    else if (0 == strcmp (neighbour->plugins->plugin->short_name, "tcp"))
-    {
-      r[c].c = ressources[c].c_tcp;
-    }
-    else if (0 == strcmp (neighbour->plugins->plugin->short_name, "http"))
-    {
-      r[c].c = ressources[c].c_http;
-    }
-    else if (0 == strcmp (neighbour->plugins->plugin->short_name, "https"))
-    {
-      r[c].c = ressources[c].c_https;
-    }
-    else if (0 == strcmp (neighbour->plugins->plugin->short_name, "wlan"))
-    {
-      r[c].c = ressources[c].c_wlan;
-    }
-    else
-    {
-      r[c].c = ressources[c].c_default;
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Assigning default cost to peer `%s' addr plugin `%s'! This 
should not happen!\n",
-                  GNUNET_i2s (&neighbour->id),
-                  neighbour->plugins->plugin->short_name);
-    }
-  }
-
-  ret->quality =
-      GNUNET_malloc (available_quality_metrics *
-                     sizeof (struct ATS_quality_entry));
-  ret->addrlen = addrlen;
-  ret->expires =
-      GNUNET_TIME_relative_to_absolute
-      (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-  ret->latency = GNUNET_TIME_relative_get_forever ();
-  ret->distance = -1;
-  ret->timeout =
-      GNUNET_TIME_relative_to_absolute
-      (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-  ret->ready_list = head;
-  ret->next = head->addresses;
-  head->addresses = ret;
-  return ret;
-}
-
-
-/**
- * Closure for 'add_validated_address'.
- */
-struct AddValidatedAddressContext
-{
-  /**
-   * Entry that has been validated.
-   */
-  const struct ValidationEntry *ve;
-
-  /**
-   * Flag set after we have added the address so
-   * that we terminate the iteration next time.
-   */
-  int done;
-};
-
-
-/**
- * Callback function used to fill a buffer of max bytes with a list of
- * addresses in the format used by HELLOs.  Should use
- * "GNUNET_HELLO_add_address" as a helper function.
- *
- * @param cls the 'struct AddValidatedAddressContext' with the validated 
address
- * @param max maximum number of bytes that can be written to buf
- * @param buf where to write the address information
- * @return number of bytes written, 0 to signal the
- *         end of the iteration.
- */
-static size_t
-add_validated_address (void *cls, size_t max, void *buf)
-{
-  struct AddValidatedAddressContext *avac = cls;
-  const struct ValidationEntry *ve = avac->ve;
-
-  if (GNUNET_YES == avac->done)
-    return 0;
-  avac->done = GNUNET_YES;
-  return GNUNET_HELLO_add_address (ve->transport_name,
-                                   GNUNET_TIME_relative_to_absolute
-                                   (HELLO_ADDRESS_EXPIRATION), ve->addr,
-                                   ve->addrlen, buf, max);
-}
-
-
-
-/**
- * Closure for 'check_address_exists'.
- */
-struct CheckAddressExistsClosure
-{
-  /**
-   * Address to check for.
-   */
-  const void *addr;
-
-  /**
-   * Name of the transport.
-   */
-  const char *tname;
-
-  /**
-   * Session, or NULL.
-   */
-  struct Session *session;
-
-  /**
-   * Set to GNUNET_YES if the address exists.
-   */
-  int exists;
-
-  /**
-   * Length of addr.
-   */
-  uint16_t addrlen;
-
-};
-
-
-/**
- * Iterator over hash map entries.  Checks if the given
- * validation entry is for the same address as what is given
- * in the closure.
- *
- * @param cls the 'struct CheckAddressExistsClosure*'
- * @param key current key code (ignored)
- * @param value value in the hash map ('struct ValidationEntry')
- * @return GNUNET_YES if we should continue to
- *         iterate (mismatch), GNUNET_NO if not (entry matched)
- */
-static int
-check_address_exists (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct CheckAddressExistsClosure *caec = cls;
-  struct ValidationEntry *ve = value;
-
-  if ((0 == strcmp (caec->tname, ve->transport_name)) &&
-      (caec->addrlen == ve->addrlen) &&
-      (0 == memcmp (caec->addr, ve->addr, caec->addrlen)))
-  {
-    caec->exists = GNUNET_YES;
-    return GNUNET_NO;
-  }
-  if ((ve->session != NULL) && (caec->session == ve->session))
-  {
-    caec->exists = GNUNET_YES;
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-
-
-static void
-neighbour_timeout_task (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct NeighbourMapEntry *n = cls;
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-              "Neighbour `%4s' has timed out!\n", GNUNET_i2s (&n->id));
-#endif
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# disconnects due to timeout"), 1,
-                            GNUNET_NO);
-  n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  disconnect_neighbour (n, GNUNET_NO);
-}
-
-
-/**
- * Schedule the job that will cause us to send a PING to the
- * foreign address to evaluate its validity and latency.
- *
- * @param fal address to PING
- */
-static void
-schedule_next_ping (struct ForeignAddressList *fal);
-
-
-/**
- * Add the given address to the list of foreign addresses
- * available for the given peer (check for duplicates).
- *
- * @param cls the respective 'struct NeighbourMapEntry' to update
- * @param tname name of the transport
- * @param expiration expiration time
- * @param addr the address
- * @param addrlen length of the address
- * @return GNUNET_OK (always)
- */
-static int
-add_to_foreign_address_list (void *cls, const char *tname,
-                             struct GNUNET_TIME_Absolute expiration,
-                             const void *addr, uint16_t addrlen)
-{
-  struct NeighbourMapEntry *n = cls;
-  struct ForeignAddressList *fal;
-  int try;
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# valid peer addresses returned by PEERINFO"), 1,
-                            GNUNET_NO);
-  try = GNUNET_NO;
-  fal = find_peer_address (n, tname, NULL, addr, addrlen);
-  if (fal == NULL)
-  {
-#if DEBUG_TRANSPORT_HELLO
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Adding address `%s' (%s) for peer `%4s' due to PEERINFO data 
for %llums.\n",
-                a2s (tname, addr, addrlen), tname, GNUNET_i2s (&n->id),
-                expiration.abs_value);
-#endif
-    fal = add_peer_address (n, tname, NULL, addr, addrlen);
-    if (fal == NULL)
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# previously validated addresses lacking 
transport"),
-                                1, GNUNET_NO);
-    }
-    else
-    {
-      fal->expires = GNUNET_TIME_absolute_max (expiration, fal->expires);
-      schedule_next_ping (fal);
-    }
-    try = GNUNET_YES;
-  }
-  else
-  {
-    fal->expires = GNUNET_TIME_absolute_max (expiration, fal->expires);
-  }
-  if (fal == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to add new address for `%4s'\n", GNUNET_i2s (&n->id));
-#endif
-    return GNUNET_OK;
-  }
-  if (fal->validated == GNUNET_NO)
-  {
-    fal->validated = GNUNET_YES;
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# peer addresses considered valid"), 1,
-                              GNUNET_NO);
-  }
-  if (try == GNUNET_YES)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Have new addresses, will try to trigger transmissions.\n");
-#endif
-    try_transmission_to_peer (n);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Add addresses in validated HELLO "h" to the set of addresses
- * we have for this peer.
- *
- * @param cls closure ('struct NeighbourMapEntry*')
- * @param peer id of the peer, NULL for last call
- * @param h hello message for the peer (can be NULL)
- * @param err_msg NULL if successful, otherwise contains error message
- */
-static void
-add_hello_for_peer (void *cls, const struct GNUNET_PeerIdentity *peer,
-                    const struct GNUNET_HELLO_Message *h, const char *err_msg)
-{
-  struct NeighbourMapEntry *n = cls;
-
-  if (err_msg != NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                _("Error in communication with PEERINFO service: %s\n"),
-                err_msg);
-#endif
-    /* return; */
-  }
-  if (peer == NULL)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# outstanding peerinfo iterate requests"), -1,
-                              GNUNET_NO);
-    n->piter = NULL;
-    return;
-  }
-  if (h == NULL)
-    return;                     /* no HELLO available */
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Peerinfo had `%s' message for peer `%4s', adding existing 
addresses.\n",
-              "HELLO", GNUNET_i2s (peer));
-#endif
-  if (GNUNET_YES != n->public_key_valid)
-  {
-    GNUNET_HELLO_get_key (h, &n->publicKey);
-    n->public_key_valid = GNUNET_YES;
-  }
-  GNUNET_HELLO_iterate_addresses (h, GNUNET_NO, &add_to_foreign_address_list,
-                                  n);
-}
-
-
-/**
- * Create a fresh entry in our neighbour list for the given peer.
- * Will try to transmit our current HELLO to the new neighbour.
- * Do not call this function directly, use 'setup_peer_check_blacklist.
- *
- * @param peer the peer for which we create the entry
- * @param do_hello should we schedule transmitting a HELLO
- * @return the new neighbour list entry
- */
-static struct NeighbourMapEntry *
-setup_new_neighbour (const struct GNUNET_PeerIdentity *peer, int do_hello)
-{
-  struct NeighbourMapEntry *n;
-  struct TransportPlugin *tp;
-  struct ReadyList *rl;
-
-  GNUNET_assert (0 !=
-                 memcmp (peer, &my_identity,
-                         sizeof (struct GNUNET_PeerIdentity)));
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up state for neighbour 
`%4s'\n",
-              GNUNET_i2s (peer));
-#endif
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# active neighbours"), 1,
-                            GNUNET_NO);
-  n = GNUNET_malloc (sizeof (struct NeighbourMapEntry));
-  n->id = *peer;
-  n->peer_timeout =
-      GNUNET_TIME_relative_to_absolute
-      (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-  GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
-                                 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
-                                 MAX_BANDWIDTH_CARRY_S);
-  tp = plugins;
-  while (tp != NULL)
-  {
-    if ((tp->api->send != NULL) && (!is_blacklisted (peer, tp)))
-    {
-      rl = GNUNET_malloc (sizeof (struct ReadyList));
-      rl->neighbour = n;
-      rl->next = n->plugins;
-      n->plugins = rl;
-      rl->plugin = tp;
-      rl->addresses = NULL;
-    }
-    tp = tp->next;
-  }
-  n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
-  n->distance = -1;
-  n->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
-                                    &neighbour_timeout_task, n);
-  GNUNET_CONTAINER_multihashmap_put (neighbours, &n->id.hashPubKey, n,
-                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-  if (do_hello)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# peerinfo new neighbor iterate requests"), 1,
-                              GNUNET_NO);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# outstanding peerinfo iterate requests"), 1,
-                              GNUNET_NO);
-    n->piter =
-        GNUNET_PEERINFO_iterate (peerinfo, peer, GNUNET_TIME_UNIT_FOREVER_REL,
-                                 &add_hello_for_peer, n);
-
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# HELLO's sent to new neighbors"),
-                              1, GNUNET_NO);
-    if (NULL != our_hello)
-      transmit_to_peer (NULL, NULL, 0, HELLO_ADDRESS_EXPIRATION,
-                        (const char *) our_hello, GNUNET_HELLO_size 
(our_hello),
-                        GNUNET_NO, n);
-  }
-  return n;
-}
-
-
-/**
- * Function called after we have checked if communicating
- * with a given peer is acceptable.
- *
- * @param cls closure
- * @param n NULL if communication is not acceptable
- */
-typedef void (*SetupContinuation) (void *cls, struct NeighbourMapEntry * n);
-
-
-/**
- * Information kept for each client registered to perform
- * blacklisting.
- */
-struct Blacklisters
-{
-  /**
-   * This is a linked list.
-   */
-  struct Blacklisters *next;
-
-  /**
-   * This is a linked list.
-   */
-  struct Blacklisters *prev;
-
-  /**
-   * Client responsible for this entry.
-   */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Blacklist check that we're currently performing.
-   */
-  struct BlacklistCheck *bc;
-
-};
-
-
-/**
- * Head of DLL of blacklisting clients.
- */
-static struct Blacklisters *bl_head;
-
-/**
- * Tail of DLL of blacklisting clients.
- */
-static struct Blacklisters *bl_tail;
-
-
-/**
- * Context we use when performing a blacklist check.
- */
-struct BlacklistCheck
-{
-
-  /**
-   * This is a linked list.
-   */
-  struct BlacklistCheck *next;
-
-  /**
-   * This is a linked list.
-   */
-  struct BlacklistCheck *prev;
-
-  /**
-   * Peer being checked.
-   */
-  struct GNUNET_PeerIdentity peer;
-
-  /**
-   * Option for setup neighbour afterwards.
-   */
-  int do_hello;
-
-  /**
-   * Continuation to call with the result.
-   */
-  SetupContinuation cont;
-
-  /**
-   * Closure for cont.
-   */
-  void *cont_cls;
-
-  /**
-   * Current transmission request handle for this client, or NULL if no
-   * request is pending.
-   */
-  struct GNUNET_CONNECTION_TransmitHandle *th;
-
-  /**
-   * Our current position in the blacklisters list.
-   */
-  struct Blacklisters *bl_pos;
-
-  /**
-   * Current task performing the check.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier task;
-
-};
-
-/**
- * Head of DLL of active blacklisting queries.
- */
-static struct BlacklistCheck *bc_head;
-
-/**
- * Tail of DLL of active blacklisting queries.
- */
-static struct BlacklistCheck *bc_tail;
-
-
-/**
- * Perform next action in the blacklist check.
- *
- * @param cls the 'struct BlacklistCheck*'
- * @param tc unused
- */
-static void
-do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- * Transmit blacklist query to the client.
- *
- * @param cls the 'struct BlacklistCheck'
- * @param size number of bytes allowed
- * @param buf where to copy the message
- * @return number of bytes copied to buf
- */
-static size_t
-transmit_blacklist_message (void *cls, size_t size, void *buf)
-{
-  struct BlacklistCheck *bc = cls;
-  struct Blacklisters *bl;
-  struct BlacklistMessage bm;
-
-  bc->th = NULL;
-  if (size == 0)
-  {
-    GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK);
-    bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to send blacklist test for peer `%s' to client\n",
-                GNUNET_i2s (&bc->peer));
-    return 0;
-  }
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending blacklist test for peer `%s' to client\n",
-              GNUNET_i2s (&bc->peer));
-#endif
-  bl = bc->bl_pos;
-  bm.header.size = htons (sizeof (struct BlacklistMessage));
-  bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
-  bm.is_allowed = htonl (0);
-  bm.peer = bc->peer;
-  memcpy (buf, &bm, sizeof (bm));
-  GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
-  return sizeof (bm);
-}
-
-
-/**
- * Perform next action in the blacklist check.
- *
- * @param cls the 'struct BlacklistCheck*'
- * @param tc unused
- */
-static void
-do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct BlacklistCheck *bc = cls;
-  struct Blacklisters *bl;
-
-  bc->task = GNUNET_SCHEDULER_NO_TASK;
-  bl = bc->bl_pos;
-  if (bl == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No blacklist clients active, will now setup neighbour record 
for peer `%s'\n",
-                GNUNET_i2s (&bc->peer));
-#endif
-    bc->cont (bc->cont_cls, setup_new_neighbour (&bc->peer, bc->do_hello));
-    GNUNET_free (bc);
-    return;
-  }
-  if (bl->bc == NULL)
-  {
-    bl->bc = bc;
-    bc->th =
-        GNUNET_SERVER_notify_transmit_ready (bl->client,
-                                             sizeof (struct BlacklistMessage),
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &transmit_blacklist_message, bc);
-  }
-}
-
-
-/**
- * Obtain a 'struct NeighbourMapEntry' for the given peer.  If such an entry
- * does not yet exist, check the blacklist.  If the blacklist says creating
- * one is acceptable, create one and call the continuation; otherwise
- * call the continuation with NULL.
- *
- * @param peer peer to setup or look up a struct NeighbourMapEntry for
- * @param do_hello should we also schedule sending our HELLO to the peer
- *        if this is a new record
- * @param cont function to call with the 'struct NeigbhbourList*'
- * @param cont_cls closure for cont
- */
-static void
-setup_peer_check_blacklist (const struct GNUNET_PeerIdentity *peer,
-                            int do_hello, SetupContinuation cont,
-                            void *cont_cls)
-{
-  struct NeighbourMapEntry *n;
-  struct BlacklistCheck *bc;
-
-  n = find_neighbour (peer);
-  if (n != NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Neighbour record exists for peer `%s'\n", GNUNET_i2s (peer));
-#endif
-    if (cont != NULL)
-      cont (cont_cls, n);
-    return;
-  }
-  if (bl_head == NULL)
-  {
-    if (cont != NULL)
-      cont (cont_cls, setup_new_neighbour (peer, do_hello));
-    else
-      setup_new_neighbour (peer, do_hello);
-    return;
-  }
-  bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
-  GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
-  bc->peer = *peer;
-  bc->do_hello = do_hello;
-  bc->cont = cont;
-  bc->cont_cls = cont_cls;
-  bc->bl_pos = bl_head;
-  bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
-}
-
-
-/**
- * Function called with the result of querying a new blacklister about
- * it being allowed (or not) to continue to talk to an existing neighbour.
- *
- * @param cls the original 'struct NeighbourMapEntry'
- * @param n NULL if we need to disconnect
- */
-static void
-confirm_or_drop_neighbour (void *cls, struct NeighbourMapEntry *n)
-{
-  struct NeighbourMapEntry *orig = cls;
-
-  if (n == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
-                GNUNET_i2s (&orig->id), "confirm_or_drop_neighboUr");
-#endif
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# disconnects due to blacklist"),
-                              1, GNUNET_NO);
-    disconnect_neighbour (orig, GNUNET_NO);
-  }
-}
-
-
-struct TestConnectionContext
-{
-  int first;
-
-  struct Blacklisters *bl;
-};
-
-
-static int
-test_connection_ok (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct TestConnectionContext *tcc = cls;
-  struct NeighbourMapEntry *n = value;
-  struct BlacklistCheck *bc;
-
-
-  bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
-  GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
-  bc->peer = n->id;
-  bc->do_hello = GNUNET_NO;
-  bc->cont = &confirm_or_drop_neighbour;
-  bc->cont_cls = n;
-  bc->bl_pos = tcc->bl;
-  if (GNUNET_YES == tcc->first)
-  {
-    /* all would wait for the same client, no need to
-     * create more than just the first task right now */
-    bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
-    tcc->first = GNUNET_NO;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle a request to start a blacklist.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_blacklist_init (void *cls, struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
-{
-  struct Blacklisters *bl;
-  struct TestConnectionContext tcc;
-
-  bl = bl_head;
-  while (bl != NULL)
-  {
-    if (bl->client == client)
-    {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    bl = bl->next;
-  }
-  bl = GNUNET_malloc (sizeof (struct Blacklisters));
-  bl->client = client;
-  GNUNET_SERVER_client_keep (client);
-  GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
-  /* confirm that all existing connections are OK! */
-  tcc.bl = bl;
-  tcc.first = GNUNET_YES;
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &test_connection_ok, 
&tcc);
-}
-
-
-/**
- * Handle a request to blacklist a peer.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_blacklist_reply (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  const struct BlacklistMessage *msg =
-      (const struct BlacklistMessage *) message;
-  struct Blacklisters *bl;
-  struct BlacklistCheck *bc;
-
-  bl = bl_head;
-  while ((bl != NULL) && (bl->client != client))
-    bl = bl->next;
-  if (bl == NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist client disconnected\n");
-#endif
-    /* FIXME: other error handling here!? */
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  bc = bl->bc;
-  bl->bc = NULL;
-  if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklist check failed, peer not allowed\n");
-#endif
-    bc->cont (bc->cont_cls, NULL);
-    GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
-    GNUNET_free (bc);
-  }
-  else
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklist check succeeded, continuing with checks\n");
-#endif
-    bc->bl_pos = bc->bl_pos->next;
-    bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
-  }
-  /* check if any other bc's are waiting for this blacklister */
-  bc = bc_head;
-  while (bc != NULL)
-  {
-    if ((bc->bl_pos == bl) && (GNUNET_SCHEDULER_NO_TASK == bc->task))
-      bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
-    bc = bc->next;
-  }
-}
-
-
-/**
- * Send periodic PING messages to a given foreign address.
- *
- * @param cls our 'struct PeriodicValidationContext*'
- * @param tc task context
- */
-static void
-send_periodic_ping (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ForeignAddressList *peer_address = cls;
-  struct TransportPlugin *tp;
-  struct ValidationEntry *va;
-  struct NeighbourMapEntry *neighbour;
-  struct TransportPingMessage ping;
-  struct CheckAddressExistsClosure caec;
-  char *message_buf;
-  uint16_t hello_size;
-  size_t slen;
-  size_t tsize;
-
-  peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-    return;
-  GNUNET_assert (peer_address != NULL);
-  tp = peer_address->ready_list->plugin;
-  neighbour = peer_address->ready_list->neighbour;
-  if (GNUNET_YES != neighbour->public_key_valid)
-  {
-    /* no public key yet, try again later */
-    schedule_next_ping (peer_address);
-    return;
-  }
-  caec.addr = peer_address->addr;
-  caec.addrlen = peer_address->addrlen;
-  caec.tname = tp->short_name;
-  caec.session = peer_address->session;
-  caec.exists = GNUNET_NO;
-
-  GNUNET_CONTAINER_multihashmap_iterate (validation_map, &check_address_exists,
-                                         &caec);
-  if (caec.exists == GNUNET_YES)
-  {
-    /* During validation attempts we will likely trigger the other
-     * peer trying to validate our address which in turn will cause
-     * it to send us its HELLO, so we expect to hit this case rather
-     * frequently.  Only print something if we are very verbose. */
-#if DEBUG_TRANSPORT > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Some validation of address `%s' via `%s' for peer `%4s' 
already in progress.\n",
-                (peer_address->addr != NULL) ? a2s (tp->short_name,
-                                                    peer_address->addr,
-                                                    peer_address->addrlen) :
-                "<inbound>", tp->short_name, GNUNET_i2s (&neighbour->id));
-#endif
-    schedule_next_ping (peer_address);
-    return;
-  }
-  va = GNUNET_malloc (sizeof (struct ValidationEntry) + peer_address->addrlen);
-  va->transport_name = GNUNET_strdup (tp->short_name);
-  va->challenge =
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT_MAX);
-  va->send_time = GNUNET_TIME_absolute_get ();
-  va->session = peer_address->session;
-  if (peer_address->addr != NULL)
-  {
-    va->addr = (const void *) &va[1];
-    memcpy (&va[1], peer_address->addr, peer_address->addrlen);
-    va->addrlen = peer_address->addrlen;
-  }
-  memcpy (&va->publicKey, &neighbour->publicKey,
-          sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
-
-  va->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
-                                    &timeout_hello_validation, va);
-  GNUNET_CONTAINER_multihashmap_put (validation_map, &neighbour->id.hashPubKey,
-                                     va,
-                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-
-  if (peer_address->validated != GNUNET_YES)
-    hello_size = GNUNET_HELLO_size (our_hello);
-  else
-    hello_size = 0;
-
-  tsize = sizeof (struct TransportPingMessage) + hello_size;
-
-  if (peer_address->addr != NULL)
-  {
-    slen = strlen (tp->short_name) + 1;
-    tsize += slen + peer_address->addrlen;
-  }
-  else
-  {
-    slen = 0;                   /* make gcc happy */
-  }
-  message_buf = GNUNET_malloc (tsize);
-  ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
-  ping.challenge = htonl (va->challenge);
-  memcpy (&ping.target, &neighbour->id, sizeof (struct GNUNET_PeerIdentity));
-  if (peer_address->validated != GNUNET_YES)
-  {
-    memcpy (message_buf, our_hello, hello_size);
-  }
-
-  if (peer_address->addr != NULL)
-  {
-    ping.header.size =
-        htons (sizeof (struct TransportPingMessage) + peer_address->addrlen +
-               slen);
-    memcpy (&message_buf[hello_size + sizeof (struct TransportPingMessage)],
-            tp->short_name, slen);
-    memcpy (&message_buf
-            [hello_size + sizeof (struct TransportPingMessage) + slen],
-            peer_address->addr, peer_address->addrlen);
-  }
-  else
-  {
-    ping.header.size = htons (sizeof (struct TransportPingMessage));
-  }
-
-  memcpy (&message_buf[hello_size], &ping,
-          sizeof (struct TransportPingMessage));
-
-#if DEBUG_TRANSPORT_REVALIDATION
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Performing re-validation of address `%s' via `%s' for peer 
`%4s' sending `%s' (%u bytes) and `%s'\n",
-              (peer_address->addr !=
-               NULL) ? a2s (peer_address->plugin->short_name,
-                            peer_address->addr,
-                            peer_address->addrlen) : "<inbound>",
-              tp->short_name, GNUNET_i2s (&neighbour->id), "HELLO", hello_size,
-              "PING");
-#endif
-  if (peer_address->validated != GNUNET_YES)
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# PING with HELLO messages sent"),
-                              1, GNUNET_NO);
-  else
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# PING without HELLO messages sent"), 1,
-                              GNUNET_NO);
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# PING messages sent for re-validation"), 1,
-                            GNUNET_NO);
-  transmit_to_peer (NULL, peer_address, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                    HELLO_VERIFICATION_TIMEOUT, message_buf, tsize, GNUNET_YES,
-                    neighbour);
-  GNUNET_free (message_buf);
-  schedule_next_ping (peer_address);
-}
-
-
-/**
- * Schedule the job that will cause us to send a PING to the
- * foreign address to evaluate its validity and latency.
- *
- * @param fal address to PING
- */
-static void
-schedule_next_ping (struct ForeignAddressList *fal)
-{
-  struct GNUNET_TIME_Relative delay;
-
-  if (fal->revalidate_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (fal->revalidate_task);
-    fal->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  delay = GNUNET_TIME_absolute_get_remaining (fal->expires);
-  delay.rel_value /= 2;         /* do before expiration */
-  delay = GNUNET_TIME_relative_min (delay, LATENCY_EVALUATION_MAX_DELAY);
-  if (GNUNET_YES != fal->estimated)
-  {
-    delay = GNUNET_TIME_UNIT_ZERO;
-    fal->estimated = GNUNET_YES;
-  }
-
-  if (GNUNET_YES == fal->connected)
-  {
-    delay =
-        GNUNET_TIME_relative_min (delay,
-                                  CONNECTED_LATENCY_EVALUATION_MAX_DELAY);
-  }
-  /* FIXME: also adjust delay based on how close the last
-   * observed latency is to the latency of the best alternative */
-  /* bound how fast we can go */
-  delay = GNUNET_TIME_relative_max (delay, GNUNET_TIME_UNIT_SECONDS);
-  /* randomize a bit (to avoid doing all at the same time) */
-  delay.rel_value +=
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000);
-
-  GNUNET_assert (fal->revalidate_task == GNUNET_SCHEDULER_NO_TASK);
-  fal->revalidate_task =
-      GNUNET_SCHEDULER_add_delayed (delay, &send_periodic_ping, fal);
-}
-
-
-
-
-/**
- * Function that will be called if we receive some payload
- * from another peer.
- *
- * @param message the payload
- * @param n peer who claimed to be the sender
- */
-static void
-handle_payload_message (const struct GNUNET_MessageHeader *message,
-                        struct NeighbourMapEntry *n)
-{
-  struct InboundMessage *im;
-  struct TransportClient *cpos;
-  uint16_t msize;
-
-  msize = ntohs (message->size);
-  if (n->received_pong == GNUNET_NO)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received message of type %u and size %u from `%4s', but no 
pong yet!\n",
-                ntohs (message->type), ntohs (message->size),
-                GNUNET_i2s (&n->id));
-#endif
-    GNUNET_free_non_null (n->pre_connect_message_buffer);
-    n->pre_connect_message_buffer = GNUNET_malloc (msize);
-    memcpy (n->pre_connect_message_buffer, message, msize);
-    return;
-  }
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received message of type %u and size %u from `%4s', sending to 
all clients.\n",
-              ntohs (message->type), ntohs (message->size),
-              GNUNET_i2s (&n->id));
-#endif
-  if (GNUNET_YES ==
-      GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, (ssize_t) msize))
-  {
-    n->quota_violation_count++;
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
-                n->in_tracker.available_bytes_per_s__,
-                n->quota_violation_count);
-#endif
-    /* Discount 32k per violation */
-    GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024);
-  }
-  else
-  {
-    if (n->quota_violation_count > 0)
-    {
-      /* try to add 32k back */
-      GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, 32 * 1024);
-      n->quota_violation_count--;
-    }
-  }
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# payload received from other peers"), msize,
-                            GNUNET_NO);
-  /* transmit message to all clients */
-  uint32_t ats_count = 2;
-  size_t size =
-      sizeof (struct InboundMessage) +
-      ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + msize;
-  if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
-    GNUNET_break (0);
-
-  im = GNUNET_malloc (size);
-  im->header.size = htons (size);
-  im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
-  im->peer = n->id;
-  im->ats_count = htonl (ats_count);
-  /* Setting ATS data */
-  (&(im->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
-  (&(im->ats))[0].value = htonl (n->distance);
-  (&(im->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
-  (&(im->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
-  (&(im->ats))[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
-  (&(im->ats))[ats_count].value = htonl (0);
-
-  memcpy (&((&(im->ats))[ats_count + 1]), message, msize);
-  cpos = clients;
-  while (cpos != NULL)
-  {
-    transmit_to_client (cpos, &im->header, GNUNET_YES);
-    cpos = cpos->next;
-  }
-  GNUNET_free (im);
-}
-
-
-/**
- * Iterator over hash map entries.  Checks if the given validation
- * entry is for the same challenge as what is given in the PONG.
- *
- * @param cls the 'struct TransportPongMessage*'
- * @param key peer identity
- * @param value value in the hash map ('struct ValidationEntry')
- * @return GNUNET_YES if we should continue to
- *         iterate (mismatch), GNUNET_NO if not (entry matched)
- */
-static int
-check_pending_validation (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  const struct TransportPongMessage *pong = cls;
-  struct ValidationEntry *ve = value;
-  struct AddValidatedAddressContext avac;
-  unsigned int challenge = ntohl (pong->challenge);
-  struct GNUNET_HELLO_Message *hello;
-  struct GNUNET_PeerIdentity target;
-  struct NeighbourMapEntry *n;
-  struct ForeignAddressList *fal;
-  struct OwnAddressList *oal;
-  struct TransportPlugin *tp;
-  struct GNUNET_MessageHeader *prem;
-  uint16_t ps;
-  const char *addr;
-  size_t slen;
-  size_t alen;
-
-  ps = ntohs (pong->header.size);
-  if (ps < sizeof (struct TransportPongMessage))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_NO;
-  }
-  addr = (const char *) &pong[1];
-  slen = strlen (ve->transport_name) + 1;
-  if ((ps - sizeof (struct TransportPongMessage) < slen) ||
-      (ve->challenge != challenge) || (addr[slen - 1] != '\0') ||
-      (0 != strcmp (addr, ve->transport_name)) ||
-      (ntohl (pong->purpose.size) !=
-       sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (uint32_t) +
-       sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-       sizeof (struct GNUNET_PeerIdentity) + ps -
-       sizeof (struct TransportPongMessage)))
-  {
-    return GNUNET_YES;
-  }
-
-  alen = ps - sizeof (struct TransportPongMessage) - slen;
-  switch (ntohl (pong->purpose.purpose))
-  {
-  case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN:
-    if ((ve->addrlen + slen != ntohl (pong->addrlen)) ||
-        (0 != memcmp (&addr[slen], ve->addr, ve->addrlen)))
-    {
-      return GNUNET_YES;        /* different entry, keep trying! */
-    }
-    if (0 != memcmp (&pong->pid, key, sizeof (struct GNUNET_PeerIdentity)))
-    {
-      GNUNET_break_op (0);
-      return GNUNET_NO;
-    }
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
-                                  &pong->purpose, &pong->signature,
-                                  &ve->publicKey))
-    {
-      GNUNET_break_op (0);
-      return GNUNET_NO;
-    }
-
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Confirmed validity of address, peer `%4s' has address `%s' 
(%s).\n",
-                GNUNET_h2s (key), a2s (ve->transport_name,
-                                       (const struct sockaddr *) ve->addr,
-                                       ve->addrlen), ve->transport_name);
-#endif
-    break;
-  case GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING:
-    if (0 !=
-        memcmp (&pong->pid, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
-    {
-      char *peer;
-
-      GNUNET_asprintf (&peer, "%s", GNUNET_i2s (&pong->pid));
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received PONG for different identity: I am `%s', PONG 
identity: `%s'\n",
-                  GNUNET_i2s (&my_identity), peer);
-#endif
-      GNUNET_free (peer);
-      return GNUNET_NO;
-    }
-    if (ve->addrlen != 0)
-    {
-      /* must have been for a different validation entry */
-      return GNUNET_YES;
-    }
-    tp = find_transport (ve->transport_name);
-    if (tp == NULL)
-    {
-      GNUNET_break (0);
-      return GNUNET_YES;
-    }
-    oal = tp->addresses;
-    while (NULL != oal)
-    {
-      if ((oal->addrlen == alen) && (0 == memcmp (&oal[1], &addr[slen], alen)))
-        break;
-      oal = oal->next;
-    }
-    if (oal == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Not accepting PONG from `%s' with address `%s' since I 
cannot confirm using this address.\n"),
-                  GNUNET_i2s (&pong->pid), a2s (ve->transport_name, 
&addr[slen],
-                                                alen));
-      /* FIXME: since the sender of the PONG currently uses the
-       * wrong address (see FIMXE there!), we cannot run a
-       * proper check here... */
-#if FIXME_URGENT
-      return GNUNET_NO;
-#endif
-    }
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_rsa_verify 
(GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING,
-                                  &pong->purpose, &pong->signature,
-                                  &ve->publicKey))
-    {
-      GNUNET_break_op (0);
-      return GNUNET_NO;
-    }
-
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Confirmed that peer `%4s' is talking to us using address `%s' 
(%s) for us.\n",
-                GNUNET_h2s (key), a2s (ve->transport_name, &addr[slen], alen),
-                ve->transport_name);
-#endif
-    break;
-  default:
-    GNUNET_break_op (0);
-    return GNUNET_NO;
-  }
-  if (GNUNET_TIME_absolute_get_remaining
-      (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value == 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("Received expired signature.  Check system time.\n"));
-    return GNUNET_NO;
-  }
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# address validation successes"), 1,
-                            GNUNET_NO);
-  /* create the updated HELLO */
-  GNUNET_CRYPTO_hash (&ve->publicKey,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &target.hashPubKey);
-  if (ve->addr != NULL)
-  {
-    avac.done = GNUNET_NO;
-    avac.ve = ve;
-    hello = GNUNET_HELLO_create (&ve->publicKey, &add_validated_address, 
&avac);
-    GNUNET_PEERINFO_add_peer (peerinfo, hello);
-    GNUNET_free (hello);
-  }
-  n = find_neighbour (&target);
-  if (n != NULL)
-  {
-    n->publicKey = ve->publicKey;
-    n->public_key_valid = GNUNET_YES;
-    fal =
-        add_peer_address (n, ve->transport_name, ve->session, ve->addr,
-                          ve->addrlen);
-    GNUNET_assert (fal != NULL);
-    fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
-    fal->validated = GNUNET_YES;
-    mark_address_connected (fal);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# peer addresses considered valid"), 1,
-                              GNUNET_NO);
-    fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
-    update_addr_value (fal,
-                       GNUNET_TIME_absolute_get_duration (ve->
-                                                          send_time).rel_value,
-                       GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
-
-    schedule_next_ping (fal);
-    if (n->latency.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
-      n->latency = fal->latency;
-    else
-      n->latency.rel_value =
-          (fal->latency.rel_value + n->latency.rel_value) / 2;
-
-    n->distance = fal->distance;
-    if (GNUNET_NO == n->received_pong)
-    {
-      n->received_pong = GNUNET_YES;
-      notify_clients_connect (&target, n->latency, n->distance);
-      if (NULL != (prem = n->pre_connect_message_buffer))
-      {
-        n->pre_connect_message_buffer = NULL;
-        handle_payload_message (prem, n);
-        GNUNET_free (prem);
-      }
-    }
-    if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
-    {
-      GNUNET_SCHEDULER_cancel (n->retry_task);
-      n->retry_task = GNUNET_SCHEDULER_NO_TASK;
-      try_transmission_to_peer (n);
-    }
-  }
-
-  /* clean up validation entry */
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multihashmap_remove (validation_map, key,
-                                                       ve));
-  abort_validation (NULL, NULL, ve);
-  return GNUNET_NO;
-}
-
-
-/**
- * Function that will be called if we receive a validation
- * of an address challenge that we transmitted to another
- * peer.  Note that the validation should only be considered
- * acceptable if the challenge matches AND if the sender
- * address is at least a plausible address for this peer
- * (otherwise we may be seeing a MiM attack).
- *
- * @param cls closure
- * @param message the pong message
- * @param peer who responded to our challenge
- * @param sender_address string describing our sender address (as observed
- *         by the other peer in binary format)
- * @param sender_address_len number of bytes in 'sender_address'
- */
-static void
-handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
-             const struct GNUNET_PeerIdentity *peer, const char 
*sender_address,
-             size_t sender_address_len)
-{
-  if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    /* PONG send to self, ignore */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message from 
myself\n",
-                "PONG");
-    return;
-  }
-#if DEBUG_TRANSPORT > 1
-  /* we get tons of these that just get discarded, only log
-   * if we are quite verbose */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message from `%4s'.\n",
-              "PONG", GNUNET_i2s (peer));
-#endif
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"), 
1,
-                            GNUNET_NO);
-  if (GNUNET_SYSERR !=
-      GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
-                                                  &peer->hashPubKey,
-                                                  &check_pending_validation,
-                                                  (void *) message))
-  {
-    /* This is *expected* to happen a lot since we send
-     * PONGs to *all* known addresses of the sender of
-     * the PING, so most likely we get multiple PONGs
-     * per PING, and all but the first PONG will end up
-     * here. So really we should not print anything here
-     * unless we want to be very, very verbose... */
-#if DEBUG_TRANSPORT > 2
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received `%s' message from `%4s' but have no record of a 
matching `%s' message. Ignoring.\n",
-                "PONG", GNUNET_i2s (peer), "PING");
-#endif
-    return;
-  }
-
-}
-
-
-/**
- * Try to validate a neighbour's address by sending him our HELLO and a PING.
- *
- * @param cls the 'struct ValidationEntry*'
- * @param neighbour neighbour to validate, NULL if validation failed
- */
-static void
-transmit_hello_and_ping (void *cls, struct NeighbourMapEntry *neighbour)
-{
-  struct ValidationEntry *va = cls;
-  struct ForeignAddressList *peer_address;
-  struct TransportPingMessage ping;
-  uint16_t hello_size;
-  size_t tsize;
-  char *message_buf;
-  struct GNUNET_PeerIdentity id;
-  size_t slen;
-
-  GNUNET_CRYPTO_hash (&va->publicKey,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &id.hashPubKey);
-  if (neighbour == NULL)
-  {
-    /* FIXME: stats... */
-    GNUNET_break (GNUNET_OK ==
-                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
-                                                        &id.hashPubKey, va));
-    abort_validation (NULL, NULL, va);
-    return;
-  }
-  neighbour->publicKey = va->publicKey;
-  neighbour->public_key_valid = GNUNET_YES;
-  peer_address =
-      add_peer_address (neighbour, va->transport_name, NULL,
-                        (const void *) &va[1], va->addrlen);
-  if (peer_address == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to add peer `%4s' for plugin `%s'\n",
-                GNUNET_i2s (&neighbour->id), va->transport_name);
-    GNUNET_break (GNUNET_OK ==
-                  GNUNET_CONTAINER_multihashmap_remove (validation_map,
-                                                        &id.hashPubKey, va));
-    abort_validation (NULL, NULL, va);
-    return;
-  }
-  if (NULL == our_hello)
-    refresh_hello_task (NULL, NULL);
-  hello_size = GNUNET_HELLO_size (our_hello);
-  slen = strlen (va->transport_name) + 1;
-  tsize =
-      sizeof (struct TransportPingMessage) + hello_size + va->addrlen + slen;
-  message_buf = GNUNET_malloc (tsize);
-  ping.challenge = htonl (va->challenge);
-  ping.header.size =
-      htons (sizeof (struct TransportPingMessage) + slen + va->addrlen);
-  ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
-  memcpy (&ping.target, &neighbour->id, sizeof (struct GNUNET_PeerIdentity));
-  memcpy (message_buf, our_hello, hello_size);
-  memcpy (&message_buf[hello_size], &ping,
-          sizeof (struct TransportPingMessage));
-  memcpy (&message_buf[hello_size + sizeof (struct TransportPingMessage)],
-          va->transport_name, slen);
-  memcpy (&message_buf
-          [hello_size + sizeof (struct TransportPingMessage) + slen], &va[1],
-          va->addrlen);
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Performing validation of address `%s' via `%s' for peer `%4s' 
sending `%s' (%u bytes) and `%s' (%u bytes)\n",
-              (va->addrlen == 0) ? "<inbound>" : a2s (va->transport_name,
-                                                      (const void *) &va[1],
-                                                      va->addrlen),
-              va->transport_name, GNUNET_i2s (&neighbour->id), "HELLO",
-              hello_size, "PING",
-              sizeof (struct TransportPingMessage) + va->addrlen + slen);
-#endif
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# PING messages sent for initial validation"), 1,
-                            GNUNET_NO);
-  transmit_to_peer (NULL, peer_address, GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                    HELLO_VERIFICATION_TIMEOUT, message_buf, tsize, GNUNET_YES,
-                    neighbour);
-  GNUNET_free (message_buf);
-}
-
-
-/**
- * Check if the given address is already being validated; if not,
- * append the given address to the list of entries that are being be
- * validated and initiate validation.
- *
- * @param cls closure ('struct CheckHelloValidatedContext *')
- * @param tname name of the transport
- * @param expiration expiration time
- * @param addr the address
- * @param addrlen length of the address
- * @return GNUNET_OK (always)
- */
-static int
-run_validation (void *cls, const char *tname,
-                struct GNUNET_TIME_Absolute expiration, const void *addr,
-                uint16_t addrlen)
-{
-  struct CheckHelloValidatedContext *chvc = cls;
-  struct GNUNET_PeerIdentity id;
-  struct TransportPlugin *tp;
-  struct ValidationEntry *va;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
-  struct CheckAddressExistsClosure caec;
-  struct OwnAddressList *oal;
-
-  GNUNET_assert (addr != NULL);
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# peer addresses scheduled for validation"), 1,
-                            GNUNET_NO);
-  tp = find_transport (tname);
-  if (tp == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
-                _
-                ("Transport `%s' not loaded, will not try to validate peer 
address using this transport.\n"),
-                tname);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# peer addresses not validated (plugin not 
available)"),
-                              1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  /* check if this is one of our own addresses */
-  oal = tp->addresses;
-  while (NULL != oal)
-  {
-    if ((oal->addrlen == addrlen) && (0 == memcmp (&oal[1], addr, addrlen)))
-    {
-      /* not plausible, this address is equivalent to our own address! */
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# peer addresses not validated (loopback)"),
-                                1, GNUNET_NO);
-      return GNUNET_OK;
-    }
-    oal = oal->next;
-  }
-  GNUNET_HELLO_get_key (chvc->hello, &pk);
-  GNUNET_CRYPTO_hash (&pk,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &id.hashPubKey);
-
-  if (is_blacklisted (&id, tp))
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Attempted to validate blacklisted peer `%s' using `%s'!\n",
-                GNUNET_i2s (&id), tname);
-#endif
-    return GNUNET_OK;
-  }
-
-  caec.addr = addr;
-  caec.addrlen = addrlen;
-  caec.session = NULL;
-  caec.tname = tname;
-  caec.exists = GNUNET_NO;
-  GNUNET_CONTAINER_multihashmap_iterate (validation_map, &check_address_exists,
-                                         &caec);
-  if (caec.exists == GNUNET_YES)
-  {
-    /* During validation attempts we will likely trigger the other
-     * peer trying to validate our address which in turn will cause
-     * it to send us its HELLO, so we expect to hit this case rather
-     * frequently.  Only print something if we are very verbose. */
-#if DEBUG_TRANSPORT > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Validation of address `%s' via `%s' for peer `%4s' already in 
progress.\n",
-                a2s (tname, addr, addrlen), tname, GNUNET_i2s (&id));
-#endif
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# peer addresses not validated (in progress)"),
-                              1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
-  va->chvc = chvc;
-  chvc->ve_count++;
-  va->transport_name = GNUNET_strdup (tname);
-  va->challenge =
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT_MAX);
-  va->send_time = GNUNET_TIME_absolute_get ();
-  va->addr = (const void *) &va[1];
-  memcpy (&va[1], addr, addrlen);
-  va->addrlen = addrlen;
-  GNUNET_HELLO_get_key (chvc->hello, &va->publicKey);
-  va->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
-                                    &timeout_hello_validation, va);
-  GNUNET_CONTAINER_multihashmap_put (validation_map, &id.hashPubKey, va,
-                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-  setup_peer_check_blacklist (&id, GNUNET_NO, &transmit_hello_and_ping, va);
-  return GNUNET_OK;
-}
-
-
-/**
- * Check if addresses in validated hello "h" overlap with
- * those in "chvc->hello" and validate the rest.
- *
- * @param cls closure
- * @param peer id of the peer, NULL for last call
- * @param h hello message for the peer (can be NULL)
- * @param err_msg NULL if successful, otherwise contains error message
- */
-static void
-check_hello_validated (void *cls, const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_HELLO_Message *h,
-                       const char *err_msg)
-{
-  struct CheckHelloValidatedContext *chvc = cls;
-  struct GNUNET_HELLO_Message *plain_hello;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
-  struct GNUNET_PeerIdentity target;
-  struct NeighbourMapEntry *n;
-
-  if (err_msg != NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                _("Error in communication with PEERINFO service: %s\n"),
-                err_msg);
-#endif
-    /* return; */
-  }
-
-  if (peer == NULL)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# outstanding peerinfo iterate requests"), -1,
-                              GNUNET_NO);
-    chvc->piter = NULL;
-    if (GNUNET_NO == chvc->hello_known)
-    {
-      /* notify PEERINFO about the peer now, so that we at least
-       * have the public key if some other component needs it */
-      GNUNET_HELLO_get_key (chvc->hello, &pk);
-      GNUNET_CRYPTO_hash (&pk,
-                          sizeof (struct
-                                  GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                          &target.hashPubKey);
-      plain_hello = GNUNET_HELLO_create (&pk, NULL, NULL);
-      GNUNET_PEERINFO_add_peer (peerinfo, plain_hello);
-      GNUNET_free (plain_hello);
-#if DEBUG_TRANSPORT_HELLO
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "PEERINFO had no `%s' message for peer `%4s', full 
validation needed.\n",
-                  "HELLO", GNUNET_i2s (&target));
-#endif
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# new HELLOs requiring full validation"), 1,
-                                GNUNET_NO);
-      GNUNET_HELLO_iterate_addresses (chvc->hello, GNUNET_NO, &run_validation,
-                                      chvc);
-    }
-    else
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop ("# duplicate HELLO (peer 
known)"),
-                                1, GNUNET_NO);
-    }
-    chvc->ve_count--;
-    if (chvc->ve_count == 0)
-    {
-      GNUNET_CONTAINER_DLL_remove (chvc_head, chvc_tail, chvc);
-      GNUNET_free (chvc);
-    }
-    return;
-  }
-  if (h == NULL)
-    return;
-#if DEBUG_TRANSPORT_HELLO
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "PEERINFO had `%s' message for peer `%4s', validating only new 
addresses.\n",
-              "HELLO", GNUNET_i2s (peer));
-#endif
-  chvc->hello_known = GNUNET_YES;
-  n = find_neighbour (peer);
-  if (n != NULL)
-  {
-#if DEBUG_TRANSPORT_HELLO
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Calling hello_iterate_addresses for %s!\n", GNUNET_i2s 
(peer));
-#endif
-    GNUNET_HELLO_iterate_addresses (h, GNUNET_NO, &add_to_foreign_address_list,
-                                    n);
-    try_transmission_to_peer (n);
-  }
-  else
-  {
-#if DEBUG_TRANSPORT_HELLO
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No existing neighbor record for %s!\n", GNUNET_i2s (peer));
-#endif
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# no existing neighbour record (validating 
HELLO)"),
-                              1, GNUNET_NO);
-  }
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# HELLO validations (update case)"),
-                            1, GNUNET_NO);
-  GNUNET_HELLO_iterate_new_addresses (chvc->hello, h,
-                                      GNUNET_TIME_relative_to_absolute
-                                      (HELLO_REVALIDATION_START_TIME),
-                                      &run_validation, chvc);
-}
-
-
-/**
- * Process HELLO-message.
- *
- * @param plugin transport involved, may be NULL
- * @param message the actual message
- * @return GNUNET_OK if the HELLO was well-formed, GNUNET_SYSERR otherwise
- */
-static int
-process_hello (struct TransportPlugin *plugin,
-               const struct GNUNET_MessageHeader *message)
-{
-  uint16_t hsize;
-  struct GNUNET_PeerIdentity target;
-  const struct GNUNET_HELLO_Message *hello;
-  struct CheckHelloValidatedContext *chvc;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
-  struct NeighbourMapEntry *n;
-
-#if DEBUG_TRANSPORT_HELLO > 2
-  char *my_id;
-#endif
-
-  hsize = ntohs (message->size);
-  if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
-      (hsize < sizeof (struct GNUNET_MessageHeader)))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# HELLOs received for validation"),
-                            1, GNUNET_NO);
-
-  hello = (const struct GNUNET_HELLO_Message *) message;
-  if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
-  {
-#if DEBUG_TRANSPORT_HELLO
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Unable to get public key from `%s' for `%4s'!\n", "HELLO",
-                GNUNET_i2s (&target));
-#endif
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_CRYPTO_hash (&publicKey,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &target.hashPubKey);
-
-#if DEBUG_TRANSPORT_HELLO
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for `%4s'\n",
-              "HELLO", GNUNET_i2s (&target));
-#endif
-  if (0 == memcmp (&my_identity, &target, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# HELLOs ignored for validation (is my own 
HELLO)"),
-                              1, GNUNET_NO);
-    return GNUNET_OK;
-  }
-  n = find_neighbour (&target);
-  if ((NULL != n) && (!n->public_key_valid))
-  {
-    GNUNET_HELLO_get_key (hello, &n->publicKey);
-    n->public_key_valid = GNUNET_YES;
-  }
-
-  /* check if load is too high before doing expensive stuff */
-  if (GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_BACKGROUND) >
-      MAX_HELLO_LOAD)
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# HELLOs ignored due to high load"), 1,
-                              GNUNET_NO);
-#if DEBUG_TRANSPORT_HELLO
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Ignoring `%s' for `%4s', load too high.\n", "HELLO",
-                GNUNET_i2s (&target));
-#endif
-    return GNUNET_OK;
-  }
-
-
-  chvc = chvc_head;
-  while (NULL != chvc)
-  {
-    if (GNUNET_HELLO_equals
-        (hello, chvc->hello, GNUNET_TIME_absolute_get ()).abs_value > 0)
-    {
-#if DEBUG_TRANSPORT_HELLO > 2
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received duplicate `%s' message for `%4s'; ignored\n",
-                  "HELLO", GNUNET_i2s (&target));
-#endif
-      return GNUNET_OK;         /* validation already pending */
-    }
-    if (GNUNET_HELLO_size (hello) == GNUNET_HELLO_size (chvc->hello))
-      GNUNET_break (0 !=
-                    memcmp (hello, chvc->hello, GNUNET_HELLO_size (hello)));
-    chvc = chvc->next;
-  }
-
-#if BREAK_TESTS
-  struct NeighbourMapEntry *temp_neighbor = find_neighbour (&target);
-
-  if ((NULL != temp_neighbor))
-  {
-    fprintf (stderr, "Already know peer, ignoring hello\n");
-    return GNUNET_OK;
-  }
-#endif
-
-#if DEBUG_TRANSPORT_HELLO > 2
-  if (plugin != NULL)
-  {
-#if DEBUG_TRANSPORT
-    my_id = GNUNET_strdup (GNUNET_i2s (plugin->env.my_identity));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "%s: Starting validation of `%s' message for `%4s' via '%s' of 
size %u\n",
-                my_id, "HELLO", GNUNET_i2s (&target), plugin->short_name,
-                GNUNET_HELLO_size (hello));
-    GNUNET_free (my_id);
-#endif
-  }
-#endif
-  chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
-  chvc->ve_count = 1;
-  chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
-  memcpy (&chvc[1], hello, hsize);
-  GNUNET_CONTAINER_DLL_insert (chvc_head, chvc_tail, chvc);
-  /* finally, check if HELLO was previously validated
-   * (continuation will then schedule actual validation) */
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# peerinfo process hello iterate requests"), 1,
-                            GNUNET_NO);
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# outstanding peerinfo iterate requests"), 1,
-                            GNUNET_NO);
-  chvc->piter =
-      GNUNET_PEERINFO_iterate (peerinfo, &target, HELLO_VERIFICATION_TIMEOUT,
-                               &check_hello_validated, chvc);
-  return GNUNET_OK;
-}
-
-
-/**
- * The peer specified by the given neighbour has timed-out or a plugin
- * has disconnected.  We may either need to do nothing (other plugins
- * still up), or trigger a full disconnect and clean up.  This
- * function updates our state and does the necessary notifications.
- * Also notifies our clients that the neighbour is now officially
- * gone.
- *
- * @param n the neighbour list entry for the peer
- * @param check GNUNET_YES to check if ALL addresses for this peer
- *              are gone, GNUNET_NO to force a disconnect of the peer
- *              regardless of whether other addresses exist.
- */
-static void
-disconnect_neighbour (struct NeighbourMapEntry *n, int check)
-{
-  struct ReadyList *rpos;
-  struct MessageQueue *mq;
-  struct ForeignAddressList *peer_addresses;
-  struct ForeignAddressList *peer_pos;
-
-  if (GNUNET_YES == n->in_disconnect)
-    return;
-  if (GNUNET_YES == check)
-  {
-    rpos = n->plugins;
-    while (NULL != rpos)
-    {
-      peer_addresses = rpos->addresses;
-      while (peer_addresses != NULL)
-      {
-        /* Do not disconnect if: an address is connected or an inbound address 
exists */
-        if ((GNUNET_YES == peer_addresses->connected) ||
-            (peer_addresses->addrlen == 0))
-        {
-#if DEBUG_TRANSPORT
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "NOT Disconnecting from `%4s', still have live address 
`%s'!\n",
-                      GNUNET_i2s (&n->id),
-                      a2s (peer_addresses->ready_list->plugin->short_name,
-                           peer_addresses->addr, peer_addresses->addrlen));
-#endif
-          return;               /* still connected */
-        }
-        peer_addresses = peer_addresses->next;
-      }
-      rpos = rpos->next;
-    }
-  }
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-              "Disconnecting from `%4s'\n", GNUNET_i2s (&n->id));
-#endif
-  n->in_disconnect = GNUNET_YES;        /* prevent recursive entry */
-
-  /* notify all clients about disconnect */
-  if (GNUNET_YES == n->received_pong)
-  {
-    n->received_pong = GNUNET_NO;
-    notify_clients_disconnect (&n->id);
-  }
-#if HAVE_LIBGLPK
-  ats_modify_problem_state (ats, ATS_MODIFIED);
-#endif
-  /* clean up all plugins, cancel connections and pending transmissions */
-  while (NULL != (rpos = n->plugins))
-  {
-    n->plugins = rpos->next;
-    rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
-    while (rpos->addresses != NULL)
-    {
-      peer_pos = rpos->addresses;
-      rpos->addresses = peer_pos->next;
-      if (peer_pos->connected == GNUNET_YES)
-      {
-        GNUNET_STATISTICS_update (stats, gettext_noop ("# connected 
addresses"),
-                                  -1, GNUNET_NO);
-        peer_pos->connected = GNUNET_NO;
-      }
-      if (GNUNET_YES == peer_pos->validated)
-        GNUNET_STATISTICS_update (stats,
-                                  gettext_noop
-                                  ("# peer addresses considered valid"), -1,
-                                  GNUNET_NO);
-      if (GNUNET_SCHEDULER_NO_TASK != peer_pos->revalidate_task)
-      {
-        GNUNET_SCHEDULER_cancel (peer_pos->revalidate_task);
-        peer_pos->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-      }
-      GNUNET_free (peer_pos->ressources);
-      peer_pos->ressources = NULL;
-      GNUNET_free (peer_pos->quality);
-      peer_pos->ressources = NULL;
-      GNUNET_free (peer_pos);
-    }
-    GNUNET_free (rpos);
-  }
-
-  /* free all messages on the queue */
-  while (NULL != (mq = n->messages_head))
-  {
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# bytes in message queue for other peers"),
-                              -(int64_t) mq->message_buf_size, GNUNET_NO);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# bytes discarded due to disconnect"),
-                              mq->message_buf_size, GNUNET_NO);
-    GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
-    GNUNET_assert (0 ==
-                   memcmp (&mq->neighbour_id, &n->id,
-                           sizeof (struct GNUNET_PeerIdentity)));
-    GNUNET_free (mq);
-  }
-
-  while (NULL != (mq = n->cont_head))
-  {
-
-    GNUNET_CONTAINER_DLL_remove (n->cont_head, n->cont_tail, mq);
-    GNUNET_assert (0 ==
-                   memcmp (&mq->neighbour_id, &n->id,
-                           sizeof (struct GNUNET_PeerIdentity)));
-    GNUNET_free (mq);
-  }
-
-  if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (n->timeout_task);
-    n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (n->retry_task);
-    n->retry_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (n->piter != NULL)
-  {
-    GNUNET_PEERINFO_iterate_cancel (n->piter);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# outstanding peerinfo iterate requests"), -1,
-                              GNUNET_NO);
-    n->piter = NULL;
-  }
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_remove (neighbours,
-                                                       &n->id.hashPubKey, n));
-  /* finally, free n itself */
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# active neighbours"), -1,
-                            GNUNET_NO);
-  GNUNET_free_non_null (n->pre_connect_message_buffer);
-  GNUNET_free (n);
-}
-
-
-/**
- * We have received a PING message from someone.  Need to send a PONG message
- * in response to the peer by any means necessary.
- */
-static int
-handle_ping (void *cls, const struct GNUNET_MessageHeader *message,
-             const struct GNUNET_PeerIdentity *peer, struct Session *session,
-             const char *sender_address, uint16_t sender_address_len)
-{
-  struct TransportPlugin *plugin = cls;
-  struct SessionHeader *session_header = (struct SessionHeader *) session;
-  struct TransportPingMessage *ping;
-  struct TransportPongMessage *pong;
-  struct NeighbourMapEntry *n;
-  struct ReadyList *rl;
-  struct ForeignAddressList *fal;
-  struct OwnAddressList *oal;
-  const char *addr;
-  size_t alen;
-  size_t slen;
-  int did_pong;
-
-  if (ntohs (message->size) < sizeof (struct TransportPingMessage))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-
-  ping = (struct TransportPingMessage *) message;
-  if (0 !=
-      memcmp (&ping->target, plugin->env.my_identity,
-              sizeof (struct GNUNET_PeerIdentity)))
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                _
-                ("Received `%s' message from `%s' destined for `%s' which is 
not me!\n"),
-                "PING", (sender_address != NULL) ? a2s (plugin->short_name,
-                                                        (const struct sockaddr
-                                                         *) sender_address,
-                                                        sender_address_len) :
-                "<inbound>", GNUNET_i2s (&ping->target));
-#endif
-    return GNUNET_SYSERR;
-  }
-#if DEBUG_PING_PONG
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-              "Processing `%s' from `%s'\n", "PING",
-              (sender_address != NULL) ? a2s (plugin->short_name,
-                                              (const struct sockaddr *)
-                                              sender_address,
-                                              sender_address_len) :
-              "<inbound>");
-#endif
-  GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"), 
1,
-                            GNUNET_NO);
-  addr = (const char *) &ping[1];
-  alen = ntohs (message->size) - sizeof (struct TransportPingMessage);
-  slen = strlen (plugin->short_name) + 1;
-  if (alen == 0)
-  {
-    /* peer wants to confirm that we have an outbound connection to him */
-    if (session == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  _
-                  ("Refusing to create PONG since I do not have a session with 
`%s'.\n"),
-                  GNUNET_i2s (peer));
-      return GNUNET_SYSERR;
-    }
-    /* FIXME-urg: the use of 'sender_address' in the code below is 
doubly-wrong:
-     * 1) it is NULL when we need to have a real value
-     * 2) it is documented to be the address of the sender (source-IP), where
-     * what we actually want is our LISTEN IP (what we 'bound' to); which we 
don't even
-     * have...
-     */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating PONG indicating that we received a connection at our 
address `%s' from `%s'.\n",
-                a2s (plugin->short_name, sender_address, sender_address_len),
-                GNUNET_i2s (peer));
-
-    pong =
-        GNUNET_malloc (sizeof (struct TransportPongMessage) +
-                       sender_address_len + slen);
-    pong->header.size =
-        htons (sizeof (struct TransportPongMessage) + sender_address_len +
-               slen);
-    pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
-    pong->purpose.size =
-        htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
-               sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-               sizeof (struct GNUNET_PeerIdentity) + sender_address_len + 
slen);
-    pong->purpose.purpose =
-        htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING);
-    pong->challenge = ping->challenge;
-    pong->addrlen = htonl (sender_address_len + slen);
-    memcpy (&pong->pid, peer, sizeof (struct GNUNET_PeerIdentity));
-    memcpy (&pong[1], plugin->short_name, slen);
-    if ((sender_address != NULL) && (sender_address_len > 0))
-      memcpy (&((char *) &pong[1])[slen], sender_address, sender_address_len);
-    if (GNUNET_TIME_absolute_get_remaining
-        (session_header->pong_sig_expires).rel_value <
-        PONG_SIGNATURE_LIFETIME.rel_value / 4)
-    {
-      /* create / update cached sig */
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Creating PONG signature to indicate active connection.\n");
-#endif
-      session_header->pong_sig_expires =
-          GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
-      pong->expiration =
-          GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
-      GNUNET_assert (GNUNET_OK ==
-                     GNUNET_CRYPTO_rsa_sign (my_private_key, &pong->purpose,
-                                             &session_header->pong_signature));
-    }
-    else
-    {
-      pong->expiration =
-          GNUNET_TIME_absolute_hton (session_header->pong_sig_expires);
-    }
-    memcpy (&pong->signature, &session_header->pong_signature,
-            sizeof (struct GNUNET_CRYPTO_RsaSignature));
-
-
-  }
-  else
-  {
-    /* peer wants to confirm that this is one of our addresses */
-    addr += slen;
-    alen -= slen;
-    if (GNUNET_OK != plugin->api->check_address (plugin->api->cls, addr, alen))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  _
-                  ("Not confirming PING with address `%s' since I cannot 
confirm having this address.\n"),
-                  a2s (plugin->short_name, addr, alen));
-      return GNUNET_NO;
-    }
-    oal = plugin->addresses;
-    while (NULL != oal)
-    {
-      if ((oal->addrlen == alen) && (0 == memcmp (addr, &oal[1], alen)))
-        break;
-      oal = oal->next;
-    }
-    pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen);
-    pong->header.size =
-        htons (sizeof (struct TransportPongMessage) + alen + slen);
-    pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
-    pong->purpose.size =
-        htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
-               sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-               sizeof (struct GNUNET_PeerIdentity) + alen + slen);
-    pong->purpose.purpose = htonl 
(GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
-    pong->challenge = ping->challenge;
-    pong->addrlen = htonl (alen + slen);
-    memcpy (&pong->pid, &my_identity, sizeof (struct GNUNET_PeerIdentity));
-    memcpy (&pong[1], plugin->short_name, slen);
-    memcpy (&((char *) &pong[1])[slen], addr, alen);
-    if ((oal != NULL) &&
-        (GNUNET_TIME_absolute_get_remaining (oal->pong_sig_expires).rel_value <
-         PONG_SIGNATURE_LIFETIME.rel_value / 4))
-    {
-      /* create / update cached sig */
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Creating PONG signature to indicate ownership.\n");
-#endif
-      oal->pong_sig_expires =
-          GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
-      pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
-      GNUNET_assert (GNUNET_OK ==
-                     GNUNET_CRYPTO_rsa_sign (my_private_key, &pong->purpose,
-                                             &oal->pong_signature));
-      memcpy (&pong->signature, &oal->pong_signature,
-              sizeof (struct GNUNET_CRYPTO_RsaSignature));
-    }
-    else if (oal == NULL)
-    {
-      /* not using cache (typically DV-only) */
-      pong->expiration =
-          GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute
-                                     (PONG_SIGNATURE_LIFETIME));
-      GNUNET_assert (GNUNET_OK ==
-                     GNUNET_CRYPTO_rsa_sign (my_private_key, &pong->purpose,
-                                             &pong->signature));
-    }
-    else
-    {
-      /* can used cached version */
-      pong->expiration = GNUNET_TIME_absolute_hton (oal->pong_sig_expires);
-      memcpy (&pong->signature, &oal->pong_signature,
-              sizeof (struct GNUNET_CRYPTO_RsaSignature));
-    }
-  }
-  n = find_neighbour (peer);
-  GNUNET_assert (n != NULL);
-  did_pong = GNUNET_NO;
-  /* first try reliable response transmission */
-  rl = n->plugins;
-  while (rl != NULL)
-  {
-    fal = rl->addresses;
-    while (fal != NULL)
-    {
-      if (-1 !=
-          rl->plugin->api->send (rl->plugin->api->cls, peer,
-                                 (const char *) pong, ntohs 
(pong->header.size),
-                                 TRANSPORT_PONG_PRIORITY,
-                                 HELLO_VERIFICATION_TIMEOUT, fal->session,
-                                 fal->addr, fal->addrlen, GNUNET_SYSERR, NULL,
-                                 NULL))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Transmitted PONG to `%s' via reliable mechanism\n",
-                    GNUNET_i2s (peer));
-        /* done! */
-        GNUNET_STATISTICS_update (stats,
-                                  gettext_noop
-                                  ("# PONGs unicast via reliable transport"), 
1,
-                                  GNUNET_NO);
-        GNUNET_free (pong);
-        return GNUNET_OK;
-      }
-      did_pong = GNUNET_YES;
-      fal = fal->next;
-    }
-    rl = rl->next;
-  }
-  /* no reliable method found, do multicast */
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# PONGs multicast to all available addresses"), 
1,
-                            GNUNET_NO);
-  rl = n->plugins;
-  while (rl != NULL)
-  {
-    fal = rl->addresses;
-    while (fal != NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Transmitting PONG to `%s' via unreliable mechanism 
`%s':%s\n",
-                  GNUNET_i2s (peer), a2s (rl->plugin->short_name, fal->addr,
-                                          fal->addrlen),
-                  rl->plugin->short_name);
-      transmit_to_peer (NULL, fal, TRANSPORT_PONG_PRIORITY,
-                        HELLO_VERIFICATION_TIMEOUT, (const char *) pong,
-                        ntohs (pong->header.size), GNUNET_YES, n);
-      did_pong = GNUNET_YES;
-      fal = fal->next;
-    }
-    rl = rl->next;
-  }
-  GNUNET_free (pong);
-  if (GNUNET_YES != did_pong)
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Could not send PONG to `%s': no address available\n"),
-                GNUNET_i2s (peer));
-  return GNUNET_OK;
-}
-
-
-/**
- * Function called by the plugin for each received message.  Update
- * data volumes, possibly notify plugins about reducing the rate at
- * which they read from the socket and generally forward to our
- * receive callback.
- *
- * @param cls the "struct TransportPlugin *" we gave to the plugin
- * @param peer (claimed) identity of the other peer
- * @param message the message, NULL if we only care about
- *                learning about the delay until we should receive again
- * @param ats_data information for automatic transport selection
- * @param ats_count number of elements in ats not including 0-terminator
- * @param session identifier used for this session (can be NULL)
- * @param sender_address binary address of the sender (if observed)
- * @param sender_address_len number of bytes in sender_address
- * @return how long in ms the plugin should wait until receiving more data
- *         (plugins that do not support this, can ignore the return value)
- */
-static struct GNUNET_TIME_Relative
-plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
-                    const struct GNUNET_MessageHeader *message,
-                    const struct GNUNET_TRANSPORT_ATS_Information *ats_data,
-                    uint32_t ats_count, struct Session *session,
-                    const char *sender_address, uint16_t sender_address_len)
-{
-  struct TransportPlugin *plugin = cls;
-  struct ReadyList *service_context;
-  struct ForeignAddressList *peer_address;
-  uint16_t msize;
-  struct NeighbourMapEntry *n;
-  struct GNUNET_TIME_Relative ret;
-  uint32_t distance;
-  int c;
-
-  if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    /* refuse to receive from myself */
-    GNUNET_break (0);
-    return GNUNET_TIME_UNIT_FOREVER_REL;
-  }
-  if (is_blacklisted (peer, plugin))
-    return GNUNET_TIME_UNIT_FOREVER_REL;
-  n = find_neighbour (peer);
-  if (n == NULL)
-    n = setup_new_neighbour (peer, GNUNET_YES);
-  service_context = n->plugins;
-  while ((service_context != NULL) && (plugin != service_context->plugin))
-    service_context = service_context->next;
-  GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
-  peer_address = NULL;
-  distance = 1;
-
-  for (c = 0; c < ats_count; c++)
-    if (ntohl (ats_data[c].type) == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
-      distance = ntohl (ats_data[c].value);
-
-
-  if (message != NULL)
-  {
-    if ((session != NULL) || (sender_address != NULL))
-      peer_address =
-          add_peer_address (n, plugin->short_name, session, sender_address,
-                            sender_address_len);
-    if (peer_address != NULL)
-    {
-      update_addr_ats (peer_address, ats_data, ats_count);
-      update_addr_value (peer_address, distance,
-                         GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
-
-      peer_address->distance = distance;
-      if (GNUNET_YES == peer_address->validated)
-      {
-        mark_address_connected (peer_address);
-        schedule_next_ping (peer_address);
-      }
-      else
-      {
-#if DEBUG_TRANSPORT
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "New address is unvalidated, trying to validate it now\n");
-#endif
-        if (peer_address->revalidate_task != GNUNET_SCHEDULER_NO_TASK)
-        {
-          GNUNET_SCHEDULER_cancel (peer_address->revalidate_task);
-          peer_address->revalidate_task = GNUNET_SCHEDULER_NO_TASK;
-        }
-        peer_address->revalidate_task =
-            GNUNET_SCHEDULER_add_now (&send_periodic_ping, peer_address);
-
-      }
-      peer_address->timeout =
-          GNUNET_TIME_relative_to_absolute
-          (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-    }
-    /* update traffic received amount ... */
-    msize = ntohs (message->size);
-
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# bytes received from other peers"), msize,
-                              GNUNET_NO);
-    n->distance = distance;
-    n->peer_timeout =
-        GNUNET_TIME_relative_to_absolute
-        (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-    GNUNET_SCHEDULER_cancel (n->timeout_task);
-    n->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
-                                      &neighbour_timeout_task, n);
-    if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
-    {
-      /* dropping message due to frequent inbound volume violations! */
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
-                  _
-                  ("Dropping incoming message due to repeated bandwidth quota 
(%u b/s) violations (total of %u).\n"),
-                  n->in_tracker.available_bytes_per_s__,
-                  n->quota_violation_count);
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# bandwidth quota violations by other 
peers"),
-                                1, GNUNET_NO);
-      return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
-    }
-    if ((ntohs (message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_ATS) &&
-        (ntohs (message->size) ==
-         (sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t))))
-    {
-#if HAVE_LIBGLPK
-      uint32_t value = ntohl (*((uint32_t *) & message[1]));
-
-      //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
"GNUNET_MESSAGE_TYPE_TRANSPORT_ATS: %i \n", value);
-      /* Force ressource and quality update */
-      if ((value == 4) && (ats != NULL))
-        ats_modify_problem_state (ats, ATS_QUALITY_COST_UPDATED);
-      /* Force cost update */
-      if ((value == 3) && (ats != NULL))
-        ats_modify_problem_state (ats, ATS_COST_UPDATED);
-      /* Force quality update */
-      if ((value == 2) && (ats != NULL))
-        ats_modify_problem_state (ats, ATS_QUALITY_UPDATED);
-      /* Force full rebuild */
-      if ((value == 1) && (ats != NULL))
-        ats_modify_problem_state (ats, ATS_MODIFIED);
-#endif
-    }
-
-#if DEBUG_PING_PONG
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received message of type %u and size %u from `%4s', sending 
to all clients.\n",
-                ntohs (message->type), ntohs (message->size),
-                GNUNET_i2s (peer));
-#endif
-    switch (ntohs (message->type))
-    {
-    case GNUNET_MESSAGE_TYPE_HELLO:
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# HELLO messages received from other peers"),
-                                1, GNUNET_NO);
-      process_hello (plugin, message);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
-      handle_ping (plugin, message, peer, session, sender_address,
-                   sender_address_len);
-      if (GNUNET_YES != n->received_pong)
-        transmit_plain_ping (n);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
-      handle_pong (plugin, message, peer, sender_address, sender_address_len);
-      break;
-    case GNUNET_MESSAGE_TYPE_TRANSPORT_ATS:
-      break;
-    default:
-      handle_payload_message (message, n);
-      break;
-    }
-  }
-  ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
-  if (ret.rel_value > 0)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Throttling read (%llu bytes excess at %u b/s), waiting %llu 
ms before reading more.\n",
-                (unsigned long long) n->
-                in_tracker.consumption_since_last_update__,
-                (unsigned int) n->in_tracker.available_bytes_per_s__,
-                (unsigned long long) ret.rel_value);
-#endif
-    GNUNET_STATISTICS_update (stats, gettext_noop ("# ms throttling 
suggested"),
-                              (int64_t) ret.rel_value, GNUNET_NO);
-  }
-  return ret;
-}
-
-
-static int
-notify_client_about_neighbour (void *cls, const GNUNET_HashCode * key,
-                               void *value)
-{
-  struct TransportClient *c = cls;
-  struct NeighbourMapEntry *n = value;
-  struct ConnectInfoMessage *cim;
-  uint32_t ats_count;
-  size_t size;
-
-  if (GNUNET_YES != n->received_pong)
-    return GNUNET_OK;
-
-  ats_count = 2;
-  size =
-      sizeof (struct ConnectInfoMessage) +
-      ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
-  GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
-  cim = GNUNET_malloc (size);
-  cim->header.size = htons (size);
-  cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
-  cim->ats_count = htonl (ats_count);
-  (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
-  (&(cim->ats))[2].value = htonl (0);
-  if (GNUNET_YES == n->received_pong)
-  {
-    (&cim->ats)[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
-    (&cim->ats)[0].value = htonl (n->distance);
-    (&cim->ats)[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
-    (&cim->ats)[1].value = htonl ((uint32_t) n->latency.rel_value);
-    cim->id = n->id;
-    transmit_to_client (c, &cim->header, GNUNET_NO);
-  }
-  GNUNET_free (cim);
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle START-message.  This is the first message sent to us
- * by any client which causes us to add it to our list.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_start (void *cls, struct GNUNET_SERVER_Client *client,
-              const struct GNUNET_MessageHeader *message)
-{
-  const struct StartMessage *start;
-  struct TransportClient *c;
-
-  start = (const struct StartMessage *) message;
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' request from client\n",
-              "START");
-#endif
-  c = clients;
-  while (c != NULL)
-  {
-    if (c->client == client)
-    {
-      /* client already on our list! */
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    c = c->next;
-  }
-  if ((GNUNET_NO != ntohl (start->do_check)) &&
-      (0 !=
-       memcmp (&start->self, &my_identity,
-               sizeof (struct GNUNET_PeerIdentity))))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("Rejecting control connection from peer `%s', which is not 
me!\n"),
-                GNUNET_i2s (&start->self));
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  c = GNUNET_malloc (sizeof (struct TransportClient));
-  c->next = clients;
-  clients = c;
-  c->client = client;
-  if (our_hello != NULL)
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending our own `%s' to new 
client\n",
-                "HELLO");
-#endif
-    transmit_to_client (c, (const struct GNUNET_MessageHeader *) our_hello,
-                        GNUNET_NO);
-    /* tell new client about all existing connections */
-    GNUNET_CONTAINER_multihashmap_iterate (neighbours,
-                                           &notify_client_about_neighbour, c);
-  }
-  else
-  {
-#if DEBUG_TRANSPORT_HELLO
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No HELLO created yet, will transmit HELLO to client 
later!\n");
-#endif
-    refresh_hello ();
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handle HELLO-message.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_hello (void *cls, struct GNUNET_SERVER_Client *client,
-              const struct GNUNET_MessageHeader *message)
-{
-  int ret;
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# HELLOs received from clients"), 1,
-                            GNUNET_NO);
-  ret = process_hello (NULL, message);
-  GNUNET_SERVER_receive_done (client, ret);
-}
-
-
-/**
- * Closure for 'transmit_client_message'; followed by
- * 'msize' bytes of the actual message.
- */
-struct TransmitClientMessageContext
-{
-  /**
-   * Client on whom's behalf we are sending.
-   */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Timeout for the transmission.
-   */
-  struct GNUNET_TIME_Absolute timeout;
-
-  /**
-   * Message priority.
-   */
-  uint32_t priority;
-
-  /**
-   * Size of the message in bytes.
-   */
-  uint16_t msize;
-};
-
-
-/**
- * Schedule transmission of a message we got from a client to a peer.
- *
- * @param cls the 'struct TransmitClientMessageContext*'
- * @param n destination, or NULL on error (in that case, drop the message)
- */
-static void
-transmit_client_message (void *cls, struct NeighbourMapEntry *n)
-{
-  struct TransmitClientMessageContext *tcmc = cls;
-  struct TransportClient *tc;
-
-  tc = clients;
-  while ((tc != NULL) && (tc->client != tcmc->client))
-    tc = tc->next;
-
-  if (n != NULL)
-  {
-    transmit_to_peer (tc, NULL, tcmc->priority,
-                      GNUNET_TIME_absolute_get_remaining (tcmc->timeout),
-                      (char *) &tcmc[1], tcmc->msize, GNUNET_NO, n);
-  }
-  GNUNET_SERVER_receive_done (tcmc->client, GNUNET_OK);
-  GNUNET_SERVER_client_drop (tcmc->client);
-  GNUNET_free (tcmc);
-}
-
-
-/**
- * Handle SEND-message.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_send (void *cls, struct GNUNET_SERVER_Client *client,
-             const struct GNUNET_MessageHeader *message)
-{
-  const struct OutboundMessage *obm;
-  const struct GNUNET_MessageHeader *obmm;
-  struct TransmitClientMessageContext *tcmc;
-  uint16_t size;
-  uint16_t msize;
-
-  size = ntohs (message->size);
-  if (size <
-      sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# payload received for other 
peers"),
-                            size, GNUNET_NO);
-  obm = (const struct OutboundMessage *) message;
-  obmm = (const struct GNUNET_MessageHeader *) &obm[1];
-  msize = size - sizeof (struct OutboundMessage);
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' request from client with target `%4s' and message 
of type %u and size %u\n",
-              "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize);
-#endif
-  tcmc = GNUNET_malloc (sizeof (struct TransmitClientMessageContext) + msize);
-  tcmc->client = client;
-  tcmc->priority = ntohl (obm->priority);
-  tcmc->timeout =
-      GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh
-                                        (obm->timeout));
-  tcmc->msize = msize;
-  /* FIXME: this memcpy can be up to 7% of our total runtime */
-  memcpy (&tcmc[1], obmm, msize);
-  GNUNET_SERVER_client_keep (client);
-  setup_peer_check_blacklist (&obm->peer, GNUNET_YES, &transmit_client_message,
-                              tcmc);
-}
-
-
-/**
- * Handle request connect message
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  const struct TransportRequestConnectMessage *trcm =
-      (const struct TransportRequestConnectMessage *) message;
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop
-                            ("# REQUEST CONNECT messages received"), 1,
-                            GNUNET_NO);
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a request connect message for peer `%s'\n",
-              GNUNET_i2s (&trcm->peer));
-#endif
-  setup_peer_check_blacklist (&trcm->peer, GNUNET_YES, NULL, NULL);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handle SET_QUOTA-message.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_set_quota (void *cls, struct GNUNET_SERVER_Client *client,
-                  const struct GNUNET_MessageHeader *message)
-{
-  const struct QuotaSetMessage *qsm = (const struct QuotaSetMessage *) message;
-  struct NeighbourMapEntry *n;
-
-  GNUNET_STATISTICS_update (stats,
-                            gettext_noop ("# SET QUOTA messages received"), 1,
-                            GNUNET_NO);
-  n = find_neighbour (&qsm->peer);
-  if (n == NULL)
-  {
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop
-                              ("# SET QUOTA messages ignored (no such peer)"),
-                              1, GNUNET_NO);
-    return;
-  }
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' request (new quota %u, old quota %u) from client 
for peer `%4s'\n",
-              "SET_QUOTA", (unsigned int) ntohl (qsm->quota.value__),
-              (unsigned int) n->in_tracker.available_bytes_per_s__,
-              GNUNET_i2s (&qsm->peer));
-#endif
-  GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, qsm->quota);
-  if (0 == ntohl (qsm->quota.value__))
-  {
-#if DEBUG_TRANSPORT
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
-                GNUNET_i2s (&n->id), "SET_QUOTA");
-#endif
-    GNUNET_STATISTICS_update (stats,
-                              gettext_noop ("# disconnects due to quota of 0"),
-                              1, GNUNET_NO);
-    disconnect_neighbour (n, GNUNET_NO);
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Take the given address and append it to the set of results sent back to
- * the client.
- *
- * @param cls the transmission context used ('struct 
GNUNET_SERVER_TransmitContext*')
- * @param address the resolved name, NULL to indicate the last response
- */
-static void
-transmit_address_to_client (void *cls, const char *address)
-{
-  struct GNUNET_SERVER_TransmitContext *tc = cls;
-  size_t slen;
-
-  if (NULL != address)
-  {
-    slen = strlen (address) + 1;
-    GNUNET_SERVER_transmit_context_append_data (tc, address, slen,
-                                                
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
-  }
-  else
-  {
-    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                                
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
-    GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-}
-
-
-/**
- * Handle AddressLookup-message.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_address_lookup (void *cls, struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
-{
-  const struct AddressLookupMessage *alum;
-  struct TransportPlugin *lsPlugin;
-  const char *nameTransport;
-  const char *address;
-  uint16_t size;
-  struct GNUNET_SERVER_TransmitContext *tc;
-  struct GNUNET_TIME_Relative rtimeout;
-  int32_t numeric;
-
-  size = ntohs (message->size);
-  if (size < sizeof (struct AddressLookupMessage))
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  alum = (const struct AddressLookupMessage *) message;
-  uint32_t addressLen = ntohl (alum->addrlen);
-
-  if (size <= sizeof (struct AddressLookupMessage) + addressLen)
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  address = (const char *) &alum[1];
-  nameTransport = (const char *) &address[addressLen];
-  if (nameTransport
-      [size - sizeof (struct AddressLookupMessage) - addressLen - 1] != '\0')
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout);
-  numeric = ntohl (alum->numeric_only);
-  lsPlugin = find_transport (nameTransport);
-  if (NULL == lsPlugin)
-  {
-    tc = GNUNET_SERVER_transmit_context_create (client);
-    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                                
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
-    GNUNET_SERVER_transmit_context_run (tc, rtimeout);
-    return;
-  }
-  GNUNET_SERVER_disable_receive_done_warning (client);
-  tc = GNUNET_SERVER_transmit_context_create (client);
-  lsPlugin->api->address_pretty_printer (lsPlugin->api->cls, nameTransport,
-                                         address, addressLen, numeric, 
rtimeout,
-                                         &transmit_address_to_client, tc);
-}
-
-/**
- * Handle PeerAddressLookupMessage.
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_peer_address_lookup (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  const struct PeerAddressLookupMessage *peer_address_lookup;
-  struct NeighbourMapEntry *neighbor_iterator;
-  struct ReadyList *ready_iterator;
-  struct ForeignAddressList *foreign_address_iterator;
-  struct TransportPlugin *transport_plugin;
-
-  uint16_t size;
-  struct GNUNET_SERVER_TransmitContext *tc;
-  struct GNUNET_TIME_Relative rtimeout;
-  char *addr_buf;
-
-  size = ntohs (message->size);
-  if (size < sizeof (struct PeerAddressLookupMessage))
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  peer_address_lookup = (const struct PeerAddressLookupMessage *) message;
-
-  rtimeout = GNUNET_TIME_relative_ntoh (peer_address_lookup->timeout);
-
-  neighbor_iterator = find_neighbour (&peer_address_lookup->peer);
-
-  /* Found no neighbor matching this peer id (shouldn't be possible, but...) */
-  if (neighbor_iterator == NULL)
-  {
-    GNUNET_break (0);
-    tc = GNUNET_SERVER_transmit_context_create (client);
-    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                                
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
-    GNUNET_SERVER_transmit_context_run (tc, rtimeout);
-    return;
-  }
-
-  ready_iterator = neighbor_iterator->plugins;
-  GNUNET_SERVER_disable_receive_done_warning (client);
-  tc = GNUNET_SERVER_transmit_context_create (client);
-  while (ready_iterator != NULL)
-  {
-    foreign_address_iterator = ready_iterator->addresses;
-    while (foreign_address_iterator != NULL)
-    {
-      transport_plugin = foreign_address_iterator->ready_list->plugin;
-      if (foreign_address_iterator->addr != NULL)
-      {
-        GNUNET_asprintf (&addr_buf, "%s --- %s, %s",
-                         a2s (transport_plugin->short_name,
-                              foreign_address_iterator->addr,
-                              foreign_address_iterator->addrlen),
-                         (foreign_address_iterator->connected ==
-                          GNUNET_YES) ? "CONNECTED" : "DISCONNECTED",
-                         (foreign_address_iterator->validated ==
-                          GNUNET_YES) ? "VALIDATED" : "UNVALIDATED");
-        transmit_address_to_client (tc, addr_buf);
-        GNUNET_free (addr_buf);
-      }
-      else if (foreign_address_iterator->addrlen == 0)
-      {
-        GNUNET_asprintf (&addr_buf, "%s --- %s, %s", "<inbound>",
-                         (foreign_address_iterator->connected ==
-                          GNUNET_YES) ? "CONNECTED" : "DISCONNECTED",
-                         (foreign_address_iterator->validated ==
-                          GNUNET_YES) ? "VALIDATED" : "UNVALIDATED");
-        transmit_address_to_client (tc, addr_buf);
-        GNUNET_free (addr_buf);
-      }
-
-      foreign_address_iterator = foreign_address_iterator->next;
-    }
-    ready_iterator = ready_iterator->next;
-  }
-  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                              
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-
-
-static int
-output_addresses (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct GNUNET_SERVER_TransmitContext *tc = cls;
-  struct NeighbourMapEntry *neighbor_iterator = value;
-  struct ForeignAddressList *foreign_address_iterator;
-  struct TransportPlugin *transport_plugin;
-  struct ReadyList *ready_iterator;
-  char *addr_buf;
-
-  ready_iterator = neighbor_iterator->plugins;
-  while (ready_iterator != NULL)
-  {
-    foreign_address_iterator = ready_iterator->addresses;
-    while (foreign_address_iterator != NULL)
-    {
-      transport_plugin = foreign_address_iterator->ready_list->plugin;
-      if (foreign_address_iterator->addr != NULL)
-      {
-        GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
-                         GNUNET_i2s (&neighbor_iterator->id),
-                         a2s (transport_plugin->short_name,
-                              foreign_address_iterator->addr,
-                              foreign_address_iterator->addrlen),
-                         (foreign_address_iterator->connected ==
-                          GNUNET_YES) ? "CONNECTED" : "DISCONNECTED",
-                         (foreign_address_iterator->validated ==
-                          GNUNET_YES) ? "VALIDATED" : "UNVALIDATED");
-        transmit_address_to_client (tc, addr_buf);
-        GNUNET_free (addr_buf);
-      }
-      else if (foreign_address_iterator->addrlen == 0)
-      {
-        GNUNET_asprintf (&addr_buf, "%s:%s --- %s, %s",
-                         GNUNET_i2s (&neighbor_iterator->id), "<inbound>",
-                         (foreign_address_iterator->connected ==
-                          GNUNET_YES) ? "CONNECTED" : "DISCONNECTED",
-                         (foreign_address_iterator->validated ==
-                          GNUNET_YES) ? "VALIDATED" : "UNVALIDATED");
-        transmit_address_to_client (tc, addr_buf);
-        GNUNET_free (addr_buf);
-      }
-
-      foreign_address_iterator = foreign_address_iterator->next;
-    }
-    ready_iterator = ready_iterator->next;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Handle AddressIterateMessage
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_address_iterate (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_SERVER_TransmitContext *tc;
-  uint16_t size;
-
-  size = ntohs (message->size);
-  if (size < sizeof (struct AddressIterateMessage))
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_SERVER_disable_receive_done_warning (client);
-  tc = GNUNET_SERVER_transmit_context_create (client);
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &output_addresses, tc);
-  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                              
GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-
-static const struct GNUNET_MessageHeader *
-do_get_our_hello ()
-{
-  return (const struct GNUNET_MessageHeader *) our_hello;
-}
-
-
-/**
- * Setup the environment for this plugin.
- */
-static void
-create_environment (struct TransportPlugin *plug)
-{
-  plug->env.cfg = cfg;
-  plug->env.my_identity = &my_identity;
-  plug->env.get_our_hello = &do_get_our_hello;
-  plug->env.cls = plug;
-  plug->env.receive = &plugin_env_receive;
-  plug->env.notify_address = &plugin_env_notify_address;
-  plug->env.session_end = &plugin_env_session_end;
-  plug->env.max_connections = max_connect_per_transport;
-  plug->env.stats = stats;
-}
-
-
-/**
- * Start the specified transport (load the plugin).
- */
-static void
-start_transport (struct GNUNET_SERVER_Handle *server, const char *name)
-{
-  struct TransportPlugin *plug;
-  char *libname;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' transport plugin\n"),
-              name);
-  GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", name);
-  plug = GNUNET_malloc (sizeof (struct TransportPlugin));
-  create_environment (plug);
-  plug->short_name = GNUNET_strdup (name);
-  plug->lib_name = libname;
-  plug->next = plugins;
-  plugins = plug;
-  plug->api = GNUNET_PLUGIN_load (libname, &plug->env);
-  if (plug->api == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Failed to load transport plugin for `%s'\n"), name);
-    GNUNET_free (plug->short_name);
-    plugins = plug->next;
-    GNUNET_free (libname);
-    GNUNET_free (plug);
-  }
-}
-
-
-static int
-null_mq_client_pointers (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct TransportClient *pos = cls;
-  struct NeighbourMapEntry *n = value;
-  struct MessageQueue *mq;
-
-  for (mq = n->messages_head; mq != NULL; mq = mq->next)
-  {
-    if (mq->client == pos)
-      mq->client = NULL;        /* do not use anymore! */
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Called whenever a client is disconnected.  Frees our
- * resources associated with that client.
- *
- * @param cls closure
- * @param client identification of the client
- */
-static void
-client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
-{
-  struct TransportClient *pos;
-  struct TransportClient *prev;
-  struct ClientMessageQueueEntry *mqe;
-  struct Blacklisters *bl;
-  struct BlacklistCheck *bc;
-
-  if (client == NULL)
-    return;
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
-              "Client disconnected, cleaning up.\n");
-#endif
-  /* clean up blacklister */
-  bl = bl_head;
-  while (bl != NULL)
-  {
-    if (bl->client == client)
-    {
-      bc = bc_head;
-      while (bc != NULL)
-      {
-        if (bc->bl_pos == bl)
-        {
-          bc->bl_pos = bl->next;
-          if (bc->th != NULL)
-          {
-            GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
-            bc->th = NULL;
-          }
-          if (bc->task == GNUNET_SCHEDULER_NO_TASK)
-            bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
-          break;
-        }
-        bc = bc->next;
-      }
-      GNUNET_CONTAINER_DLL_remove (bl_head, bl_tail, bl);
-      GNUNET_SERVER_client_drop (bl->client);
-      GNUNET_free (bl);
-      break;
-    }
-    bl = bl->next;
-  }
-  /* clean up 'normal' clients */
-  prev = NULL;
-  pos = clients;
-  while ((pos != NULL) && (pos->client != client))
-  {
-    prev = pos;
-    pos = pos->next;
-  }
-  if (pos == NULL)
-    return;
-  while (NULL != (mqe = pos->message_queue_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (pos->message_queue_head,
-                                 pos->message_queue_tail, mqe);
-    pos->message_count--;
-    GNUNET_free (mqe);
-  }
-  if (NULL != neighbours)
-    GNUNET_CONTAINER_multihashmap_iterate (neighbours, 
&null_mq_client_pointers,
-                                           pos);
-  if (prev == NULL)
-    clients = pos->next;
-  else
-    prev->next = pos->next;
-  if (GNUNET_YES == pos->tcs_pending)
-  {
-    pos->client = NULL;
-    return;
-  }
-  if (pos->th != NULL)
-  {
-    GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
-    pos->th = NULL;
-  }
-  GNUNET_break (0 == pos->message_count);
-  GNUNET_free (pos);
-}
-
-
-static int
-disconnect_all_neighbours (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct NeighbourMapEntry *n = value;
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
-              GNUNET_i2s (&n->id), "SHUTDOWN_TASK");
-#endif
-  disconnect_neighbour (n, GNUNET_NO);
-  return GNUNET_OK;
-}
-
-
-/**
- * Function called when the service shuts down.  Unloads our plugins
- * and cancels pending validations.
- *
- * @param cls closure, unused
- * @param tc task context (unused)
- */
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct TransportPlugin *plug;
-  struct OwnAddressList *al;
-  struct CheckHelloValidatedContext *chvc;
-
-  shutdown_in_progress = GNUNET_YES;
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, 
&disconnect_all_neighbours,
-                                         NULL);
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Transport service is unloading plugins...\n");
-#endif
-  while (NULL != (plug = plugins))
-  {
-    if (plug->address_update_task != GNUNET_SCHEDULER_NO_TASK)
-    {
-      GNUNET_SCHEDULER_cancel (plug->address_update_task);
-      plug->address_update_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-    GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
-    GNUNET_free (plug->lib_name);
-    GNUNET_free (plug->short_name);
-    while (NULL != (al = plug->addresses))
-    {
-      plug->addresses = al->next;
-      GNUNET_free (al);
-    }
-    plugins = plug->next;
-    GNUNET_free (plug);
-  }
-  if (my_private_key != NULL)
-    GNUNET_CRYPTO_rsa_key_free (my_private_key);
-  GNUNET_free_non_null (our_hello);
-
-  GNUNET_CONTAINER_multihashmap_iterate (validation_map, &abort_validation,
-                                         NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (validation_map);
-  validation_map = NULL;
-
-
-  if (ats_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (ats_task);
-    ats_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-#if HAVE_LIBGLPK
-  if (ats != NULL)
-    ats_shutdown (ats);
-#endif
-
-  /* free 'chvc' data structure */
-  while (NULL != (chvc = chvc_head))
-  {
-    chvc_head = chvc->next;
-    if (chvc->piter != NULL)
-    {
-      GNUNET_PEERINFO_iterate_cancel (chvc->piter);
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# outstanding peerinfo iterate requests"), 
-1,
-                                GNUNET_NO);
-      chvc->ve_count--;
-    }
-    else
-      GNUNET_break (0);
-    GNUNET_assert (chvc->ve_count == 0);
-    GNUNET_free (chvc);
-  }
-  chvc_tail = NULL;
-
-  if (stats != NULL)
-  {
-    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-    stats = NULL;
-  }
-  if (peerinfo != NULL)
-  {
-    GNUNET_PEERINFO_disconnect (peerinfo);
-    peerinfo = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != hello_task)
-  {
-    GNUNET_SCHEDULER_cancel (hello_task);
-    hello_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  /* Can we assume those are gone by now, or do we need to clean up
-   * explicitly!? */
-  GNUNET_break (bl_head == NULL);
-  GNUNET_break (bc_head == NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (neighbours);
-  neighbours = NULL;
-}
-
-
-void
-ats_result_cb ()
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS Result callback\n");
-}
-
-
-#if HAVE_LIBGLPK
-struct AtsBuildContext
-{
-  struct ATS_mechanism *mechanisms;
-  struct ATS_peer *peers;
-  int c_peers;
-  int c_mechs;
-};
-
-
-static int
-find_and_count_addresses (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct AtsBuildContext *abc = cls;
-  struct NeighbourMapEntry *next = value;
-  int found_addresses = GNUNET_NO;
-
-  struct ReadyList *r_next = next->plugins;
-
-  while (r_next != NULL)
-  {
-    struct ForeignAddressList *a_next = r_next->addresses;
-
-    while (a_next != NULL)
-    {
-      abc->c_mechs++;
-      found_addresses = GNUNET_YES;
-      a_next = a_next->next;
-    }
-    r_next = r_next->next;
-  }
-  if (found_addresses)
-    abc->c_peers++;
-  return GNUNET_OK;
-}
-
-
-static int
-setup_ats_problem (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct AtsBuildContext *abc = cls;
-  struct NeighbourMapEntry *next = value;
-
-  int found_addresses = GNUNET_NO;
-  struct ReadyList *r_next = next->plugins;
-
-  while (r_next != NULL)
-  {
-    struct ForeignAddressList *a_next = r_next->addresses;
-
-    while (a_next != NULL)
-    {
-      if (found_addresses == GNUNET_NO)
-      {
-        abc->peers[abc->c_peers].peer = next->id;
-        abc->peers[abc->c_peers].m_head = NULL;
-        abc->peers[abc->c_peers].m_tail = NULL;
-        abc->peers[abc->c_peers].f = 1.0 / abc->c_mechs;
-      }
-      abc->mechanisms[abc->c_mechs].addr = a_next;
-      abc->mechanisms[abc->c_mechs].col_index = abc->c_mechs;
-      abc->mechanisms[abc->c_mechs].peer = &abc->peers[abc->c_peers];
-      abc->mechanisms[abc->c_mechs].next = NULL;
-      abc->mechanisms[abc->c_mechs].plugin = r_next->plugin;
-      abc->mechanisms[abc->c_mechs].ressources = a_next->ressources;
-      abc->mechanisms[abc->c_mechs].quality = a_next->quality;
-      GNUNET_CONTAINER_DLL_insert_tail (abc->peers[abc->c_peers].m_head,
-                                        abc->peers[abc->c_peers].m_tail,
-                                        &abc->mechanisms[abc->c_mechs]);
-      found_addresses = GNUNET_YES;
-      abc->c_mechs++;
-      a_next = a_next->next;
-    }
-    r_next = r_next->next;
-  }
-  if (found_addresses == GNUNET_YES)
-    abc->c_peers++;
-  return GNUNET_OK;
-}
-
-
-static void
-create_ats_information (struct ATS_peer **p, int *c_p, struct ATS_mechanism 
**m,
-                        int *c_m)
-{
-  struct AtsBuildContext abc;
-
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "ATS requires clean address information\n");
-#endif
-  abc.c_peers = 0;
-  abc.c_mechs = 0;
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &find_and_count_addresses,
-                                         &abc);
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Found %u peers with % u transport mechanisms\n", c_peers,
-              c_mechs);
-#endif
-
-  if ((abc.c_peers == 0) && (abc.c_mechs == 0))
-  {
-    *p = NULL;
-    (*c_p) = 0;
-    *m = NULL;
-    (*c_m) = 0;
-    return;
-  }
-
-  abc.mechanisms =
-      GNUNET_malloc ((1 + abc.c_mechs) * sizeof (struct ATS_mechanism));
-  abc.peers = GNUNET_malloc ((1 + abc.c_peers) * sizeof (struct ATS_peer));
-  abc.c_mechs = 1;
-  abc.c_peers = 1;
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &setup_ats_problem, &abc);
-  abc.c_mechs--;
-  abc.c_peers--;
-  (*c_m) = abc.c_mechs;
-  (*c_p) = abc.c_peers;
-  (*p) = abc.peers;
-  (*m) = abc.mechanisms;
-}
-
-
-static void
-schedule_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ATS_Handle *ats = (struct ATS_Handle *) cls;
-
-  if (ats == NULL)
-    return;
-
-  ats_task = GNUNET_SCHEDULER_NO_TASK;
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-    return;
-
-  if (shutdown_in_progress == GNUNET_YES)
-    return;
-
-  struct GNUNET_TIME_Relative delta =
-      GNUNET_TIME_absolute_get_difference (last_ats_execution,
-                                           GNUNET_TIME_absolute_get ());
-
-  if (delta.rel_value < ats_minimum_interval.rel_value)
-  {
-#if DEBUG_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_BULK,
-                "Minimum time between cycles not reached\n");
-#endif
-    return;
-  }
-
-#if DEBUG_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Running scheduled calculation\n");
-#endif
-#if HAVE_LIBGLPK
-  ats_calculate_bandwidth_distribution (ats);
-#endif
-  last_ats_execution = GNUNET_TIME_absolute_get ();
-
-  ats_task =
-      GNUNET_SCHEDULER_add_delayed (ats_regular_interval, &schedule_ats, ats);
-}
-#endif
-
-
-struct ForeignAddressList *
-get_preferred_ats_address (struct NeighbourMapEntry *n)
-{
-  // TODO get ATS prefered address
-  return find_ready_address (n);
-}
-
-/**
- * Initiate transport service.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
-    {&handle_start, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)},
-    {&handle_hello, NULL,
-     GNUNET_MESSAGE_TYPE_HELLO, 0},
-    {&handle_send, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
-    {&handle_request_connect, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT,
-     sizeof (struct TransportRequestConnectMessage)},
-    {&handle_set_quota, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, sizeof (struct QuotaSetMessage)},
-    {&handle_address_lookup, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP,
-     0},
-    {&handle_peer_address_lookup, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_PEER_ADDRESS_LOOKUP,
-     0},
-    {&handle_address_iterate, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE,
-     0},
-    {&handle_blacklist_init, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
-     sizeof (struct GNUNET_MessageHeader)},
-    {&handle_blacklist_reply, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY,
-     sizeof (struct BlacklistMessage)},
-    {NULL, NULL, 0, 0}
-  };
-  char *plugs;
-  char *pos;
-  int no_transports;
-  unsigned long long tneigh;
-  char *keyfile;
-
-  shutdown_in_progress = GNUNET_NO;
-  cfg = c;
-  stats = GNUNET_STATISTICS_create ("transport", cfg);
-  validation_map = GNUNET_CONTAINER_multihashmap_create (64);
-  neighbours = GNUNET_CONTAINER_multihashmap_create (256);
-  /* parse configuration */
-  if ((GNUNET_OK !=
-       GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", 
"NEIGHBOUR_LIMIT",
-                                              &tneigh)) ||
-      (GNUNET_OK !=
-       GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
-                                                &keyfile)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("Transport service is lacking key configuration settings.  
Exiting.\n"));
-    GNUNET_SCHEDULER_shutdown ();
-    if (stats != NULL)
-    {
-      GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-      stats = NULL;
-    }
-    GNUNET_CONTAINER_multihashmap_destroy (validation_map);
-    validation_map = NULL;
-    GNUNET_CONTAINER_multihashmap_destroy (neighbours);
-    neighbours = NULL;
-    return;
-  }
-
-  max_connect_per_transport = (uint32_t) tneigh;
-  peerinfo = GNUNET_PEERINFO_connect (cfg);
-  if (peerinfo == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Could not access PEERINFO service.  Exiting.\n"));
-    GNUNET_SCHEDULER_shutdown ();
-    if (stats != NULL)
-    {
-      GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-      stats = NULL;
-    }
-    GNUNET_CONTAINER_multihashmap_destroy (validation_map);
-    validation_map = NULL;
-    GNUNET_CONTAINER_multihashmap_destroy (neighbours);
-    neighbours = NULL;
-    GNUNET_free (keyfile);
-    return;
-  }
-  my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
-  GNUNET_free (keyfile);
-  if (my_private_key == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Transport service could not access hostkey.  Exiting.\n"));
-    GNUNET_SCHEDULER_shutdown ();
-    if (stats != NULL)
-    {
-      GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
-      stats = NULL;
-    }
-    GNUNET_CONTAINER_multihashmap_destroy (validation_map);
-    validation_map = NULL;
-    GNUNET_CONTAINER_multihashmap_destroy (neighbours);
-    neighbours = NULL;
-    return;
-  }
-  GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
-  GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
-                      &my_identity.hashPubKey);
-  /* setup notification */
-  GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
-                                   NULL);
-  /* load plugins... */
-  no_transports = 1;
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (c, "TRANSPORT", "PLUGINS", 
&plugs))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting transport plugins `%s'\n"),
-                plugs);
-    pos = strtok (plugs, " ");
-    while (pos != NULL)
-    {
-      start_transport (server, pos);
-      no_transports = 0;
-      pos = strtok (NULL, " ");
-    }
-    GNUNET_free (plugs);
-  }
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
-                                NULL);
-  if (no_transports)
-    refresh_hello ();
-
-  /* Initializing ATS */
-  int co;
-  char *section;
-  unsigned long long value;
-
-#if HAVE_LIBGLPK
-  double D = 1.0;
-  double U = 1.0;
-  double R = 1.0;
-  int v_b_min = 64000;
-  int v_n_min = 5;
-#endif
-
-  ats_minimum_interval = ATS_MIN_INTERVAL;
-  ats_regular_interval = ATS_EXEC_INTERVAL;
-
-  /* loading cost ressources */
-  for (co = 0; co < available_ressources; co++)
-  {
-    GNUNET_asprintf (&section, "%s_UP", ressources[co].cfg_param);
-    if (GNUNET_CONFIGURATION_have_value (cfg, "transport", section))
-    {
-      if (GNUNET_OK ==
-          GNUNET_CONFIGURATION_get_value_number (cfg, "transport", section,
-                                                 &value))
-      {
-#if DEBUG_ATS
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Found ressource cost: [%s] = %llu\n", section, value);
-#endif
-        ressources[co].c_max = value;
-      }
-    }
-    GNUNET_free (section);
-    GNUNET_asprintf (&section, "%s_DOWN", ressources[co].cfg_param);
-    if (GNUNET_CONFIGURATION_have_value (cfg, "transport", section))
-    {
-      if (GNUNET_OK ==
-          GNUNET_CONFIGURATION_get_value_number (cfg, "transport", section,
-                                                 &value))
-      {
-#if DEBUG_ATS
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Found ressource cost: [%s] = %llu\n", section, value);
-#endif
-        ressources[co].c_min = value;
-      }
-    }
-    GNUNET_free (section);
-  }
-#if HAVE_LIBGLPK
-  ats =
-      ats_init (D, U, R, v_b_min, v_n_min, ATS_MAX_ITERATIONS,
-                ATS_MAX_EXEC_DURATION, &create_ats_information, ats_result_cb);
-  ats_set_logging_options (ats, stats, cfg);
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONFIGURATION_get_value_time (cfg, "transport",
-                                                     "ATS_EXEC_INTERVAL",
-                                                     &ats_regular_interval));
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONFIGURATION_get_value_time (cfg, "transport",
-                                                     "ATS_MIN_INTERVAL",
-                                                     &ats_minimum_interval));
-  if (ats != NULL)
-    ats_task = GNUNET_SCHEDULER_add_now (&schedule_ats, ats);
-#endif
-
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transport service ready.\n"));
-#endif
-  /* If we have a blacklist file, read from it */
-  read_blacklist_file (cfg);
-  /* process client requests */
-  GNUNET_SERVER_add_handlers (server, handlers);
-}
-
-
-/**
- * The main function for the transport service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  a2s (NULL, NULL, 0);          /* make compiler happy */
-  return (GNUNET_OK ==
-          GNUNET_SERVICE_run (argc, argv, "transport",
-                              GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
-}
-
-/* end of gnunet-service-transport.c */

Copied: gnunet/src/transport/gnunet-service-transport.c (from rev 16807, 
gnunet/src/transport/gnunet-service-transport-new.c)
===================================================================
--- gnunet/src/transport/gnunet-service-transport.c                             
(rev 0)
+++ gnunet/src/transport/gnunet-service-transport.c     2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -0,0 +1,492 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010,2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file transport/gnunet-service-transport-new.c
+ * @brief
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_peerinfo_service.h"
+#include "gnunet_ats_service.h"
+#include "gnunet-service-transport.h"
+#include "gnunet-service-transport_blacklist.h"
+#include "gnunet-service-transport_clients.h"
+#include "gnunet-service-transport_hello.h"
+#include "gnunet-service-transport_neighbours.h"
+#include "gnunet-service-transport_plugins.h"
+#include "gnunet-service-transport_validation.h"
+#include "transport.h"
+
+/* globals */
+
+/**
+ * Statistics handle.
+ */
+struct GNUNET_STATISTICS_Handle *GST_stats;
+
+/**
+ * Configuration handle.
+ */
+const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
+
+/**
+ * Configuration handle.
+ */
+struct GNUNET_PeerIdentity GST_my_identity;
+
+/**
+ * Handle to peerinfo service.
+ */
+struct GNUNET_PEERINFO_Handle *GST_peerinfo;
+
+/**
+ * Our public key.
+ */
+struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded GST_my_public_key;
+
+/**
+ * Our private key.
+ */
+struct GNUNET_CRYPTO_RsaPrivateKey *GST_my_private_key;
+
+/**
+ * ATS handle.
+ */
+struct GNUNET_ATS_Handle *GST_ats;
+
+
+/**
+ * Transmit our HELLO message to the given (connected) neighbour.
+ *
+ * @param cls the 'HELLO' message
+ * @param target a connected neighbour
+ * @param ats performance information (unused)
+ * @param ats_count number of records in ats (unused)
+ */
+static void
+transmit_our_hello (void *cls, const struct GNUNET_PeerIdentity *target,
+                    const struct GNUNET_TRANSPORT_ATS_Information *ats,
+                    uint32_t ats_count)
+{
+  const struct GNUNET_MessageHeader *hello = cls;
+
+  GST_neighbours_send (target, (const char *) hello, ntohs (hello->size),
+                       GST_HELLO_ADDRESS_EXPIRATION, NULL, NULL);
+}
+
+
+/**
+ * My HELLO has changed. Tell everyone who should know.
+ *
+ * @param cls unused
+ * @param hello new HELLO
+ */
+static void
+process_hello_update (void *cls, const struct GNUNET_MessageHeader *hello)
+{
+  GST_clients_broadcast (hello, GNUNET_NO);
+  GST_neighbours_iterate (&transmit_our_hello, (void *) hello);
+}
+
+
+/**
+ * Try to initiate a connection to the given peer if the blacklist
+ * allowed it.
+ *
+ * @param cls closure (unused, NULL)
+ * @param peer identity of peer that was tested
+ * @param result GNUNET_OK if the connection is allowed,
+ *               GNUNET_NO if not
+ */
+static void
+try_connect_if_allowed (void *cls, const struct GNUNET_PeerIdentity *peer,
+                        int result)
+{
+  if (GNUNET_OK != result)
+    return;                     /* not allowed */
+  GST_neighbours_try_connect (peer);
+}
+
+
+/**
+ * Function called by the transport for each received message.
+ * This function should also be called with "NULL" for the
+ * message to signal that the other peer disconnected.
+ *
+ * @param cls closure, const char* with the name of the plugin we received the 
message from
+ * @param peer (claimed) identity of the other peer
+ * @param message the message, NULL if we only care about
+ *                learning about the delay until we should receive again -- 
FIXME!
+ * @param ats performance information
+ * @param ats_count number of records in ats
+ * @param session identifier used for this session (NULL for plugins
+ *                that do not offer bi-directional communication to the sender
+ *                using the same "connection")
+ * @param sender_address binary address of the sender (if we established the
+ *                connection or are otherwise sure of it; should be NULL
+ *                for inbound TCP/UDP connections since it it not clear
+ *                that we could establish ourselves a connection to that
+ *                IP address and get the same system)
+ * @param sender_address_len number of bytes in sender_address
+ * @return how long the plugin should wait until receiving more data
+ *         (plugins that do not support this, can ignore the return value)
+ */
+static struct GNUNET_TIME_Relative
+plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
+                             const struct GNUNET_MessageHeader *message,
+                             const struct GNUNET_TRANSPORT_ATS_Information 
*ats,
+                             uint32_t ats_count, struct Session *session,
+                             const char *sender_address,
+                             uint16_t sender_address_len)
+{
+  const char *plugin_name = cls;
+  int do_forward;
+  struct GNUNET_TIME_Relative ret;
+  uint16_t type;
+
+  ret = GNUNET_TIME_UNIT_ZERO;
+  if (NULL != message)
+  {
+    type = ntohs (message->type);
+    switch (type)
+    {
+    case GNUNET_MESSAGE_TYPE_HELLO:
+      GST_validation_handle_hello (message);
+      break;
+    case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+                  "Processing `%s' from `%s'\n", "PING",
+                  (sender_address != NULL) ? GST_plugins_a2s (plugin_name,
+                                                              sender_address,
+                                                              
sender_address_len)
+                  : "<inbound>");
+#endif
+      GST_validation_handle_ping (peer, message, plugin_name, session,
+                                  sender_address, sender_address_len);
+      break;
+    case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+                  "Processing `%s' from `%s'\n", "PONG",
+                  (sender_address != NULL) ? GST_plugins_a2s (plugin_name,
+                                                              sender_address,
+                                                              
sender_address_len)
+                  : "<inbound>");
+#endif
+      GST_validation_handle_pong (peer, message);
+      break;
+    case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT:
+      (void) GST_blacklist_test_allowed (peer, NULL, &try_connect_if_allowed,
+                                         NULL);
+      /* TODO: if 'session != NULL', and timestamp more recent than the
+       * previous one, maybe notify ATS that this is now the preferred
+       * * way to communicate with this peer (other peer switched transport) */
+      break;
+    case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT:
+      /* TODO: do some validation to prevent an attacker from sending
+       * a fake disconnect message... */
+      GST_neighbours_force_disconnect (peer);
+      break;
+    case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE:
+      GST_neighbours_keepalive (peer);
+      break;
+    default:
+      /* should be payload */
+      do_forward = GNUNET_SYSERR;
+      ret =
+          GST_neighbours_calculate_receive_delay (peer,
+                                                  (message ==
+                                                   NULL) ? 0 :
+                                                  ntohs (message->size),
+                                                  &do_forward);
+      if (do_forward == GNUNET_YES)
+      {
+        struct InboundMessage *im;
+        size_t size = sizeof (struct InboundMessage) + ntohs (message->size);
+
+        im = GNUNET_malloc (size);
+        im->header.size = htons (size);
+        im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
+        im->ats_count = htonl (0);
+        memcpy (&(im->peer), peer, sizeof (struct GNUNET_PeerIdentity));
+        memcpy (&im[1], message, ntohs (message->size));
+
+        GST_clients_broadcast ((const struct GNUNET_MessageHeader *) im,
+                               GNUNET_YES);
+
+        GNUNET_free (im);
+      }
+      break;
+    }
+  }
+
+  GNUNET_assert ((ats_count > 0) && (ats != NULL));
+
+  GNUNET_ATS_address_update (GST_ats, peer, GNUNET_TIME_absolute_get (),       
 /* valid at least until right now... */
+                             plugin_name, session, sender_address,
+                             sender_address_len, ats, ats_count);
+
+  return ret;
+}
+
+
+/**
+ * Function that will be called for each address the transport
+ * is aware that it might be reachable under.  Update our HELLO.
+ *
+ * @param cls name of the plugin (const char*)
+ * @param add_remove should the address added (YES) or removed (NO) from the
+ *                   set of valid addresses?
+ * @param addr one of the addresses of the host
+ *        the specific address format depends on the transport
+ * @param addrlen length of the address
+ */
+static void
+plugin_env_address_change_notification (void *cls, int add_remove,
+                                        const void *addr, size_t addrlen)
+{
+  const char *plugin_name = cls;
+
+  GST_hello_modify_addresses (add_remove, plugin_name, addr, addrlen);
+}
+
+
+/**
+ * Function that will be called whenever the plugin internally
+ * cleans up a session pointer and hence the service needs to
+ * discard all of those sessions as well.  Plugins that do not
+ * use sessions can simply omit calling this function and always
+ * use NULL wherever a session pointer is needed.  This function
+ * should be called BEFORE a potential "TransmitContinuation"
+ * from the "TransmitFunction".
+ *
+ * @param cls closure
+ * @param peer which peer was the session for
+ * @param session which session is being destoyed
+ */
+static void
+plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
+                        struct Session *session)
+{
+  GST_neighbours_session_terminated (peer, session);
+}
+
+
+/**
+ * Function called by ATS to notify the callee that the
+ * assigned bandwidth or address for a given peer was changed.  If the
+ * callback is called with address/bandwidth assignments of zero, the
+ * ATS disconnect function will still be called once the disconnect
+ * actually happened.
+ *
+ * @param cls closure
+ * @param peer identity of the peer
+ * @param plugin_name name of the transport plugin, NULL to disconnect
+ * @param session session to use (if available)
+ * @param plugin_addr address to use (if available)
+ * @param plugin_addr_len number of bytes in addr
+ * @param bandwidth assigned outbound bandwidth for the connection
+ */
+static void
+ats_request_address_change (void *cls, const struct GNUNET_PeerIdentity *peer,
+                            const char *plugin_name, struct Session *session,
+                            const void *plugin_addr, size_t plugin_addr_len,
+                            struct GNUNET_BANDWIDTH_Value32NBO bandwidth)
+{
+  GST_neighbours_switch_to_address (peer, plugin_name, plugin_addr,
+                                    plugin_addr_len, session, NULL, 0);
+  GST_neighbours_set_incoming_quota (peer, bandwidth);
+}
+
+
+/**
+ * Function called to notify transport users that another
+ * peer connected to us.
+ *
+ * @param cls closure
+ * @param peer the peer that connected
+ * @param ats performance data
+ * @param ats_count number of entries in ats (excluding 0-termination)
+ */
+static void
+neighbours_connect_notification (void *cls,
+                                 const struct GNUNET_PeerIdentity *peer,
+                                 const struct GNUNET_TRANSPORT_ATS_Information
+                                 *ats, uint32_t ats_count)
+{
+  char buf[sizeof (struct ConnectInfoMessage) +
+           ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)];
+  struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf;
+  struct GNUNET_TRANSPORT_ATS_Information *atsm = &connect_msg->ats;
+
+  connect_msg->header.size = htons (sizeof (buf));
+  connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
+  connect_msg->ats_count = htonl (ats_count);
+  connect_msg->id = *peer;
+  memcpy (&connect_msg->ats, ats,
+          ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
+  atsm[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+  atsm[ats_count].value = htonl (0);
+  GST_clients_broadcast (&connect_msg->header, GNUNET_NO);
+}
+
+
+/**
+ * Function called to notify transport users that another
+ * peer disconnected from us.
+ *
+ * @param cls closure
+ * @param peer the peer that disconnected
+ */
+static void
+neighbours_disconnect_notification (void *cls,
+                                    const struct GNUNET_PeerIdentity *peer)
+{
+  struct DisconnectInfoMessage disconnect_msg;
+
+  disconnect_msg.header.size = htons (sizeof (struct DisconnectInfoMessage));
+  disconnect_msg.header.type = htons 
(GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
+  disconnect_msg.reserved = htonl (0);
+  disconnect_msg.peer = *peer;
+  GST_clients_broadcast (&disconnect_msg.header, GNUNET_NO);
+}
+
+
+/**
+ * Function called when the service shuts down.  Unloads our plugins
+ * and cancels pending validations.
+ *
+ * @param cls closure, unused
+ * @param tc task context (unused)
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GST_validation_stop ();
+  GST_plugins_unload ();
+  GST_neighbours_stop ();
+  GNUNET_ATS_shutdown (GST_ats);
+  GST_ats = NULL;
+  GST_clients_stop ();
+  GST_blacklist_stop ();
+  GST_hello_stop ();
+
+  if (GST_peerinfo != NULL)
+  {
+    GNUNET_PEERINFO_disconnect (GST_peerinfo);
+    GST_peerinfo = NULL;
+  }
+  if (GST_stats != NULL)
+  {
+    GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
+    GST_stats = NULL;
+  }
+  if (GST_my_private_key != NULL)
+  {
+    GNUNET_CRYPTO_rsa_key_free (GST_my_private_key);
+    GST_my_private_key = NULL;
+  }
+}
+
+
+/**
+ * Initiate transport service.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls, struct GNUNET_SERVER_Handle *server,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  char *keyfile;
+
+  /* setup globals */
+  GST_cfg = c;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
+                                               &keyfile))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("Transport service is lacking key configuration settings.  
Exiting.\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GST_my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+  GNUNET_free (keyfile);
+  if (GST_my_private_key == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Transport service could not access hostkey.  Exiting.\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GST_stats = GNUNET_STATISTICS_create ("transport", c);
+  GST_peerinfo = GNUNET_PEERINFO_connect (c);
+  GNUNET_CRYPTO_rsa_key_get_public (GST_my_private_key, &GST_my_public_key);
+  GNUNET_CRYPTO_hash (&GST_my_public_key, sizeof (GST_my_public_key),
+                      &GST_my_identity.hashPubKey);
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
+                                NULL);
+  if (GST_peerinfo == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not access PEERINFO service.  Exiting.\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  /* start subsystems */
+  GST_hello_start (&process_hello_update, NULL);
+  GST_blacklist_start (server);
+  GST_plugins_load (&plugin_env_receive_callback,
+                    &plugin_env_address_change_notification,
+                    &plugin_env_session_end);
+  GST_ats = GNUNET_ATS_init (GST_cfg, &ats_request_address_change, NULL);
+  GST_neighbours_start (NULL, &neighbours_connect_notification,
+                        &neighbours_disconnect_notification);
+  GST_clients_start (server);
+  GST_validation_start ();
+}
+
+
+/**
+ * The main function for the transport service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  return (GNUNET_OK ==
+          GNUNET_SERVICE_run (argc, argv, "transport",
+                              GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
+}
+
+/* end of file gnunet-service-transport-new.c */

Deleted: gnunet/src/transport/gnunet-service-transport_ats.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_ats.c 2011-09-13 12:25:52 UTC 
(rev 16807)
+++ gnunet/src/transport/gnunet-service-transport_ats.c 2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -1,1754 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file transport/gnunet-service-transport_ats.c
- * @brief automatic transport selection
- * @author Matthias Wachs
- *
- */
-
-
-#include "gnunet-service-transport_ats.h"
-#include "gnunet_transport_service.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_container_lib.h"
-
-
-
-
-
-/* LP/MIP problem object */
-
-#if !HAVE_LIBGLPK
-
-#ifndef GLP_PROB_DEFINED
-#define GLP_PROB_DEFINED
-typedef struct
-{
-  double _opaque_prob[100];
-} glp_prob;
-#endif
-
-typedef struct
-{                               /* integer optimizer control parameters */
-  int msg_lev;                  /* message level (see glp_smcp) */
-  int br_tech;                  /* branching technique: */
-#define GLP_BR_FFV         1    /* first fractional variable */
-#define GLP_BR_LFV         2    /* last fractional variable */
-#define GLP_BR_MFV         3    /* most fractional variable */
-#define GLP_BR_DTH         4    /* heuristic by Driebeck and Tomlin */
-#define GLP_BR_PCH         5    /* hybrid pseudocost heuristic */
-  int bt_tech;                  /* backtracking technique: */
-#define GLP_BT_DFS         1    /* depth first search */
-#define GLP_BT_BFS         2    /* breadth first search */
-#define GLP_BT_BLB         3    /* best local bound */
-#define GLP_BT_BPH         4    /* best projection heuristic */
-  double tol_int;               /* mip.tol_int */
-  double tol_obj;               /* mip.tol_obj */
-  int tm_lim;                   /* mip.tm_lim (milliseconds) */
-  int out_frq;                  /* mip.out_frq (milliseconds) */
-  int out_dly;                  /* mip.out_dly (milliseconds) */
-  /* mip.cb_func */
-  void *cb_info;                /* mip.cb_info */
-  int cb_size;                  /* mip.cb_size */
-  int pp_tech;                  /* preprocessing technique: */
-#define GLP_PP_NONE        0    /* disable preprocessing */
-#define GLP_PP_ROOT        1    /* preprocessing only on root level */
-#define GLP_PP_ALL         2    /* preprocessing on all levels */
-  double mip_gap;               /* relative MIP gap tolerance */
-  int mir_cuts;                 /* MIR cuts       (GLP_ON/GLP_OFF) */
-  int gmi_cuts;                 /* Gomory's cuts  (GLP_ON/GLP_OFF) */
-  int cov_cuts;                 /* cover cuts     (GLP_ON/GLP_OFF) */
-  int clq_cuts;                 /* clique cuts    (GLP_ON/GLP_OFF) */
-  int presolve;                 /* enable/disable using MIP presolver */
-  int binarize;                 /* try to binarize integer variables */
-  int fp_heur;                  /* feasibility pump heuristic */
-#if 1                           /* 28/V-2010 */
-  int alien;                    /* use alien solver */
-#endif
-  double foo_bar[29];           /* (reserved) */
-} glp_iocp;
-
-typedef struct
-{                               /* simplex method control parameters */
-  int msg_lev;                  /* message level: */
-#define GLP_MSG_OFF        0    /* no output */
-#define GLP_MSG_ERR        1    /* warning and error messages only */
-#define GLP_MSG_ON         2    /* normal output */
-#define GLP_MSG_ALL        3    /* full output */
-#define GLP_MSG_DBG        4    /* debug output */
-  int meth;                     /* simplex method option: */
-#define GLP_PRIMAL         1    /* use primal simplex */
-#define GLP_DUALP          2    /* use dual; if it fails, use primal */
-#define GLP_DUAL           3    /* use dual simplex */
-  int pricing;                  /* pricing technique: */
-#define GLP_PT_STD      0x11    /* standard (Dantzig rule) */
-#define GLP_PT_PSE      0x22    /* projected steepest edge */
-  int r_test;                   /* ratio test technique: */
-#define GLP_RT_STD      0x11    /* standard (textbook) */
-#define GLP_RT_HAR      0x22    /* two-pass Harris' ratio test */
-  double tol_bnd;               /* spx.tol_bnd */
-  double tol_dj;                /* spx.tol_dj */
-  double tol_piv;               /* spx.tol_piv */
-  double obj_ll;                /* spx.obj_ll */
-  double obj_ul;                /* spx.obj_ul */
-  int it_lim;                   /* spx.it_lim */
-  int tm_lim;                   /* spx.tm_lim (milliseconds) */
-  int out_frq;                  /* spx.out_frq */
-  int out_dly;                  /* spx.out_dly (milliseconds) */
-  int presolve;                 /* enable/disable using LP presolver */
-  double foo_bar[36];           /* (reserved) */
-} glp_smcp;
-
-/* optimization direction flag: */
-#define GLP_MIN            1    /* minimization */
-#define GLP_MAX            2    /* maximization */
-
-/* kind of structural variable: */
-#define GLP_CV             1    /* continuous variable */
-#define GLP_IV             2    /* integer variable */
-#define GLP_BV             3    /* binary variable */
-
-/* type of auxiliary/structural variable: */
-#define GLP_FR             1    /* free variable */
-#define GLP_LO             2    /* variable with lower bound */
-#define GLP_UP             3    /* variable with upper bound */
-#define GLP_DB             4    /* double-bounded variable */
-#define GLP_FX             5    /* fixed variable */
-
-/* solution indicator: */
-#define GLP_SOL            1    /* basic solution */
-#define GLP_IPT            2    /* interior-point solution */
-#define GLP_MIP            3    /* mixed integer solution */
-
-/* solution status: */
-#define GLP_UNDEF          1    /* solution is undefined */
-#define GLP_FEAS           2    /* solution is feasible */
-#define GLP_INFEAS         3    /* solution is infeasible */
-#define GLP_NOFEAS         4    /* no feasible solution exists */
-#define GLP_OPT            5    /* solution is optimal */
-#define GLP_UNBND          6    /* solution is unbounded */
-
-/* return codes: */
-#define GLP_EBADB       0x01    /* invalid basis */
-#define GLP_ESING       0x02    /* singular matrix */
-#define GLP_ECOND       0x03    /* ill-conditioned matrix */
-#define GLP_EBOUND      0x04    /* invalid bounds */
-#define GLP_EFAIL       0x05    /* solver failed */
-#define GLP_EOBJLL      0x06    /* objective lower limit reached */
-#define GLP_EOBJUL      0x07    /* objective upper limit reached */
-#define GLP_EITLIM      0x08    /* iteration limit exceeded */
-#define GLP_ETMLIM      0x09    /* time limit exceeded */
-#define GLP_ENOPFS      0x0A    /* no primal feasible solution */
-#define GLP_ENODFS      0x0B    /* no dual feasible solution */
-#define GLP_EROOT       0x0C    /* root LP optimum not provided */
-#define GLP_ESTOP       0x0D    /* search terminated by application */
-#define GLP_EMIPGAP     0x0E    /* relative mip gap tolerance reached */
-#define GLP_ENOFEAS     0x0F    /* no primal/dual feasible solution */
-#define GLP_ENOCVG      0x10    /* no convergence */
-#define GLP_EINSTAB     0x11    /* numerical instability */
-#define GLP_EDATA       0x12    /* invalid data */
-#define GLP_ERANGE      0x13    /* result out of range */
-
-/* enable/disable flag: */
-#define GLP_ON             1    /* enable something */
-#define GLP_OFF            0    /* disable something */
-
-#endif
-
-/*
- * Wrappers for GLPK Functions
- */
-
-
-void *
-_lp_create_prob (void)
-{
-#if HAVE_LIBGLPK
-  return glp_create_prob ();
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return NULL;
-}
-
-void
-_lp_set_obj_dir (glp_prob *P, int dir)
-{
-#if HAVE_LIBGLPK
-  return glp_set_obj_dir (P, dir);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-void
-_lp_set_prob_name (glp_prob *P, const char *name)
-{
-#if HAVE_LIBGLPK
-  glp_set_prob_name (P, name);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-int
-_lp_add_cols (glp_prob *P, int ncs)
-{
-#if HAVE_LIBGLPK
-  return glp_add_cols (P, ncs);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-int
-_lp_add_rows (glp_prob *P, int nrs)
-{
-#if HAVE_LIBGLPK
-  return glp_add_rows (P, nrs);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-
-void
-_lp_set_row_bnds (glp_prob *P, int i, int type, double lb, double ub)
-{
-#if HAVE_LIBGLPK
-  glp_set_row_bnds (P, i, type, lb, ub);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-void
-_lp_init_smcp (void *parm)
-{
-#if HAVE_LIBGLPK
-  glp_init_smcp (parm);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-void
-_lp_set_col_name (glp_prob *P, int j, const char *name)
-{
-#if HAVE_LIBGLPK
-  glp_set_col_name (P, j, name);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-void
-_lp_set_col_bnds (glp_prob *P, int j, int type, double lb, double ub)
-{
-#if HAVE_LIBGLPK
-  glp_set_col_bnds (P, j, type, lb, ub);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-void
-_lp_set_obj_coef (glp_prob *P, int j, double coef)
-{
-#if HAVE_LIBGLPK
-  glp_set_obj_coef (P, j, coef);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-void
-_lp_delete_prob (void *P)
-{
-#if HAVE_LIBGLPK
-  glp_delete_prob (P);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-static int
-_lp_simplex (glp_prob *P, void *parm)
-{
-#if HAVE_LIBGLPK
-  return glp_simplex (P, parm);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-static void
-_lp_load_matrix (glp_prob *P, int ne, const int ia[], const int ja[],
-                 const double ar[])
-{
-#if HAVE_LIBGLPK
-  glp_load_matrix (P, ne, ia, ja, ar);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-static void
-_lp_set_mat_row (glp_prob *P, int i, int len, const int ind[],
-                 const double val[])
-{
-#if HAVE_LIBGLPK
-  glp_set_mat_row (P, i, len, ind, val);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-static int
-_lp_write_lp (glp_prob *P, const void *parm, const char *fname)
-{
-#if HAVE_LIBGLPK
-  return glp_write_lp (P, parm, fname);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-static void
-_lp_init_iocp (void *parm)
-{
-#if HAVE_LIBGLPK
-  glp_init_iocp (parm);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-static int
-_lp_intopt (glp_prob *P, const void *parm)
-{
-#if HAVE_LIBGLPK
-  return glp_intopt (P, parm);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-static int
-_lp_get_status (glp_prob *P)
-{
-#if HAVE_LIBGLPK
-  return glp_get_status (P);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-static int
-_lp_mip_status (glp_prob *P)
-{
-#if HAVE_LIBGLPK
-  return glp_mip_status (P);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-static void
-_lp_set_col_kind (glp_prob *P, int j, int kind)
-{
-#if HAVE_LIBGLPK
-  glp_set_col_kind (P, j, kind);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-static void
-_lp_free_env (void)
-{
-#if HAVE_LIBGLPK
-  glp_free_env ();
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-}
-
-static const char *
-_lp_get_col_name (glp_prob *P, int j)
-{
-#if HAVE_LIBGLPK
-  return glp_get_col_name (P, j);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return NULL;
-}
-
-static double
-_lp_mip_obj_val (glp_prob *P)
-{
-#if HAVE_LIBGLPK
-  return glp_mip_obj_val (P);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0.0;
-}
-
-
-static double
-_lp_get_col_prim (glp_prob *P, int j)
-{
-#if HAVE_LIBGLPK
-  return glp_get_col_prim (P, j);
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0.0;
-}
-
-static int
-_lp_print_sol (glp_prob *P, const char *fname)
-{
-#if HAVE_LIBGLPK
-#else
-  // Function not implemented
-  GNUNET_break (0);
-#endif
-  return 0;
-}
-
-/*
- * Dummy functions for CFLAGS
- */
-
-static void
-_dummy2 ();
-static void
-_dummy ()
-{
-  return;
-  _lp_get_col_name (NULL, 0);
-  _lp_mip_obj_val (NULL);
-  _lp_get_col_prim (NULL, 0);
-  _lp_set_mat_row (NULL, 0, 0, NULL, NULL);
-  _dummy2 ();
-}
-
-
-
-static void
-_dummy2 ()
-{
-  ats_modify_problem_state (NULL, 0);
-  qm[1].atis_index = 0;
-  _dummy ();
-  int t = ATS_COST_UPDATED + ATS_MODIFIED + ATS_NEW;
-
-  t++;
-}
-
-/*
- * ATS Functions
- */
-
-
-/**
- * Initialize ATS
- * @param cfg configuration handle to retrieve configuration (to be removed)
- * @return
- */
-
-struct ATS_Handle *
-ats_init (double D, double U, double R, int v_b_min, int v_n_min,
-          int max_iterations, struct GNUNET_TIME_Relative max_duration,
-          GNUNET_TRANSPORT_ATS_AddressNotification address_not,
-          GNUNET_TRANSPORT_ATS_ResultCallback res_cb)
-{
-  struct ATS_Handle *ats = NULL;
-
-  ats = GNUNET_malloc (sizeof (struct ATS_Handle));
-
-  ats->prob = NULL;
-
-  ats->addr_notification = address_not;
-  ats->result_cb = res_cb;
-
-  ats->max_iterations = max_iterations;
-  ats->max_exec_duration = max_duration;
-
-  ats->D = D;
-  ats->U = U;
-  ats->R = R;
-  ats->v_b_min = v_b_min;
-  ats->v_n_min = v_n_min;
-  ats->dump_min_peers = 0;
-  ats->dump_min_addr = 0;
-  ats->dump_overwrite = GNUNET_NO;
-  ats->mechanisms = NULL;
-  ats->peers = NULL;
-  ats->successful_executions = 0;
-  ats->invalid_executions = 0;
-
-  return ats;
-}
-
-
-/** solve the bandwidth distribution problem
- * @param max_it maximum iterations
- * @param max_dur maximum duration in ms
- * @param D     weight for diversity
- * @param U weight for utility
- * @param R weight for relativity
- * @param v_b_min minimal bandwidth per peer
- * @param v_n_min minimum number of connections
- * @param stat result struct
- * @return GNUNET_SYSERR if glpk is not available, number of mechanisms used
- */
-int
-ats_create_problem (struct ATS_Handle *ats, struct ATS_internals *stat,
-                    struct ATS_peer *peers, int c_p,
-                    struct ATS_mechanism *mechanisms, int c_m)
-{
-  if ((c_p == 0) || (c_m == 0))
-    return GNUNET_SYSERR;
-
-  ats->prob = _lp_create_prob ();
-
-  int c;
-  int c_c_ressources = available_ressources;
-  int c_q_metrics = available_quality_metrics;
-
-  double M = VERY_BIG_DOUBLE_VALUE;
-  double Q[c_q_metrics + 1];
-
-  for (c = 1; c <= c_q_metrics; c++)
-  {
-    Q[c] = 1;
-  }
-
-  if (ats->v_n_min > c_p)
-    ats->v_n_min = c_p;
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Creating problem with: %i peers, %i mechanisms, %i resource 
entries, %i quality metrics \n",
-              c_p, c_m, c_c_ressources, c_q_metrics);
-#endif
-
-  int size =
-      1 + 3 + 10 * c_m + c_p + (c_q_metrics * c_m) + c_q_metrics +
-      c_c_ressources * c_m;
-  int row_index;
-  int array_index = 1;
-  int *ia = GNUNET_malloc (size * sizeof (int));
-  int *ja = GNUNET_malloc (size * sizeof (int));
-  double *ar = GNUNET_malloc (size * sizeof (double));
-
-  _lp_set_prob_name (ats->prob, "gnunet ats bandwidth distribution");
-  _lp_set_obj_dir (ats->prob, GLP_MAX);
-
-  /* adding columns */
-  char *name;
-
-  _lp_add_cols (ats->prob, 2 * c_m);
-  /* adding b_t cols */
-  for (c = 1; c <= c_m; c++)
-  {
-    GNUNET_asprintf (&name, "p_%s_b%i",
-                     GNUNET_i2s (&(mechanisms[c].peer->peer)), c);
-    _lp_set_col_name (ats->prob, c, name);
-    GNUNET_free (name);
-    _lp_set_col_bnds (ats->prob, c, GLP_LO, 0.0, 0.0);
-    _lp_set_col_kind (ats->prob, c, GLP_CV);
-    _lp_set_obj_coef (ats->prob, c, 0);
-  }
-
-  /* adding n_t cols */
-  for (c = c_m + 1; c <= 2 * c_m; c++)
-  {
-    GNUNET_asprintf (&name, "p_%s_n%i",
-                     GNUNET_i2s (&(mechanisms[c - c_m].peer->peer)), (c - 
c_m));
-    _lp_set_col_name (ats->prob, c, name);
-    GNUNET_free (name);
-    _lp_set_col_bnds (ats->prob, c, GLP_DB, 0.0, 1.0);
-    _lp_set_col_kind (ats->prob, c, GLP_IV);
-    _lp_set_obj_coef (ats->prob, c, 0);
-  }
-
-  /* feasibility constraints */
-  /* Constraint 1: one address per peer */
-  row_index = 1;
-
-  _lp_add_rows (ats->prob, c_p);
-
-  for (c = 1; c <= c_p; c++)
-  {
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-
-    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 1.0, 1.0);
-    struct ATS_mechanism *m = peers[c].m_head;
-
-    while (m != NULL)
-    {
-      ia[array_index] = row_index;
-      ja[array_index] = (c_m + m->col_index);
-      ar[array_index] = 1;
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                  array_index, ia[array_index], ja[array_index],
-                  ar[array_index]);
-#endif
-      array_index++;
-      m = m->next;
-    }
-    row_index++;
-  }
-
-  /* Constraint 2: only active mechanism gets bandwidth assigned */
-  _lp_add_rows (ats->prob, c_m);
-  for (c = 1; c <= c_m; c++)
-  {
-    /* b_t - n_t * M <= 0 */
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-    _lp_set_row_bnds (ats->prob, row_index, GLP_UP, 0.0, 0.0);
-    ia[array_index] = row_index;
-    ja[array_index] = mechanisms[c].col_index;
-    ar[array_index] = 1;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-    ia[array_index] = row_index;
-    ja[array_index] = c_m + mechanisms[c].col_index;
-    ar[array_index] = -M;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-    row_index++;
-  }
-
-  /* Constraint 3: minimum bandwidth */
-  _lp_add_rows (ats->prob, c_m);
-
-  for (c = 1; c <= c_m; c++)
-  {
-    /* b_t - n_t * b_min <= 0 */
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-#if HAVE_LIBGLPK
-    _lp_set_row_bnds (ats->prob, row_index, GLP_LO, 0.0, 0.0);
-#endif
-    ia[array_index] = row_index;
-    ja[array_index] = mechanisms[c].col_index;
-    ar[array_index] = 1;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-    ia[array_index] = row_index;
-    ja[array_index] = c_m + mechanisms[c].col_index;
-    ar[array_index] = -ats->v_b_min;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-    row_index++;
-  }
-  int c2;
-
-  /* Constraint 4: max ressource capacity */
-  /* V cr: bt * ct_r <= cr_max
-   * */
-
-  _lp_add_rows (ats->prob, available_ressources);
-
-  double ct_max = VERY_BIG_DOUBLE_VALUE;
-  double ct_min = 0.0;
-
-  stat->begin_cr = array_index;
-
-  for (c = 0; c < available_ressources; c++)
-  {
-    ct_max = ressources[c].c_max;
-    ct_min = ressources[c].c_min;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] %f..%f\n",
-                row_index, ct_min, ct_max);
-#endif
-#if HAVE_LIBGLPK
-    _lp_set_row_bnds (ats->prob, row_index, GLP_DB, ct_min, ct_max);
-#endif
-    for (c2 = 1; c2 <= c_m; c2++)
-    {
-      double value = 0;
-
-      ia[array_index] = row_index;
-      ja[array_index] = c2;
-      value = mechanisms[c2].ressources[c].c;
-      ar[array_index] = value;
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                  array_index, ia[array_index], ja[array_index],
-                  ar[array_index]);
-#endif
-      array_index++;
-    }
-    row_index++;
-  }
-  stat->end_cr = array_index--;
-
-  /* Constraint 5: min number of connections */
-  _lp_add_rows (ats->prob, 1);
-
-  for (c = 1; c <= c_m; c++)
-  {
-    // b_t - n_t * b_min >= 0
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-    _lp_set_row_bnds (ats->prob, row_index, GLP_LO, ats->v_n_min, 0.0);
-    ia[array_index] = row_index;
-    ja[array_index] = c_m + mechanisms[c].col_index;
-    ar[array_index] = 1;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-  }
-  row_index++;
-
-  // optimisation constraints
-
-  // adding columns
-
-  // Constraint 6: optimize for diversity
-  int col_d;
-
-  col_d = _lp_add_cols (ats->prob, 1);
-
-  _lp_set_col_name (ats->prob, col_d, "d");
-  _lp_set_obj_coef (ats->prob, col_d, ats->D);
-  _lp_set_col_bnds (ats->prob, col_d, GLP_LO, 0.0, 0.0);
-  _lp_add_rows (ats->prob, 1);
-  _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
-
-  stat->col_d = col_d;
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-  for (c = 1; c <= c_m; c++)
-  {
-    ia[array_index] = row_index;
-    ja[array_index] = c_m + mechanisms[c].col_index;
-    ar[array_index] = 1;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-  }
-  ia[array_index] = row_index;
-  ja[array_index] = col_d;
-  ar[array_index] = -1;
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-              array_index, ia[array_index], ja[array_index], ar[array_index]);
-#endif
-  array_index++;
-  row_index++;
-
-  // Constraint 7: optimize for quality
-  int col_qm;
-
-  col_qm = _lp_add_cols (ats->prob, c_q_metrics);
-
-  stat->col_qm = col_qm;
-  //GNUNET_assert (col_qm == (2*c_mechs) + 3 + 1);
-  for (c = 0; c < c_q_metrics; c++)
-  {
-    GNUNET_asprintf (&name, "Q_%s", qm[c].name);
-    _lp_set_col_name (ats->prob, col_qm + c, name);
-    _lp_set_col_bnds (ats->prob, col_qm + c, GLP_LO, 0.0, 0.0);
-    GNUNET_free (name);
-    _lp_set_obj_coef (ats->prob, col_qm + c, Q[c]);
-  }
-
-  _lp_add_rows (ats->prob, available_quality_metrics);
-
-  stat->begin_qm = row_index;
-  for (c = 1; c <= c_q_metrics; c++)
-  {
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-    double value = 1;
-
-    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
-    for (c2 = 1; c2 <= c_m; c2++)
-    {
-      ia[array_index] = row_index;
-      ja[array_index] = c2;
-      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY)
-      {
-        double v0 = 0, v1 = 0, v2 = 0;
-
-        v0 = mechanisms[c2].quality[c - 1].values[0];
-        if (v1 < 1)
-          v0 = 0.1;
-        v1 = mechanisms[c2].quality[c - 1].values[1];
-        if (v1 < 1)
-          v0 = 0.1;
-        v2 = mechanisms[c2].quality[c - 1].values[2];
-        if (v1 < 1)
-          v0 = 0.1;
-        value = 100.0 / ((v0 + 2 * v1 + 3 * v2) / 6.0);
-        value = 1;
-      }
-      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
-      {
-        double v0 = 0, v1 = 0, v2 = 0;
-
-        v0 = mechanisms[c2].quality[c - 1].values[0];
-        if (v0 < 1)
-          v0 = 1;
-        v1 = mechanisms[c2].quality[c - 1].values[1];
-        if (v1 < 1)
-          v1 = 1;
-        v2 = mechanisms[c2].quality[c - 1].values[2];
-        if (v2 < 1)
-          v2 = 1;
-        value = (v0 + 2 * v1 + 3 * v2) / 6.0;
-        if (value >= 1)
-          value = (double) 10 / value;
-        else
-          value = 10;
-      }
-      ar[array_index] = (mechanisms[c2].peer->f) * value;
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: %s [%i,%i]=%f \n",
-                  array_index, qm[c - 1].name, ia[array_index], 
ja[array_index],
-                  ar[array_index]);
-#endif
-      array_index++;
-    }
-    ia[array_index] = row_index;
-    ja[array_index] = col_qm + c - 1;
-    ar[array_index] = -1;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-    row_index++;
-  }
-  stat->end_qm = row_index - 1;
-
-  // Constraint 8: optimize bandwidth utility
-  int col_u;
-
-  col_u = _lp_add_cols (ats->prob, 1);
-
-  _lp_set_col_name (ats->prob, col_u, "u");
-  _lp_set_obj_coef (ats->prob, col_u, ats->U);
-  _lp_set_col_bnds (ats->prob, col_u, GLP_LO, 0.0, 0.0);
-  _lp_add_rows (ats->prob, 1);
-  stat->col_u = col_u;
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-  _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
-  for (c = 1; c <= c_m; c++)
-  {
-    ia[array_index] = row_index;
-    ja[array_index] = c;
-    ar[array_index] = mechanisms[c].peer->f;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-  }
-  ia[array_index] = row_index;
-  ja[array_index] = col_u;
-  ar[array_index] = -1;
-#if VERBOSE_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-              array_index, ia[array_index], ja[array_index], ar[array_index]);
-#endif
-
-  array_index++;
-  row_index++;
-
-  // Constraint 9: optimize relativity
-  int col_r;
-
-  col_r = _lp_add_cols (ats->prob, 1);
-
-  _lp_set_col_name (ats->prob, col_r, "r");
-  _lp_set_obj_coef (ats->prob, col_r, ats->R);
-  _lp_set_col_bnds (ats->prob, col_r, GLP_LO, 0.0, 0.0);
-  _lp_add_rows (ats->prob, c_p);
-
-  stat->col_r = col_r;
-  for (c = 1; c <= c_p; c++)
-  {
-    _lp_set_row_bnds (ats->prob, row_index, GLP_LO, 0.0, 0.0);
-    struct ATS_mechanism *m = peers[c].m_head;
-
-    while (m != NULL)
-    {
-      ia[array_index] = row_index;
-      ja[array_index] = m->col_index;
-      ar[array_index] = 1 / mechanisms[c].peer->f;
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                  array_index, ia[array_index], ja[array_index],
-                  ar[array_index]);
-#endif
-      array_index++;
-      m = m->next;
-    }
-    ia[array_index] = row_index;
-    ja[array_index] = col_r;
-    ar[array_index] = -1;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, ia[array_index], ja[array_index], 
ar[array_index]);
-#endif
-    array_index++;
-    row_index++;
-  }
-
-  /* Loading the matrix */
-  _lp_load_matrix (ats->prob, array_index - 1, ia, ja, ar);
-
-  stat->c_mechs = c_m;
-  stat->c_peers = c_p;
-  stat->solution = 0;
-  stat->valid = GNUNET_YES;
-
-  /* clean up */
-  GNUNET_free (ja);
-  GNUNET_free (ia);
-  GNUNET_free (ar);
-
-  return GNUNET_OK;
-}
-
-
-void
-ats_delete_problem (struct ATS_Handle *ats)
-{
-#if DEBUG_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting problem\n");
-#endif
-  int c;
-
-  for (c = 0; c < (ats->internal).c_mechs; c++)
-    GNUNET_free_non_null (ats->mechanisms[c].rc);
-  if (ats->mechanisms != NULL)
-  {
-    GNUNET_free (ats->mechanisms);
-    ats->mechanisms = NULL;
-  }
-
-  if (ats->peers != NULL)
-  {
-    GNUNET_free (ats->peers);
-    ats->peers = NULL;
-  }
-
-  if (ats->prob != NULL)
-  {
-    _lp_delete_prob (ats->prob);
-    ats->prob = NULL;
-  }
-
-  ats->internal.begin_cr = GNUNET_SYSERR;
-  ats->internal.begin_qm = GNUNET_SYSERR;
-  ats->internal.c_mechs = 0;
-  ats->internal.c_peers = 0;
-  ats->internal.end_cr = GNUNET_SYSERR;
-  ats->internal.end_qm = GNUNET_SYSERR;
-  ats->internal.solution = GNUNET_SYSERR;
-  ats->internal.valid = GNUNET_SYSERR;
-}
-
-void
-ats_modify_problem_state (struct ATS_Handle *ats, enum ATS_problem_state s)
-{
-  if (ats == NULL)
-    return;
-  switch (s)
-  {
-  case ATS_NEW:
-    ats->internal.recreate_problem = GNUNET_NO;
-    ats->internal.modified_quality = GNUNET_NO;
-    ats->internal.modified_resources = GNUNET_NO;
-    break;
-  case ATS_MODIFIED:
-    ats->internal.recreate_problem = GNUNET_YES;
-    break;
-  case ATS_QUALITY_UPDATED:
-    ats->internal.modified_quality = GNUNET_YES;
-    break;
-  case ATS_COST_UPDATED:
-    ats->internal.modified_resources = GNUNET_YES;
-    break;
-  case ATS_QUALITY_COST_UPDATED:
-    ats->internal.modified_resources = GNUNET_YES;
-    ats->internal.modified_quality = GNUNET_YES;
-    break;
-  default:
-    return;
-  }
-
-
-
-}
-
-void
-ats_solve_problem (struct ATS_Handle *ats, unsigned int max_it,
-                   unsigned int max_dur, unsigned int c_peers,
-                   unsigned int c_mechs, struct ATS_internals *stat)
-{
-  int result = GNUNET_SYSERR;
-  int lp_solution = GNUNET_SYSERR;
-  int mlp_solution = GNUNET_SYSERR;
-
-  // Solving simplex
-
-  glp_smcp opt_lp;
-
-  _lp_init_smcp (&opt_lp);
-#if VERBOSE_ATS
-  opt_lp.msg_lev = GLP_MSG_ALL;
-#else
-  opt_lp.msg_lev = GLP_MSG_OFF;
-#endif
-  // setting iteration limit
-  opt_lp.it_lim = max_it;
-  // maximum duration
-  opt_lp.tm_lim = max_dur;
-
-  if (ats->internal.recreate_problem == GNUNET_YES)
-    opt_lp.presolve = GLP_ON;
-
-  result = _lp_simplex (ats->prob, &opt_lp);
-  lp_solution = _lp_get_status (ats->prob);
-
-  if ((result == GLP_ETMLIM) || (result == GLP_EITLIM))
-  {
-    ats->internal.valid = GNUNET_NO;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "ATS exceeded time or iteration limit!\n");
-    return;
-  }
-
-  if (ats_evaluate_results (result, lp_solution, "LP") == GNUNET_YES)
-  {
-    stat->valid = GNUNET_YES;
-  }
-  else
-  {
-    ats->internal.simplex_rerun_required = GNUNET_YES;
-    opt_lp.presolve = GLP_ON;
-    result = _lp_simplex (ats->prob, &opt_lp);
-    lp_solution = _lp_get_status (ats->prob);
-
-    // TODO: Remove if this does not appear until release
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "" "EXECUTED SIMPLEX WITH PRESOLVER! %i \n", lp_solution);
-
-    if (ats_evaluate_results (result, lp_solution, "LP") != GNUNET_YES)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "After execution simplex with presolver: STILL INVALID!\n");
-      char *filename;
-
-      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i_%llu.mlp",
-                       ats->internal.c_peers, ats->internal.c_mechs,
-                       GNUNET_TIME_absolute_get ().abs_value);
-      _lp_write_lp ((void *) ats->prob, NULL, filename);
-      GNUNET_free (filename);
-      stat->valid = GNUNET_NO;
-      ats->internal.recreate_problem = GNUNET_YES;
-      return;
-    }
-    stat->valid = GNUNET_YES;
-  }
-
-  // Solving mlp
-  glp_iocp opt_mlp;
-
-  _lp_init_iocp (&opt_mlp);
-  // maximum duration
-  opt_mlp.tm_lim = max_dur;
-  // output level
-#if VERBOSE_ATS
-  opt_mlp.msg_lev = GLP_MSG_ALL;
-#else
-  opt_mlp.msg_lev = GLP_MSG_OFF;
-#endif
-
-  result = _lp_intopt (ats->prob, &opt_mlp);
-  mlp_solution = _lp_mip_status (ats->prob);
-  stat->solution = mlp_solution;
-
-  if (ats_evaluate_results (result, mlp_solution, "MLP") == GNUNET_YES)
-  {
-    stat->valid = GNUNET_YES;
-  }
-  else
-  {
-    // TODO: Remove if this does not appear until release
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "MLP solution for %i peers, %i mechs is invalid: %i\n",
-                ats->internal.c_peers, ats->internal.c_mechs, mlp_solution);
-    stat->valid = GNUNET_NO;
-  }
-
-#if VERBOSE_ATS
-  if (_lp_get_col_prim (ats->prob, 2 * c_mechs + 1) != 1)
-  {
-    int c;
-
-    for (c = 1; c <= available_quality_metrics; c++)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
-                  _lp_get_col_name (ats->prob, 2 * c_mechs + 3 + c),
-                  _lp_get_col_prim (ats->prob, 2 * c_mechs + 3 + c));
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
-                _lp_get_col_name (ats->prob, 2 * c_mechs + 1),
-                _lp_get_col_prim (ats->prob, 2 * c_mechs + 1));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
-                _lp_get_col_name (ats->prob, 2 * c_mechs + 2),
-                _lp_get_col_prim (ats->prob, 2 * c_mechs + 2));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s %f\n",
-                _lp_get_col_name (ats->prob, 2 * c_mechs + 3),
-                _lp_get_col_prim (ats->prob, 2 * c_mechs + 3));
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "objective value:  %f\n",
-                _lp_mip_obj_val (ats->prob));
-  }
-#endif
-}
-
-
-void
-ats_shutdown (struct ATS_Handle *ats)
-{
-#if DEBUG_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS shutdown\n");
-#endif
-  ats_delete_problem (ats);
-  _lp_free_env ();
-
-  GNUNET_free (ats);
-}
-
-void
-ats_update_problem_qm (struct ATS_Handle *ats)
-{
-  int array_index;
-  int row_index;
-  int c, c2;
-  int c_q_metrics = available_quality_metrics;
-
-  int *ja =
-      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
-                      available_quality_metrics) * sizeof (int));
-  double *ar =
-      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
-                      available_quality_metrics) * sizeof (double));
-#if DEBUG_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating problem quality metrics\n");
-#endif
-  row_index = ats->internal.begin_qm;
-
-  for (c = 1; c <= c_q_metrics; c++)
-  {
-    array_index = 1;
-    double value = 1;
-
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n", row_index);
-#endif
-    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
-    for (c2 = 1; c2 <= ats->internal.c_mechs; c2++)
-    {
-      ja[array_index] = c2;
-      GNUNET_assert (ats->mechanisms[c2].addr != NULL);
-      GNUNET_assert (ats->mechanisms[c2].peer != NULL);
-
-      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY)
-      {
-        double v0 = 0, v1 = 0, v2 = 0;
-
-        v0 = ats->mechanisms[c2].quality[c - 1].values[0];
-        if (v1 < 1)
-          v0 = 0.1;
-        v1 = ats->mechanisms[c2].quality[c - 1].values[1];
-        if (v1 < 1)
-          v0 = 0.1;
-        v2 = ats->mechanisms[c2].quality[c - 1].values[2];
-        if (v1 < 1)
-          v0 = 0.1;
-        value = 100.0 / ((v0 + 2 * v1 + 3 * v2) / 6.0);
-        //value = 1;
-      }
-      if (qm[c - 1].atis_index == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
-      {
-        double v0 = 0, v1 = 0, v2 = 0;
-
-        v0 = ats->mechanisms[c2].quality[c - 1].values[0];
-        if (v0 < 1)
-          v0 = 1;
-        v1 = ats->mechanisms[c2].quality[c - 1].values[1];
-        if (v1 < 1)
-          v1 = 1;
-        v2 = ats->mechanisms[c2].quality[c - 1].values[2];
-        if (v2 < 1)
-          v2 = 1;
-        value = (v0 + 2 * v1 + 3 * v2) / 6.0;
-        if (value >= 1)
-          value = (double) 10 / value;
-        else
-          value = 10;
-      }
-      ar[array_index] = (ats->mechanisms[c2].peer->f) * value;
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: %s [%i,%i]=%f \n",
-                  array_index, qm[c - 1].name, row_index, ja[array_index],
-                  ar[array_index]);
-#endif
-      array_index++;
-    }
-    ja[array_index] = ats->internal.col_qm + c - 1;
-    ar[array_index] = -1;
-
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                array_index, row_index, ja[array_index], ar[array_index]);
-#endif
-    _lp_set_mat_row (ats->prob, row_index, array_index, ja, ar);
-    array_index = 1;
-    row_index++;
-  }
-  GNUNET_free_non_null (ja);
-  GNUNET_free_non_null (ar);
-
-}
-
-
-void
-ats_calculate_bandwidth_distribution (struct ATS_Handle *ats)
-{
-  struct GNUNET_TIME_Absolute start;
-  struct GNUNET_TIME_Relative creation;
-  struct GNUNET_TIME_Relative solving;
-  int c_m;
-  int c_p;
-  char *text = "unmodified";
-
-#if FIXME_WACHS
-  int dur;
-
-  if (INT_MAX < ats->max_exec_duration.rel_value)
-    dur = INT_MAX;
-  else
-    dur = (int) ats->max_exec_duration.rel_value;
-#endif
-
-  ats->internal.simplex_rerun_required = GNUNET_NO;
-  start = GNUNET_TIME_absolute_get ();
-  if ((ats->internal.recreate_problem == GNUNET_YES) || (ats->prob == NULL) ||
-      (ats->internal.valid == GNUNET_NO))
-  {
-    text = "new";
-    ats->internal.recreate_problem = GNUNET_YES;
-    ats_delete_problem (ats);
-    ats->addr_notification (&ats->peers, &c_p, &ats->mechanisms, &c_m);
-#if DEBUG_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Service returned: %i peer, %i mechs\n", c_p, c_m);
-#endif
-    ats_create_problem (ats, &ats->internal, ats->peers, c_p, ats->mechanisms,
-                        c_m);
-
-
-#if DEBUG_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Peers/Addresses were modified... new problem: %i peer, %i 
mechs\n",
-                ats->internal.c_peers, ats->internal.c_mechs);
-#endif
-  }
-
-  else if ((ats->internal.recreate_problem == GNUNET_NO) &&
-           (ats->internal.modified_resources == GNUNET_YES) &&
-           (ats->internal.valid == GNUNET_YES))
-  {
-    text = "modified resources";
-    ats_update_problem_cr (ats);
-  }
-  else if ((ats->internal.recreate_problem == GNUNET_NO) &&
-           (ats->internal.modified_quality == GNUNET_YES) &&
-           (ats->internal.valid == GNUNET_YES))
-  {
-    text = "modified quality";
-    ats_update_problem_qm (ats);
-    //ats_update_problem_qm_TEST ();
-  }
-#if DEBUG_ATS
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Problem is %s\n", text);
-#endif
-
-  creation =
-      GNUNET_TIME_absolute_get_difference (start, GNUNET_TIME_absolute_get ());
-  start = GNUNET_TIME_absolute_get ();
-
-  ats->internal.solution = GLP_UNDEF;
-  if (ats->internal.valid == GNUNET_YES)
-  {
-    ats_solve_problem (ats, ats->max_iterations,
-                       ats->max_exec_duration.rel_value, ats->internal.c_peers,
-                       ats->internal.c_mechs, &ats->internal);
-  }
-  solving =
-      GNUNET_TIME_absolute_get_difference (start, GNUNET_TIME_absolute_get ());
-
-  if (ats->internal.valid == GNUNET_YES)
-  {
-    /* Telling about new distribution */
-    ats->result_cb ();
-
-    int msg_type = GNUNET_ERROR_TYPE_DEBUG;
-
-#if DEBUG_ATS
-    msg_type = GNUNET_ERROR_TYPE_ERROR;
-#endif
-    GNUNET_log (msg_type,
-                "MLP %s: creation time: %llu, execution time: %llu, %i peers, 
%i mechanisms, simplex rerun: %s, solution %s\n",
-                text, creation.rel_value, solving.rel_value,
-                ats->internal.c_peers, ats->internal.c_mechs,
-                (ats->internal.simplex_rerun_required ==
-                 GNUNET_NO) ? "NO" : "YES",
-                (ats->internal.solution == 5) ? "OPTIMAL" : "INVALID");
-    ats->successful_executions++;
-    GNUNET_STATISTICS_set (ats->stats, "# ATS successful executions",
-                           ats->successful_executions, GNUNET_NO);
-
-    if ((ats->internal.recreate_problem == GNUNET_YES) || (ats->prob == NULL))
-      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_NEW, GNUNET_NO);
-    else if ((ats->internal.modified_resources == GNUNET_YES) &&
-             (ats->internal.modified_quality == GNUNET_NO))
-      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_COST_UPDATED,
-                             GNUNET_NO);
-    else if ((ats->internal.modified_resources == GNUNET_NO) &&
-             (ats->internal.modified_quality == GNUNET_YES) &&
-             (ats->internal.simplex_rerun_required == GNUNET_NO))
-      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_QUALITY_UPDATED,
-                             GNUNET_NO);
-    else if ((ats->internal.modified_resources == GNUNET_YES) &&
-             (ats->internal.modified_quality == GNUNET_YES) &&
-             (ats->internal.simplex_rerun_required == GNUNET_NO))
-      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_QUALITY_COST_UPDATED,
-                             GNUNET_NO);
-    else if (ats->internal.simplex_rerun_required == GNUNET_NO)
-      GNUNET_STATISTICS_set (ats->stats, "ATS state", ATS_UNMODIFIED,
-                             GNUNET_NO);
-  }
-  else
-  {
-    if (ats->internal.c_peers != 0)
-    {
-      ats->invalid_executions++;
-      GNUNET_STATISTICS_set (ats->stats, "# ATS invalid executions",
-                             ats->invalid_executions, GNUNET_NO);
-    }
-    else
-    {
-      GNUNET_STATISTICS_set (ats->stats, "# ATS successful executions",
-                             ats->successful_executions, GNUNET_NO);
-    }
-  }
-
-  GNUNET_STATISTICS_set (ats->stats, "ATS duration",
-                         solving.rel_value + creation.rel_value, GNUNET_NO);
-  GNUNET_STATISTICS_set (ats->stats, "ATS mechanisms", ats->internal.c_mechs,
-                         GNUNET_NO);
-  GNUNET_STATISTICS_set (ats->stats, "ATS peers", ats->internal.c_peers,
-                         GNUNET_NO);
-  GNUNET_STATISTICS_set (ats->stats, "ATS solution", ats->internal.solution,
-                         GNUNET_NO);
-  GNUNET_STATISTICS_set (ats->stats, "ATS timestamp", start.abs_value,
-                         GNUNET_NO);
-
-  if ((ats->save_mlp == GNUNET_YES) &&
-      (ats->internal.c_mechs >= ats->dump_min_peers) &&
-      (ats->internal.c_mechs >= ats->dump_min_addr))
-  {
-    char *filename;
-
-    if (ats->dump_overwrite == GNUNET_NO)
-    {
-      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i_%s_%llu.mlp",
-                       ats->internal.c_peers, ats->internal.c_mechs, text,
-                       GNUNET_TIME_absolute_get ().abs_value);
-      _lp_write_lp ((void *) ats->prob, NULL, filename);
-    }
-    else
-    {
-      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i.mlp", ats->internal.c_peers,
-                       ats->internal.c_mechs);
-      _lp_write_lp ((void *) ats->prob, NULL, filename);
-    }
-    GNUNET_free (filename);
-  }
-  if ((ats->save_solution == GNUNET_YES) &&
-      (ats->internal.c_mechs >= ats->dump_min_peers) &&
-      (ats->internal.c_mechs >= ats->dump_min_addr))
-  {
-    char *filename;
-
-    if (ats->dump_overwrite == GNUNET_NO)
-    {
-      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i_%s_%llu.sol",
-                       ats->internal.c_peers, ats->internal.c_mechs, text,
-                       GNUNET_TIME_absolute_get ().abs_value);
-      _lp_print_sol (ats->prob, filename);
-    }
-    else
-    {
-      GNUNET_asprintf (&filename, "ats_mlp_p%i_m%i.sol", ats->internal.c_peers,
-                       ats->internal.c_mechs);
-      _lp_print_sol (ats->prob, filename);
-    }
-    GNUNET_free (filename);
-  }
-
-  ats->internal.recreate_problem = GNUNET_NO;
-  ats->internal.modified_resources = GNUNET_NO;
-  ats->internal.modified_quality = GNUNET_NO;
-}
-
-/**
- * Evaluate the result of the last simplex or mlp solving
- * @param result return value returned by the solver
- * @param solution solution state
- * @param problem mlp or lp
- * @return GNUNET_NO if solution is invalid, GNUNET_YES if solution is
- *      valid
- */
-
-int
-ats_evaluate_results (int result, int solution, char *problem)
-{
-  int cont = GNUNET_NO;
-
-#if DEBUG_ATS || VERBOSE_ATS
-  int error_kind = GNUNET_ERROR_TYPE_DEBUG;
-#endif
-#if VERBOSE_ATS
-  error_kind = GNUNET_ERROR_TYPE_ERROR;
-#endif
-  switch (result)
-  {
-  case GNUNET_SYSERR:          /* GNUNET problem, not GLPK related */
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s, GLPK solving not executed\n", problem);
-#endif
-    break;
-  case GLP_ESTOP:              /* search terminated by application */
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s , Search terminated by application\n", 
problem);
-#endif
-    break;
-  case GLP_EITLIM:             /* iteration limit exceeded */
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s Iteration limit exceeded\n",
-                problem);
-#endif
-    break;
-  case GLP_ETMLIM:             /* time limit exceeded */
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s Time limit exceeded\n", 
problem);
-#endif
-    break;
-  case GLP_ENOPFS:             /* no primal feasible solution */
-  case GLP_ENODFS:             /* no dual feasible solution */
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s No feasible solution\n", problem);
-#endif
-    break;
-  case GLP_EBADB:              /* invalid basis */
-  case GLP_ESING:              /* singular matrix */
-  case GLP_ECOND:              /* ill-conditioned matrix */
-  case GLP_EBOUND:             /* invalid bounds */
-  case GLP_EFAIL:              /* solver failed */
-  case GLP_EOBJLL:             /* objective lower limit reached */
-  case GLP_EOBJUL:             /* objective upper limit reached */
-  case GLP_EROOT:              /* root LP optimum not provided */
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s Invalid Input data: %i\n", problem, result);
-#endif
-    break;
-  case 0:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s Problem has been solved\n", problem);
-#endif
-    break;
-  }
-
-  switch (solution)
-  {
-  case GLP_UNDEF:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s solution is undefined\n", problem);
-#endif
-    break;
-  case GLP_OPT:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s solution is optimal\n", problem);
-#endif
-    cont = GNUNET_YES;
-    break;
-  case GLP_FEAS:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind,
-                "%s solution is %s feasible, however, its optimality (or 
non-optimality) has not been proven\n",
-                problem, (0 == strcmp (problem, "LP") ? "" : "integer"));
-#endif
-    cont = GNUNET_YES;
-    break;
-  case GLP_NOFEAS:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s problem has no %sfeasible solution\n", problem,
-                (0 == strcmp (problem, "LP") ? "" : "integer "));
-#endif
-    break;
-  case GLP_INFEAS:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s problem is infeasible \n", problem);
-#endif
-    break;
-  case GLP_UNBND:
-#if DEBUG_ATS || VERBOSE_ATS
-    GNUNET_log (error_kind, "%s problem is unbounded \n", problem);
-#endif
-  default:
-    break;
-  }
-  return cont;
-}
-
-void
-ats_update_problem_cr (struct ATS_Handle *ats)
-{
-  int array_index;
-  int row_index;
-  int c, c2;
-  double ct_max, ct_min;
-
-  int *ja =
-      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
-                      available_quality_metrics) * sizeof (int));
-  double *ar =
-      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
-                      available_quality_metrics) * sizeof (double));
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating problem quality metrics\n");
-  row_index = ats->internal.begin_cr;
-  array_index = 1;
-
-  for (c = 0; c < available_ressources; c++)
-  {
-    ct_max = ressources[c].c_max;
-    ct_min = ressources[c].c_min;
-#if VERBOSE_ATS
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] %f..%f\n",
-                row_index, ct_min, ct_max);
-#endif
-    _lp_set_row_bnds (ats->prob, row_index, GLP_DB, ct_min, ct_max);
-    for (c2 = 1; c2 <= ats->internal.c_mechs; c2++)
-    {
-      double value = 0;
-
-      GNUNET_assert (ats->mechanisms[c2].addr != NULL);
-      GNUNET_assert (ats->mechanisms[c2].peer != NULL);
-
-      ja[array_index] = c2;
-      value = ats->mechanisms[c2].ressources[c].c;
-      ar[array_index] = value;
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",
-                  array_index, row_index, ja[array_index], ar[array_index]);
-#endif
-      array_index++;
-    }
-    _lp_set_mat_row (ats->prob, row_index, array_index, ja, ar);
-    row_index++;
-  }
-  GNUNET_free_non_null (ja);
-  GNUNET_free_non_null (ar);
-
-}
-
-void
-ats_set_logging_options (struct ATS_Handle *ats,
-                         struct GNUNET_STATISTICS_Handle *stats,
-                         const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  int minimum_addresses;
-  int minimum_peers;
-  int overwrite_dump;
-  int log_solution;
-  int log_problem;
-  unsigned long long value;
-
-  if (ats == NULL)
-    return;
-  log_problem =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "transport", "DUMP_MLP");
-  log_solution =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "transport", "DUMP_SOLUTION");
-  overwrite_dump =
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "transport", 
"DUMP_OVERWRITE");
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "transport", 
"DUMP_MIN_PEERS",
-                                             &value))
-    minimum_peers = (int) value;
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "transport", 
"DUMP_MIN_ADDRS",
-                                             &value))
-    minimum_addresses = (int) value;
-
-
-  ats->stats = stats;
-  ats->dump_min_addr = minimum_addresses;
-  ats->dump_min_peers = minimum_peers;
-  ats->dump_overwrite = overwrite_dump;
-  ats->save_mlp = log_problem;
-  ats->save_solution = log_solution;
-}
-
-#if 0
-static void
-ats_update_problem_qm_TEST ()
-{
-  int row_index;
-  int c int c2;
-  int c_old;
-  int changed = 0;
-
-  int old_ja[ats->internal.c_mechs + 2];
-  double old_ar[ats->internal.c_mechs + 2];
-
-  int *ja =
-      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
-                      available_quality_metrics) * sizeof (int));
-  double *ar =
-      GNUNET_malloc ((1 + ats->internal.c_mechs * 2 + 3 +
-                      available_quality_metrics) * sizeof (double));
-#if DEBUG_ATS
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Updating problem quality metrics TEST\n");
-#endif
-  if (ats->internal.begin_qm > 0)
-    row_index = ats->internal.begin_qm;
-  else
-    return;
-  for (c = 0; c < available_quality_metrics; c++)
-  {
-    c_old = _lp_get_mat_row (ats->prob, row_index, old_ja, old_ar);
-    _lp_set_row_bnds (ats->prob, row_index, GLP_FX, 0.0, 0.0);
-    for (c2 = 1; c2 <= c_old; c2++)
-    {
-      ja[c2] = old_ja[c2];
-      if ((changed < 3) && (c2 > 2) && (old_ar[c2] != -1))
-      {
-        ar[c2] = old_ar[c2] + 5 - changed;
-        changed++;
-      }
-      else
-        ar[c2] = old_ar[c2];
-#if VERBOSE_ATS
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "[index]=[%i]: old [%i,%i]=%f  new [%i,%i]=%f\n", c2,
-                  row_index, old_ja[c2], old_ar[c2], row_index, ja[c2], 
ar[c2]);
-#endif
-    }
-    _lp_set_mat_row (ats->prob, row_index, c_old, ja, ar);
-    row_index++;
-  }
-  GNUNET_free_non_null (ja);
-  GNUNET_free_non_null (ar);
-}
-#endif
-
-
-
-/* end of transport_ats.c */

Deleted: gnunet/src/transport/gnunet-service-transport_ats.h
===================================================================
--- gnunet/src/transport/gnunet-service-transport_ats.h 2011-09-13 12:25:52 UTC 
(rev 16807)
+++ gnunet/src/transport/gnunet-service-transport_ats.h 2011-09-13 12:40:14 UTC 
(rev 16808)
@@ -1,496 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2010,2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file transport/gnunet-service-transport_ats.h
- * @brief common internal definitions for transport service's ats code
- * @author Matthias Wachs
- */
-#ifndef GNUNET_SERVICE_TRANSPORT_ATS_H
-#define GNUNET_SERVICE_TRANSPORT_ATS_H
-
-#include "platform.h"
-#include "gnunet_constants.h"
-#include "gnunet_scheduler_lib.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet_time_lib.h"
-
-
-#if HAVE_LIBGLPK
-#include <glpk.h>
-#endif
-
-/*
- *  ATS defines
- */
-
-#define DEBUG_ATS GNUNET_NO
-#define VERBOSE_ATS GNUNET_NO
-
-
-/* Minimum time between to calculations*/
-#define ATS_MIN_INTERVAL  
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15)
-#define ATS_EXEC_INTERVAL 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
-#define ATS_MAX_EXEC_DURATION 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
-#define ATS_MAX_ITERATIONS INT_MAX
-
-#define ATS_DEFAULT_D 1.0
-#define ATS_DEFAULT_U 1.0
-#define ATS_DEFAULT_R 1.0
-#define ATS_DEFAULT_B_MIN 64000
-#define ATS_DEFAULT_N_MIN 10
-
-#define VERY_BIG_DOUBLE_VALUE 100000000000LL
-
-
-/*
- * Callback Functions
- */
-
-struct ATS_mechanism;
-struct ATS_peer;
-
-typedef void (*GNUNET_TRANSPORT_ATS_AddressNotification) (struct ATS_peer **
-                                                          peers, int *c_p,
-                                                          struct ATS_mechanism
-                                                          ** mechanisms,
-                                                          int *c_m);
-
-typedef void (*GNUNET_TRANSPORT_ATS_ResultCallback) (void);
-
-enum ATS_problem_state
-{
-  /**
-   * Problem is new
-   */
-  ATS_NEW = 0,
-
-  /**
-   * Problem quality properties were modified
-   */
-  ATS_QUALITY_UPDATED = 1,
-
-  /**
-   * Problem ressource properties were modified
-   */
-  ATS_COST_UPDATED = 2,
-
-  /**
-   * Problem quality and ressource properties were modified
-   */
-  ATS_QUALITY_COST_UPDATED = 3,
-
-  /**
-   * Problem is modified and needs to be completely recalculated
-   * due to e.g. connecting or disconnecting peers
-   */
-  ATS_MODIFIED = 4,
-
-  /**
-   * Problem is unmodified
-   */
-  ATS_UNMODIFIED = 8
-};
-
-/*
-*  ATS data structures
-*/
-
-struct ATS_internals
-{
-    /**
-     * result of last GLPK run
-     * 5 == OPTIMAL
-     */
-  int solution;
-
-    /**
-     * Ressource costs or quality metrics changed
-     * update problem before solving
-     */
-  int modified_resources;
-
-    /**
-     * Ressource costs or quality metrics changed, update matrix
-     * update problem before solving
-     */
-  int modified_quality;
-
-    /**
-     * Peers have connected or disconnected
-     * problem has to be recreated
-     */
-  int recreate_problem;
-
-    /**
-     * Was the available basis invalid and we needed to rerun simplex?
-     */
-  int simplex_rerun_required;
-
-    /**
-     * is problem currently valid and can it be solved
-     */
-  int valid;
-
-    /**
-     * Number of transport mechanisms in the problem
-     */
-  int c_mechs;
-
-    /**
-     * Number of transport mechanisms in the problem
-     */
-  int c_peers;
-
-    /**
-     * row index where quality related rows start
-     */
-  int begin_qm;
-
-    /**
-     * row index where quality related rows end
-     */
-  int end_qm;
-
-    /**
-     * row index where ressource cost related rows start
-     */
-  int begin_cr;
-
-    /**
-     * row index where ressource cost related rows end
-     */
-  int end_cr;
-
-    /**
-     * column index for objective function value d
-     */
-  int col_d;
-
-    /**
-     * column index for objective function value u
-     */
-  int col_u;
-
-    /**
-     * column index for objective function value r
-     */
-  int col_r;
-
-    /**
-     * column index for objective function value quality metrics
-     */
-  int col_qm;
-
-    /**
-     * column index for objective function value cost ressources
-     */
-  int col_cr;
-};
-
-struct ATS_Handle
-{
-  /*
-   *  Callback functions
-   */
-
-  GNUNET_TRANSPORT_ATS_AddressNotification addr_notification;
-
-  GNUNET_TRANSPORT_ATS_ResultCallback result_cb;
-
-
-    /**
-     * Statistics handle
-     */
-  struct GNUNET_STATISTICS_Handle *stats;
-
-    /**
-     * Maximum execution time per calculation
-     */
-  struct GNUNET_TIME_Relative max_exec_duration;
-
-    /**
-     * GLPK (MLP) problem object
-     */
-#if HAVE_LIBGLPK
-
-  glp_prob *prob;
-#else
-  void *prob;
-#endif
-
-    /**
-     * Internal information state of the GLPK problem
-     */
-  struct ATS_internals internal;
-
-    /**
-     * mechanisms used in current problem
-     * needed for problem modification
-     */
-  struct ATS_mechanism *mechanisms;
-
-    /**
-     * peers used in current problem
-     * needed for problem modification
-     */
-  struct ATS_peer *peers;
-
-    /**
-     * State of the MLP problem
-     * value of ATS_problem_state
-     *
-     */
-  int state;
-
-    /**
-     * number of successful executions
-     */
-  int successful_executions;
-
-    /**
-     * number with an invalid result
-     */
-  int invalid_executions;
-
-    /**
-     * Maximum number of LP iterations per calculation
-     */
-  int max_iterations;
-
-
-  /*
-   * ATS configuration
-   */
-
-
-    /**
-     * Diversity weight
-     */
-  double D;
-
-    /**
-     * Utility weight
-     */
-  double U;
-
-    /**
-     * Relativity weight
-     */
-  double R;
-
-    /**
-     * Minimum bandwidth per peer
-     */
-  int v_b_min;
-
-    /**
-     * Minimum number of connections per peer
-     */
-  int v_n_min;
-
-
-    /**
-     * Logging related variables
-     */
-
-
-    /**
-     * Dump problem to a file?
-     */
-  int save_mlp;
-
-    /**
-     * Dump solution to a file
-     */
-  int save_solution;
-
-    /**
-     * Dump solution when minimum peers:
-     */
-  int dump_min_peers;
-
-    /**
-     * Dump solution when minimum addresses:
-     */
-  int dump_min_addr;
-
-    /**
-     * Dump solution overwrite file:
-     */
-  int dump_overwrite;
-};
-
-struct ATS_mechanism
-{
-  struct ATS_mechanism *prev;
-  struct ATS_mechanism *next;
-  struct ForeignAddressList *addr;
-  struct ATS_quality_entry *quality;
-  struct ATS_ressource_entry *ressources;
-  struct TransportPlugin *plugin;
-  struct ATS_peer *peer;
-  int col_index;
-  int id;
-  struct ATS_ressource_cost *rc;
-};
-
-struct ATS_peer
-{
-  struct GNUNET_PeerIdentity peer;
-
-  struct ATS_mechanism *m_head;
-  struct ATS_mechanism *m_tail;
-
-  /* preference value f */
-  double f;
-
-  //struct NeighbourList * n;
-};
-
-struct ATS_ressource
-{
-  /* index in ressources array */
-  int index;
-  /* depending ATSi parameter to calculcate limits */
-  int atis_index;
-  /* cfg option to load limits */
-  char *cfg_param;
-  /* lower bound */
-  double c_min;
-  /* upper bound */
-  double c_max;
-
-  /* cofficients for the specific plugins */
-  double c_unix;
-  double c_tcp;
-  double c_udp;
-  double c_http;
-  double c_https;
-  double c_wlan;
-  double c_default;
-};
-
-
-struct ATS_ressource_entry
-{
-  /* index in ressources array */
-  int index;
-  /* depending ATSi parameter to calculcate limits */
-  int atis_index;
-  /* lower bound */
-  double c;
-};
-
-
-struct ATS_quality_metric
-{
-  int index;
-  int atis_index;
-  char *name;
-};
-
-struct ATS_quality_entry
-{
-  int index;
-  int atsi_index;
-  uint32_t values[3];
-  int current;
-};
-
-/*
- * ATS ressources
- */
-
-
-static struct ATS_ressource ressources[] = {
-  /* FIXME: the coefficients for the specific plugins */
-  {1, 7, "LAN_BW_LIMIT", 0, VERY_BIG_DOUBLE_VALUE, 0, 1, 1, 2, 2, 1, 3},
-  {2, 7, "WAN_BW_LIMIT", 0, VERY_BIG_DOUBLE_VALUE, 0, 1, 1, 2, 2, 2, 3},
-  {3, 4, "WLAN_ENERGY_LIMIT", 0, VERY_BIG_DOUBLE_VALUE, 0, 0, 0, 0, 0, 2, 1}
-/*
-    {4, 4, "COST_ENERGY_CONSUMPTION", VERY_BIG_DOUBLE_VALUE},
-    {5, 5, "COST_CONNECT", VERY_BIG_DOUBLE_VALUE},
-    {6, 6, "COST_BANDWITH_AVAILABLE", VERY_BIG_DOUBLE_VALUE},
-    {7, 7, "COST_NETWORK_OVERHEAD", VERY_BIG_DOUBLE_VALUE},*/
-};
-
-#define available_ressources (sizeof(ressources)/sizeof(*ressources))
-
-/*
- * ATS quality metrics
- */
-
-static struct ATS_quality_metric qm[] = {
-  {1, 1028, "QUALITY_NET_DISTANCE"},
-  {2, 1034, "QUALITY_NET_DELAY"},
-};
-
-#define available_quality_metrics (sizeof(qm)/sizeof(*qm))
-
-
-/*
- * ATS functions
- */
-struct ATS_Handle *
-ats_init (double D, double U, double R, int v_b_min, int v_n_min,
-          int max_iterations, struct GNUNET_TIME_Relative max_duration,
-          GNUNET_TRANSPORT_ATS_AddressNotification address_not,
-          GNUNET_TRANSPORT_ATS_ResultCallback res_cb);
-
-void
-ats_shutdown (struct ATS_Handle *ats);
-
-void
-ats_delete_problem (struct ATS_Handle *ats);
-
-int
-ats_create_problem (struct ATS_Handle *ats, struct ATS_internals *stat,
-                    struct ATS_peer *peers, int c_p,
-                    struct ATS_mechanism *mechanisms, int c_m);
-
-void
-ats_modify_problem_state (struct ATS_Handle *ats, enum ATS_problem_state s);
-
-void
-ats_calculate_bandwidth_distribution (struct ATS_Handle *ats);
-
-void
-ats_solve_problem (struct ATS_Handle *ats, unsigned int max_it,
-                   unsigned int max_dur, unsigned int c_peers,
-                   unsigned int c_mechs, struct ATS_internals *stat);
-
-int
-ats_evaluate_results (int result, int solution, char *problem);
-
-void
-ats_update_problem_qm (struct ATS_Handle *ats);
-
-void
-ats_update_problem_cr (struct ATS_Handle *ats);
-
-
-void
-ats_set_logging_options (struct ATS_Handle *ats,
-                         struct GNUNET_STATISTICS_Handle *stats,
-                         const struct GNUNET_CONFIGURATION_Handle *cfg);
-
-#endif
-/* end of file gnunet-service-transport_ats.h */




reply via email to

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