curly wars / auto-indentation
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
index 6ed3672939e41d7a91c28e7eb3af111fd83eaa0a..cbab8cb0fe42acecb7a2691d22732f0c6f26cc71 100644 (file)
@@ -1,6 +1,6 @@
 /*
  This file is part of GNUnet
- (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
+ (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
@@ -24,6 +24,8 @@
  * @author David Brodski
  */
 
+//TODO split rx and tx structures for better handling
+
 #include "platform.h"
 #include "gnunet_hello_lib.h"
 #include "gnunet_protocols.h"
@@ -35,6 +37,7 @@
 #include "gnunet_common.h"
 #include "gnunet_crypto_lib.h"
 #include "gnunet_fragmentation_lib.h"
+#include "gnunet_constants.h"
 //#include "wlan/ieee80211.h"
 //#include  <netinet/ip.h>
 
 /**
  * Max size of packet
  */
-#define WLAN_MTU 1450
+#define WLAN_MTU 1430
 
 /**
  * time out of a session
  */
-#define SESSION_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+#define SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
 
 /**
  * time out of a mac endpoint
  */
-#define MACENDPOINT_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
 
 /**
  * scaling factor for hello beacon
  */
-#define HALLO_BEACON_SCALING_FACTOR 900
+#define HELLO_BEACON_SCALING_FACTOR 30
+
+/**
+ * scaling factor for restarting the helper
+ */
+#define HELPER_RESTART_SCALING_FACTOR 2
 
 /**
  * max size of fragment queue
  */
 #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 1
 
+/**
+ * LLC fields for better compatibility
+ */
+#define WLAN_LLC_DSAP_FIELD 0x1f
+#define WLAN_LLC_SSAP_FIELD 0x1f
+
 
 /**
  * DEBUG switch
  */
-#define DEBUG_wlan GNUNET_NO
-#define DEBUG_wlan_retransmission GNUNET_NO
+#define DEBUG_wlan GNUNET_EXTRA_LOGGING
+#define DEBUG_wlan_retransmission GNUNET_EXTRA_LOGGING
 #define DEBUG_wlan_ip_udp_packets_on_air GNUNET_NO
+#define DEBUG_wlan_msg_dump GNUNET_EXTRA_LOGGING
 
 
 #define IEEE80211_ADDR_LEN      6       /* size of 802.11 address */
@@ -153,8 +168,8 @@ struct ieee80211_frame
   u_int8_t i_addr2[IEEE80211_ADDR_LEN];
   u_int8_t i_addr3[IEEE80211_ADDR_LEN];
   u_int8_t i_seq[2];
-#if DEBUG_wlan_ip_udp_packets_on_air
   u_int8_t llc[4];
+#if DEBUG_wlan_ip_udp_packets_on_air > 1
   struct iph ip;
   struct udphdr udp;
 #endif
@@ -240,6 +255,11 @@ struct Plugin
    */
   char *interface;
 
+  /**
+   * Mode of operation for the helper, 0 = normal, 1 = first loopback, 2 = second loopback
+   */
+  long long unsigned int testmode;
+
   /**
    * The mac_address of the wlan card given to us by the helper.
    */
@@ -301,9 +321,24 @@ struct Plugin
  */
 struct Finish_send
 {
+  /**
+   * pointer to the global plugin struct
+   */
   struct Plugin *plugin;
-  char *msgheader;
+
+  /**
+   * head of the next part to send to the helper
+   */
+  char *head_of_next_write;
+
+  /**
+   * Start of the message to send, needed for free
+   */
   struct GNUNET_MessageHeader *msgstart;
+
+  /**
+   * rest size to send
+   */
   ssize_t size;
 };
 
@@ -667,8 +702,11 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 static void
 free_session (struct Plugin *plugin, struct Sessionqueue *queue,
               int do_free_macendpoint);
-static struct MacEndpoint *create_macendpoint (struct Plugin *plugin,
-                                               const struct MacAddress *addr);
+static struct MacEndpoint *
+create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr);
+
+static void
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
 /**
  * Generates a nice hexdump of a memory area.
@@ -676,8 +714,8 @@ static struct MacEndpoint *create_macendpoint (struct Plugin *plugin,
  * \param  mem     pointer to memory to dump
  * \param  length  how many bytes to dump
  */
-void
-hexdump (void *mem, unsigned length)
+static void
+hexdump (const void *mem, unsigned length)
 {
   char line[80];
   char *src = (char *) mem;
@@ -699,6 +737,7 @@ hexdump (void *mem, unsigned length)
         t += sprintf (t, "%02X", src[j] & 0xff);
       else
         t += sprintf (t, "  ");
+
       t += sprintf (t, j % 2 ? " " : "-");
     }
 
@@ -738,7 +777,7 @@ get_macendpoint (struct Plugin *plugin, const struct MacAddress *addr,
 
   while (queue != NULL)
   {
-    GNUNET_assert (queue->sessions_head != NULL);
+    //GNUNET_assert (queue->sessions_head != NULL);
     if (memcmp (addr, &queue->addr, sizeof (struct MacAddress)) == 0)
       return queue;             /* session found */
     queue = queue->next;
@@ -756,10 +795,10 @@ get_macendpoint (struct Plugin *plugin, const struct MacAddress *addr,
 }
 
 /**
- * search for a session with the addr and peer id
+ * search for a session with the macendpoint and peer id
  *
  * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac address of the peer
+ * @param endpoint pointer to the mac endpoint of the peer
  * @param peer pointer to the peerid
  * @return returns the session
  */
@@ -773,8 +812,9 @@ search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
   while (queue != NULL)
   {
     GNUNET_assert (queue->content != NULL);
-    if (memcmp (peer, &queue->content->target,
-                sizeof (struct GNUNET_PeerIdentity)) == 0)
+    if (memcmp
+        (peer, &queue->content->target,
+         sizeof (struct GNUNET_PeerIdentity)) == 0)
       return queue->content;    /* session found */
     queue = queue->next;
   }
@@ -807,6 +847,7 @@ wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
   GNUNET_snprintf (ret, sizeof (ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
                    PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2],
                    mac->mac[3], mac->mac[4], mac->mac[5]);
+
   return ret;
 }
 
@@ -821,6 +862,7 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct Sessionqueue *queue = cls;
 
   GNUNET_assert (queue != NULL);
+  GNUNET_assert (queue->content != NULL);
   queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
   {
@@ -830,6 +872,11 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       (GNUNET_TIME_absolute_add
        (queue->content->last_activity, SESSION_TIMEOUT)).rel_value == 0)
   {
+
+    GNUNET_assert (queue->content->mac != NULL);
+    GNUNET_assert (queue->content->mac->plugin != NULL);
+    GNUNET_STATISTICS_update (queue->content->mac->plugin->env->stats,
+                              _("# wlan session timeouts"), 1, GNUNET_NO);
     free_session (queue->content->mac->plugin, queue, GNUNET_YES);
   }
   else
@@ -843,7 +890,8 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  * create a new session
  *
  * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac endpoint of the peer
+ * @param endpoint pointer to the mac endpoint of the peer
+ * @param peer peer identity to use for this session
  * @return returns the session
  */
 
@@ -852,6 +900,9 @@ create_session (struct Plugin *plugin, struct MacEndpoint *endpoint,
                 const struct GNUNET_PeerIdentity *peer)
 {
   GNUNET_assert (endpoint != NULL);
+  GNUNET_assert (plugin != NULL);
+  GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan session created"), 1,
+                            GNUNET_NO);
   struct Sessionqueue *queue =
       GNUNET_malloc (sizeof (struct Sessionqueue) + sizeof (struct Session));
 
@@ -934,6 +985,8 @@ queue_session (struct Plugin *plugin, struct Session *session)
     GNUNET_CONTAINER_DLL_insert_tail (plugin->pending_Sessions_head,
                                       plugin->pending_Sessions_tail, queue);
     plugin->pendingsessions++;
+    GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                           plugin->pendingsessions, GNUNET_NO);
   }
 
 }
@@ -974,27 +1027,29 @@ set_next_beacon_time (struct Plugin *const plugin)
   //under 10 known peers: once a second
   if (plugin->mac_count < 10)
   {
-    plugin->beacon_time = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
-                                                    GNUNET_TIME_relative_multiply
-                                                    (GNUNET_TIME_UNIT_SECONDS,
-                                                     HALLO_BEACON_SCALING_FACTOR));
+    plugin->beacon_time =
+        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS,
+                                   HELLO_BEACON_SCALING_FACTOR));
   }
   //under 30 known peers: every 10 seconds
   else if (plugin->mac_count < 30)
   {
-    plugin->beacon_time = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
-                                                    GNUNET_TIME_relative_multiply
-                                                    (GNUNET_TIME_UNIT_SECONDS,
-                                                     10 *
-                                                     HALLO_BEACON_SCALING_FACTOR));
+    plugin->beacon_time =
+        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS,
+                                   10 * HELLO_BEACON_SCALING_FACTOR));
   }
   //over 30 known peers: once a minute
   else
   {
-    plugin->beacon_time = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
-                                                    GNUNET_TIME_relative_multiply
-                                                    (GNUNET_TIME_UNIT_MINUTES,
-                                                     HALLO_BEACON_SCALING_FACTOR));
+    plugin->beacon_time =
+        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MINUTES,
+                                   HELLO_BEACON_SCALING_FACTOR));
   }
 }
 
@@ -1079,27 +1134,39 @@ get_next_queue_session (struct Plugin *plugin)
     GNUNET_assert (session != NULL);
     pm = session->pending_message_head;
 
-#if DEBUG_wlan
     if (pm == NULL)
     {
+#if DEBUG_wlan
       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
                        "pending message is empty, should not happen. session %p\n",
                        session);
-    }
 #endif
+      sessionqueue_alt = sessionqueue;
+      sessionqueue = sessionqueue->next;
+      plugin->pendingsessions--;
+      GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                             plugin->pendingsessions, GNUNET_NO);
+      GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
+                                   plugin->pending_Sessions_tail,
+                                   sessionqueue_alt);
+
+      GNUNET_free (sessionqueue_alt);
+      continue;
 
-    GNUNET_assert (pm != NULL);
+    }
 
     //check for message timeout
     if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
     {
       //check if session has no message in the fragment queue
-      if ((session->mac->fragment_messages_out_count
-           < FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT)
-          && (session->fragment_messages_out_count
-              < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
+      if ((session->mac->fragment_messages_out_count <
+           FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT) &&
+          (session->fragment_messages_out_count <
+           FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
       {
         plugin->pendingsessions--;
+        GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                               plugin->pendingsessions, GNUNET_NO);
         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
                                      plugin->pending_Sessions_tail,
                                      sessionqueue);
@@ -1129,6 +1196,8 @@ get_next_queue_session (struct Plugin *plugin)
         sessionqueue_alt = sessionqueue;
         sessionqueue = sessionqueue->next;
         plugin->pendingsessions--;
+        GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                               plugin->pendingsessions, GNUNET_NO);
         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
                                      plugin->pending_Sessions_tail,
                                      sessionqueue_alt);
@@ -1154,38 +1223,41 @@ free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
   struct FragmentMessage_queue *fmq;
   struct FragmentMessage_queue *fmq_next;
 
-  if (fm != NULL)
+  fmq = plugin->sending_messages_head;
+  while (fmq != NULL)
   {
-    fmq = plugin->sending_messages_head;
-    while (fmq != NULL)
+    fmq_next = fmq->next;
+    if (fmq->content == fm)
     {
-      fmq_next = fmq->next;
-      if (fmq->content == fm)
-      {
-        GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
-                                     plugin->sending_messages_tail, fmq);
-        GNUNET_free (fmq);
-      }
-      fmq = fmq_next;
+      GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
+                                   plugin->sending_messages_tail, fmq);
+      GNUNET_free (fmq);
     }
+    fmq = fmq_next;
+  }
+
+  (session->mac->fragment_messages_out_count)--;
+  session->fragment_messages_out_count--;
+  plugin->pending_Fragment_Messages--;
+  GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
+                         plugin->pending_Fragment_Messages, GNUNET_NO);
+  GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
+                               endpoint->sending_messages_tail, fm);
+  GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
+  if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (fm->timeout_task);
+    fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  }
 
-    (session->mac->fragment_messages_out_count)--;
-    session->fragment_messages_out_count--;
-    plugin->pending_Fragment_Messages--;
-    GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
-                                 endpoint->sending_messages_tail, fm);
-    GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
-    if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-      GNUNET_SCHEDULER_cancel (fm->timeout_task);
-    GNUNET_free (fm);
-
-    queue_session (plugin, session);
+  GNUNET_free (fm);
+
+  queue_session (plugin, session);
 #if DEBUG_wlan
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Free pending fragment messages %p, session %p\n", fm,
-                     session);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Free pending fragment messages %p, session %p\n", fm,
+                   session);
 #endif
-  }
 }
 
 /**
@@ -1221,6 +1293,7 @@ getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
  * @param Header address to write the header to
  * @param to_mac_addr address of the recipient
  * @param plugin pointer to the plugin struct
+ * @param size size of the whole packet, needed to calculate the time to send the packet
  * @return GNUNET_YES if there was no error
  */
 static int
@@ -1240,8 +1313,10 @@ getWlanHeader (struct ieee80211_frame *Header,
 
   tmp16 = (uint16_t *) Header->i_dur;
   *tmp16 = (uint16_t) htole16 ((size * 1000000) / rate + 290);
+  Header->llc[0] = WLAN_LLC_DSAP_FIELD;
+  Header->llc[1] = WLAN_LLC_SSAP_FIELD;
 
-#if DEBUG_wlan_ip_udp_packets_on_air
+#if DEBUG_wlan_ip_udp_packets_on_air > 1
   uint crc = 0;
   uint16_t *x;
   int count;
@@ -1267,8 +1342,6 @@ getWlanHeader (struct ieee80211_frame *Header,
     crc += *(unsigned char *) x;
   crc = (crc & 0xffff) + (crc >> 16);
   Header->ip.ip_sum = htons (~(unsigned short) crc);
-  Header->llc[0] = 6;
-  Header->llc[1] = 6;
   Header->udp.len = htons (size - sizeof (struct ieee80211_frame));
 
 #endif
@@ -1329,14 +1402,15 @@ add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
   struct GNUNET_MessageHeader *msgheader2;
   uint16_t size;
 
-#if DEBUG_wlan_retransmission
+#if DEBUG_wlan_retransmission > 1
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                   "Adding fragment of message %p to send, session %p, endpoint %p\n",
-                   fm, fm->session, endpoint);
+                   "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
+                   fm, fm->session, endpoint, hdr->type);
 #endif
 
-  size = sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send)
-      + sizeof (struct ieee80211_frame) + ntohs (hdr->size);
+  size =
+      sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
+      sizeof (struct ieee80211_frame) + ntohs (hdr->size);
   fm->frag = GNUNET_malloc (size);
   fm->size = size;
 
@@ -1357,142 +1431,513 @@ add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
   set_next_send (plugin);
 }
 
+
 /**
- * function to send a hallo beacon
- * @param plugin pointer to the plugin struct
+ * We have been notified that wlan-helper has written something to stdout.
+ * Handle the output, then reschedule this function to be called again once
+ * more is available.
+ *
+ * @param cls the plugin handle
+ * @param tc the scheduling context
  */
 static void
-send_hello_beacon (struct Plugin *plugin)
+wlan_plugin_helper_read (void *cls,
+                         const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct Plugin *plugin = cls;
 
-#if DEBUG_wlan
-  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                   "Sending hello beacon\n");
-#endif
+  plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
 
-  uint16_t size;
-  ssize_t bytes;
-  uint16_t hallo_size;
-  struct GNUNET_MessageHeader *msgheader;
-  struct ieee80211_frame *ieeewlanheader;
-  struct Radiotap_Send *radioHeader;
-  struct GNUNET_MessageHeader *msgheader2;
-  const struct GNUNET_MessageHeader *hello;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
 
-  hello = plugin->env->get_our_hello ();
-  hallo_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
-  GNUNET_assert (sizeof (struct WlanHeader) + hallo_size <= WLAN_MTU);
-  size = sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send)
-      + sizeof (struct ieee80211_frame) + sizeof (struct GNUNET_MessageHeader)
-      + hallo_size;
+  char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)];
+  ssize_t bytes;
 
-  msgheader = GNUNET_malloc (size);
-  msgheader->size = htons (size);
-  msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+  bytes =
+      GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf,
+                             sizeof (mybuf));
+  if (bytes <= 0)
+  {
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     _
+                     ("Finished reading from wlan-helper stdout with code: %d\n"),
+                     bytes);
+#endif
+    return;
+  }
+  GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes,
+                             GNUNET_NO, GNUNET_NO);
 
-  radioHeader = (struct Radiotap_Send *) &msgheader[1];
-  getRadiotapHeader (plugin, NULL, radioHeader);
-  ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
-  getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size);
+  GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
+  plugin->server_read_task =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      plugin->server_stdout_handle,
+                                      &wlan_plugin_helper_read, plugin);
+}
 
-  msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
-  msgheader2->size =
-      htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) +
-             sizeof (struct GNUNET_MessageHeader));
+/**
+ * Start the gnunet-wlan-helper process.
+ *
+ * @param plugin the transport plugin
+ * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
+ */
+static int
+wlan_transport_start_wlan_helper (struct Plugin *plugin)
+{
+  const char *filenamehw = "gnunet-transport-wlan-helper";
+  char *filenameloopback = "gnunet-transport-wlan-helper-dummy";
+  char *absolute_filename = NULL;
 
-  msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
-  memcpy (&msgheader2[1], hello, hallo_size);
+  plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
+  if (plugin->server_stdout == NULL)
+    return GNUNET_SYSERR;
 
-  bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size);
+  plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
+  if (plugin->server_stdin == NULL)
+    return GNUNET_SYSERR;
 
-  if (bytes == GNUNET_SYSERR)
+  if ((plugin->testmode == 1) || (plugin->testmode == 2))
   {
-    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
-                     _
-                     ("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
-                     errno, strerror (errno));
+    if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
+    {
+      absolute_filename = strdup (filenameloopback);
+    }
+    else
+    {
+      char cwd[FILENAME_MAX];
+
+      GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
 
+      GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
+                       filenameloopback);
+
+      if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                         "Helper `%s' not found! %i\n", absolute_filename);
+        GNUNET_break (0);
+      }
+    }
   }
-  GNUNET_assert (bytes != GNUNET_SYSERR);
-  GNUNET_assert (bytes == size);
-  GNUNET_free (msgheader);
 
-  set_next_beacon_time (plugin);
-  set_next_send (plugin);
-}
+  /* Start the server process */
 
-/**
- * function to add an ack to send it for a received fragment
- * @param cls MacEndpoint this ack belongs to
- * @param msg_id id of the message
- * @param hdr pointer to the hdr where the ack is stored
- *
- */
+  if (plugin->testmode == 0)
+  {
 
-static void
-add_ack_for_send (void *cls, uint32_t msg_id,
-                  const struct GNUNET_MessageHeader *hdr)
-{
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Starting gnunet-wlan-helper process cmd: %s %s %i\n",
+                     filenamehw, plugin->interface, plugin->testmode);
+#endif
 
-  struct AckSendQueue *ack;
+    if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES)
+    {
+      plugin->server_proc =
+          GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
+                                   filenamehw, filenamehw, plugin->interface,
+                                   NULL);
+    }
+    else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                       "gnunet-transport-wlan-helper is not suid, please change it or look at the doku\n");
+      GNUNET_break (0);
+    }
+    else
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                       "gnunet-transport-wlan-helper not found, please look if it exists and is the $PATH variable!\n");
+      GNUNET_break (0);
+    }
 
-  GNUNET_assert (cls != NULL);
-  struct MacEndpoint *endpoint = cls;
-  struct Plugin *plugin = endpoint->plugin;
-  struct GNUNET_MessageHeader *msgheader;
-  struct GNUNET_MessageHeader *msgheader2;
-  uint16_t size;
+  }
+  else if (plugin->testmode == 1)
+  {
 
-  size = sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send)
-      + sizeof (struct ieee80211_frame) + ntohs (hdr->size)
-      + sizeof (struct AckSendQueue);
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
+                     "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n",
+                     absolute_filename, plugin->interface, plugin->testmode);
+#endif
+    plugin->server_proc =
+        GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
+                                 absolute_filename, absolute_filename, "1",
+                                 NULL);
+    if (plugin->server_proc == NULL)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                       "`%s' not found, please look if it exists and is in the $PATH variable!\n",
+                       absolute_filename);
+      GNUNET_break (0);
+    }
+  }
+  else if (plugin->testmode == 2)
+  {
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
+                     "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n",
+                     absolute_filename, plugin->interface, plugin->testmode);
+#endif
 
-  ack = GNUNET_malloc (size);
-  ack->message_id = msg_id;
-  ack->endpoint = endpoint;
+    plugin->server_proc =
+        GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
+                                 absolute_filename, absolute_filename, "2",
+                                 NULL);
+    if (plugin->server_proc == NULL)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                       "`%s' not found, please look if it exists and is in the $PATH variable!\n",
+                       absolute_filename);
+      GNUNET_break (0);
+    }
+  }
+  if (absolute_filename != NULL)
+    GNUNET_free (absolute_filename);
+  if (plugin->server_proc == NULL)
+  {
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Failed to start gnunet-wlan-helper process\n");
+#endif
+    return GNUNET_SYSERR;
+  }
 
-  size = sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send)
-      + sizeof (struct ieee80211_frame) + ntohs (hdr->size);
 
-  msgheader = (struct GNUNET_MessageHeader *) &ack[1];
-  ack->hdr = (struct GNUNET_MessageHeader *) &ack[1];
-  msgheader->size = htons (size);
-  msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
 
-  ack->radioHeader = (struct Radiotap_Send *) &msgheader[1];
-  ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1];
-  msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1];
-  memcpy (msgheader2, hdr, ntohs (hdr->size));
+  /* Close the write end of the read pipe */
+  GNUNET_DISK_pipe_close_end (plugin->server_stdout,
+                              GNUNET_DISK_PIPE_END_WRITE);
 
-  GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
-                                    plugin->ack_send_queue_tail, ack);
+  /* Close the read end of the write pipe */
+  GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
+
+  plugin->server_stdout_handle =
+      GNUNET_DISK_pipe_handle (plugin->server_stdout,
+                               GNUNET_DISK_PIPE_END_READ);
+  plugin->server_stdin_handle =
+      GNUNET_DISK_pipe_handle (plugin->server_stdin,
+                               GNUNET_DISK_PIPE_END_WRITE);
+
+  GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
 
-#if DEBUG_wlan_retransmission
+#if DEBUG_wlan
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                   "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
-                   msg_id, ack, endpoint);
+                   "Adding server_read_task for the wlan-helper\n");
 #endif
 
-  set_next_send (plugin);
+  plugin->server_read_task =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      plugin->server_stdout_handle,
+                                      &wlan_plugin_helper_read, plugin);
+
+  return GNUNET_YES;
 }
 
 /**
- * Function for the scheduler if a FragmentMessage times out
- * @param cls pointer to the FragmentMessage
- * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ * Stops the gnunet-wlan-helper process.
+ *
+ * @param plugin the transport plugin
+ * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
  */
-static void
-fragmentmessage_timeout (void *cls,
-                         const struct GNUNET_SCHEDULER_TaskContext *tc)
+static int
+wlan_transport_stop_wlan_helper (struct Plugin *plugin)
 {
-  struct FragmentMessage *fm = cls;
+#if DEBUG_wlan
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Stoping WLAN helper process\n");
+#endif
 
-  GNUNET_assert (fm != NULL);
-  fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
   {
-    return;
-  }
+    GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
+    plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (plugin->server_write_task);
+    plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (plugin->server_read_task);
+    plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  GNUNET_DISK_pipe_close (plugin->server_stdout);
+  GNUNET_DISK_pipe_close (plugin->server_stdin);
+  GNUNET_OS_process_kill (plugin->server_proc, SIGKILL);
+  GNUNET_OS_process_wait (plugin->server_proc);
+  GNUNET_OS_process_close (plugin->server_proc);
+
+  return GNUNET_YES;
+}
+
+/**
+ * function for delayed restart of the helper process
+ * @param cls Finish_send struct if message should be finished
+ * @param tc TaskContext
+ */
+static void
+delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
+
+  plugin = finish->plugin;
+
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+  {
+    GNUNET_free_non_null (finish->msgstart);
+    GNUNET_free (finish);
+    return;
+  }
+
+  wlan_transport_start_wlan_helper (plugin);
+
+  if (finish->size != 0)
+  {
+    plugin->server_write_task =
+        GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         plugin->server_stdin_handle,
+                                         &finish_sending, finish);
+  }
+  else
+  {
+    set_next_send (plugin);
+    GNUNET_free_non_null (finish->msgstart);
+    GNUNET_free (finish);
+  }
+
+}
+
+/**
+ * Function to restart the helper
+ * @param plugin pointer to the global plugin struct
+ * @param finish pointer to the Finish_send struct to finish
+ */
+static void
+restart_helper (struct Plugin *plugin, struct Finish_send *finish)
+{
+  static struct GNUNET_TIME_Relative next_try = { 1000 };
+  GNUNET_assert (finish != NULL);
+
+  wlan_transport_stop_wlan_helper (plugin);
+  plugin->server_write_task =
+      GNUNET_SCHEDULER_add_delayed (next_try, &delay_restart_helper, finish);
+  GNUNET_TIME_relative_multiply (next_try, HELPER_RESTART_SCALING_FACTOR);
+
+}
+
+/**
+ * function to finish a sending if not all could have been writen befor
+ * @param cls pointer to the Finish_send struct
+ * @param tc TaskContext
+ */
+static void
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
+  ssize_t bytes;
+
+  plugin = finish->plugin;
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+  {
+    GNUNET_free (finish->msgstart);
+    GNUNET_free (finish);
+    return;
+  }
+  bytes =
+      GNUNET_DISK_file_write (plugin->server_stdin_handle,
+                              finish->head_of_next_write, finish->size);
+
+  if (bytes != finish->size)
+  {
+    if (bytes != GNUNET_SYSERR)
+    {
+      finish->head_of_next_write += bytes;
+      finish->size -= bytes;
+      plugin->server_write_task =
+          GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                           plugin->server_stdin_handle,
+                                           &finish_sending, finish);
+    }
+    else
+    {
+      restart_helper (plugin, finish);
+    }
+  }
+  else
+  {
+    GNUNET_free (finish->msgstart);
+    GNUNET_free (finish);
+    set_next_send (plugin);
+  }
+}
+
+/**
+ * function to send a hello beacon
+ * @param plugin pointer to the plugin struct
+ */
+static void
+send_hello_beacon (struct Plugin *plugin)
+{
+
+#if DEBUG_wlan
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Sending hello beacon\n");
+#endif
+
+  uint16_t size;
+  ssize_t bytes;
+  uint16_t hello_size;
+  struct GNUNET_MessageHeader *msgheader;
+  struct ieee80211_frame *ieeewlanheader;
+  struct Radiotap_Send *radioHeader;
+  struct GNUNET_MessageHeader *msgheader2;
+  const struct GNUNET_MessageHeader *hello;
+  struct Finish_send *finish;
+
+  GNUNET_assert (plugin != NULL);
+
+  GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"),
+                            1, GNUNET_NO);
+
+  hello = plugin->env->get_our_hello ();
+  hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
+  GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
+  size =
+      sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
+      sizeof (struct ieee80211_frame) + hello_size;
+
+  msgheader = GNUNET_malloc (size);
+  msgheader->size = htons (size);
+  msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+
+  radioHeader = (struct Radiotap_Send *) &msgheader[1];
+  getRadiotapHeader (plugin, NULL, radioHeader);
+  ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
+  getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size);
+
+  msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
+  /*msgheader2->size =
+   * htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) +
+   * sizeof (struct GNUNET_MessageHeader));
+   *
+   * msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); */
+  memcpy (msgheader2, hello, hello_size);
+
+  bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size);
+
+  if (bytes == GNUNET_SYSERR)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                     _
+                     ("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
+                     errno, strerror (errno));
+    finish = GNUNET_malloc (sizeof (struct Finish_send));
+    finish->plugin = plugin;
+    finish->head_of_next_write = NULL;
+    finish->size = 0;
+    finish->msgstart = NULL;
+    restart_helper (plugin, finish);
+
+    set_next_beacon_time (plugin);
+
+  }
+  else
+  {
+    GNUNET_assert (bytes == size);
+    set_next_beacon_time (plugin);
+    set_next_send (plugin);
+  }
+  GNUNET_free (msgheader);
+
+
+}
+
+/**
+ * function to add an ack to send it for a received fragment
+ * @param cls MacEndpoint this ack belongs to
+ * @param msg_id id of the message
+ * @param hdr pointer to the hdr where the ack is stored
+ *
+ */
+
+static void
+add_ack_for_send (void *cls, uint32_t msg_id,
+                  const struct GNUNET_MessageHeader *hdr)
+{
+
+  struct AckSendQueue *ack;
+
+  GNUNET_assert (cls != NULL);
+  struct MacEndpoint *endpoint = cls;
+  struct Plugin *plugin = endpoint->plugin;
+  struct GNUNET_MessageHeader *msgheader;
+  struct GNUNET_MessageHeader *msgheader2;
+  uint16_t size;
+
+  size =
+      sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
+      sizeof (struct ieee80211_frame) + ntohs (hdr->size) +
+      sizeof (struct AckSendQueue);
+
+  ack = GNUNET_malloc (size);
+  ack->message_id = msg_id;
+  ack->endpoint = endpoint;
+
+  size =
+      sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
+      sizeof (struct ieee80211_frame) + ntohs (hdr->size);
+
+  msgheader = (struct GNUNET_MessageHeader *) &ack[1];
+  ack->hdr = (struct GNUNET_MessageHeader *) &ack[1];
+  msgheader->size = htons (size);
+  msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+
+  ack->radioHeader = (struct Radiotap_Send *) &msgheader[1];
+  ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1];
+  msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1];
+  memcpy (msgheader2, hdr, ntohs (hdr->size));
+
+  GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
+                                    plugin->ack_send_queue_tail, ack);
+
+#if DEBUG_wlan_retransmission > 1
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
+                   msg_id, ack, endpoint);
+#endif
+
+  set_next_send (plugin);
+}
+
+/**
+ * Function for the scheduler if a FragmentMessage times out
+ * @param cls pointer to the FragmentMessage
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ */
+static void
+fragmentmessage_timeout (void *cls,
+                         const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct FragmentMessage *fm = cls;
+
+  GNUNET_assert (fm != NULL);
+  fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  {
+    return;
+  }
   free_fragment_message (fm->session->mac->plugin, fm);
 }
 
@@ -1517,24 +1962,25 @@ check_fragment_queue (struct Plugin *plugin)
     if (session != NULL)
     {
       pm = session->pending_message_head;
+      GNUNET_assert (pm != NULL);
       GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
                                    session->pending_message_tail, pm);
       session->mac->fragment_messages_out_count++;
       session->fragment_messages_out_count++;
       plugin->pending_Fragment_Messages++;
-      GNUNET_assert (pm != NULL);
+      GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
+                             plugin->pending_Fragment_Messages, GNUNET_NO);
 
       fm = GNUNET_malloc (sizeof (struct FragmentMessage));
       fm->session = session;
       fm->timeout.abs_value = pm->timeout.abs_value;
       fm->frag = NULL;
-      fm->fragcontext = GNUNET_FRAGMENT_context_create (plugin->env->stats,
-                                                        WLAN_MTU,
-                                                        &plugin->tracker,
-                                                        GNUNET_TIME_UNIT_SECONDS,
-                                                        &(pm->msg->header),
-                                                        &add_message_for_send,
-                                                        fm);
+      fm->fragcontext =
+          GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
+                                          &plugin->tracker,
+                                          GNUNET_TIME_UNIT_SECONDS,
+                                          &(pm->msg->header),
+                                          &add_message_for_send, fm);
       fm->timeout_task =
           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
                                         (fm->timeout), fragmentmessage_timeout,
@@ -1577,13 +2023,17 @@ check_fragment_queue (struct Plugin *plugin)
 /**
  * Function to send an ack, does not free the ack
  * @param plugin pointer to the plugin
- * @param ack pointer to the ack to send
  */
 static void
-send_ack (struct Plugin *plugin, struct AckSendQueue *ack)
+send_ack (struct Plugin *plugin)
 {
 
   ssize_t bytes;
+  struct AckSendQueue *ack;
+  struct Finish_send *finish;
+
+  ack = plugin->ack_send_queue_head;
+
 
 #if DEBUG_wlan
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
@@ -1592,63 +2042,36 @@ send_ack (struct Plugin *plugin, struct AckSendQueue *ack)
                    ntohs (ack->hdr->size) - sizeof (struct Radiotap_Send));
 #endif
 
+  GNUNET_assert (plugin != NULL);
+  GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1,
+                            GNUNET_NO);
+
   getRadiotapHeader (plugin, ack->endpoint, ack->radioHeader);
   getWlanHeader (ack->ieeewlanheader, &ack->endpoint->addr, plugin,
                  ntohs (ack->hdr->size));
 
-  bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->hdr,
-                                  ntohs (ack->hdr->size));
+  bytes =
+      GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->hdr,
+                              ntohs (ack->hdr->size));
   if (bytes == GNUNET_SYSERR)
   {
     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
                      _
                      ("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
                      errno, strerror (errno));
-
-  }
-  GNUNET_assert (bytes != GNUNET_SYSERR);
-  GNUNET_assert (bytes == ntohs (ack->hdr->size));
-  set_next_send (plugin);
-}
-
-/**
- * function to finish a sending if not all could have been writen befor
- * @param cls pointer to the Finish_send struct
- * @param tc TaskContext
- */
-static void
-finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct Finish_send *finish = cls;
-  struct Plugin *plugin;
-  ssize_t bytes;
-
-  plugin = finish->plugin;
-  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-  {
-    GNUNET_free (finish->msgstart);
-    GNUNET_free (finish);
-    return;
-  }
-  bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle,
-                                  finish->msgheader, finish->size);
-  GNUNET_assert (bytes != GNUNET_SYSERR);
-
-  if (bytes != finish->size)
-  {
-    finish->msgheader = finish->msgheader + bytes;
-    finish->size = finish->size - bytes;
-    plugin->server_write_task =
-        GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                         plugin->server_stdin_handle,
-                                         &finish_sending, finish);
+    finish = GNUNET_malloc (sizeof (struct Finish_send));
+    finish->plugin = plugin;
+    finish->head_of_next_write = NULL;
+    finish->size = 0;
+    finish->msgstart = NULL;
+    restart_helper (plugin, finish);
   }
   else
   {
-    GNUNET_free (finish->msgstart);
-    GNUNET_free (finish);
+    GNUNET_assert (bytes == ntohs (ack->hdr->size));
+    GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
+                                 plugin->ack_send_queue_tail, ack);
+    GNUNET_free (ack);
     set_next_send (plugin);
   }
 }
@@ -1664,6 +2087,8 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct Plugin *plugin = cls;
 
+  GNUNET_assert (plugin != NULL);
+
   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
@@ -1672,16 +2097,11 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct FragmentMessage *fm;
   struct Finish_send *finish;
   struct FragmentMessage_queue *fmq;
-  struct AckSendQueue *ack;
   ssize_t bytes;
 
   if (plugin->ack_send_queue_head != NULL)
   {
-    ack = plugin->ack_send_queue_head;
-    GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
-                                 plugin->ack_send_queue_tail, ack);
-    send_ack (plugin, ack);
-    GNUNET_free (ack);
+    send_ack (plugin);
     return;
   }
 
@@ -1694,6 +2114,9 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
   if (plugin->sending_messages_head != NULL)
   {
+    GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan fragments send"), 1,
+                              GNUNET_NO);
+
     fmq = plugin->sending_messages_head;
     fm = fmq->content;
     GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
@@ -1713,32 +2136,39 @@ do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     getWlanHeader (fm->ieeewlanheader, &(fm->session->mac->addr), plugin,
                    fm->size);
 
-    bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag,
-                                    fm->size);
-    if (bytes == GNUNET_SYSERR)
-    {
-      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
-                       _
-                       ("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
-                       errno, strerror (errno));
+    bytes =
+        GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag,
+                                fm->size);
 
-    }
-    GNUNET_assert (bytes != GNUNET_SYSERR);
 
     if (bytes != fm->size)
     {
       finish = GNUNET_malloc (sizeof (struct Finish_send));
       finish->plugin = plugin;
-      finish->msgheader = fm->frag + bytes;
-      finish->size = fm->size - bytes;
       finish->msgstart = (struct GNUNET_MessageHeader *) fm->frag;
-
       GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
 
-      plugin->server_write_task =
-          GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                           plugin->server_stdin_handle,
-                                           &finish_sending, finish);
+      if (bytes == GNUNET_SYSERR)
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                         _
+                         ("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
+                         errno, strerror (errno));
+
+        finish->head_of_next_write = fm->frag;
+        finish->size = fm->size;
+        restart_helper (plugin, finish);
+      }
+      else
+      {
+        finish->head_of_next_write = fm->frag + bytes;
+        finish->size = fm->size - bytes;
+        plugin->server_write_task =
+            GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                             plugin->server_stdin_handle,
+                                             &finish_sending, finish);
+      }
+
       fm->frag = NULL;
     }
     else
@@ -1781,9 +2211,18 @@ wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
   if (addrlen == 6)
   {
     /* TODO check for bad addresses like multicast, broadcast, etc */
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "wlan_plugin_address_suggested got good address, size %u!\n",
+                     addrlen);
+#endif
     return GNUNET_OK;
   }
-
+#if DEBUG_wlan
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "wlan_plugin_address_suggested got bad address, size %u!\n",
+                   addrlen);
+#endif
   return GNUNET_SYSERR;
 }
 
@@ -1824,6 +2263,7 @@ wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
   struct PendingMessage *newmsg;
   struct WlanHeader *wlanheader;
 
+  GNUNET_assert (plugin != NULL);
   //check if msglen > 0
   GNUNET_assert (msgbuf_size > 0);
 
@@ -1842,6 +2282,9 @@ wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
     }
   }
 
+  GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan messages queued"), 1,
+                            GNUNET_NO);
+
   //queue message:
 
   //queue message in session
@@ -1850,7 +2293,7 @@ wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
   if (session->pending_message_head != NULL)
   {
     newmsg = session->pending_message_head;
-    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                      "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages for this mac connection %u\n",
                      GNUNET_TIME_absolute_get_remaining (newmsg->
                                                          timeout).rel_value,
@@ -1890,7 +2333,9 @@ wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
                    "New message for %p with size (incl wlan header) %u added\n",
                    session, newmsg->message_size);
 #endif
-
+#if DEBUG_wlan_msg_dump > 1
+  hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
+#endif
   //queue session
   queue_session (plugin, session);
 
@@ -1903,7 +2348,7 @@ wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
 /**
  * function to free a mac endpoint
  * @param plugin pointer to the plugin struct
- * @param endpoin pointer to the MacEndpoint to free
+ * @param endpoint pointer to the MacEndpoint to free
  */
 static void
 free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
@@ -1923,7 +2368,13 @@ free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
 
   GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint);
   if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+  {
     GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
+    endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  plugin->mac_count--;
+  GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
+                         plugin->mac_count, GNUNET_NO);
   GNUNET_free (endpoint);
 
 }
@@ -1946,6 +2397,7 @@ free_session (struct Plugin *plugin, struct Sessionqueue *queue,
   struct FragmentMessage *fmnext;
   int check = 0;
 
+  GNUNET_assert (plugin != NULL);
   GNUNET_assert (queue != NULL);
   GNUNET_assert (queue->content != NULL);
 
@@ -1954,19 +2406,22 @@ free_session (struct Plugin *plugin, struct Sessionqueue *queue,
   pendingsession = plugin->pending_Sessions_head;
   while (pendingsession != NULL)
   {
-    pendingsession_tmp = pendingsession->next;
-    if (pendingsession->content == queue->content)
+    pendingsession_tmp = pendingsession;
+    pendingsession = pendingsession->next;
+    GNUNET_assert (pendingsession_tmp->content != NULL);
+    if (pendingsession_tmp->content == queue->content)
     {
       plugin->pendingsessions--;
+      GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                             plugin->pendingsessions, GNUNET_NO);
       GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
                                    plugin->pending_Sessions_tail,
-                                   pendingsession);
-      GNUNET_free (pendingsession);
+                                   pendingsession_tmp);
+      GNUNET_free (pendingsession_tmp);
 
       GNUNET_assert (check == 0);
       check = 1;
     }
-    pendingsession = pendingsession_tmp;
   }
 
   endpoint = queue->content->mac;
@@ -1992,17 +2447,26 @@ free_session (struct Plugin *plugin, struct Sessionqueue *queue,
     pm = queue->content->pending_message_head;
   }
 
-  GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head,
-                               endpoint->sessions_tail, queue);
-
+  GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail,
+                               queue);
+  //Check that no ohter session on this endpoint for this session exits
+  GNUNET_assert (search_session (plugin, endpoint, &queue->content->target) ==
+                 NULL);
   if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
   {
     free_macendpoint (plugin, endpoint);
+    //check if no endpoint with the same address exists
+    GNUNET_assert (get_macendpoint (plugin, &endpoint->addr, GNUNET_NO) ==
+                   NULL);
   }
 
   if (queue->content->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+  {
     GNUNET_SCHEDULER_cancel (queue->content->timeout_task);
+    queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  }
   GNUNET_free (queue);
+
   check_fragment_queue (plugin);
 }
 
@@ -2033,8 +2497,9 @@ wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
       // content is never NULL
       GNUNET_assert (queue->content != NULL);
       queue_next = queue->next;
-      if (memcmp (target, &(queue->content->target),
-                  sizeof (struct GNUNET_PeerIdentity)) == 0)
+      if (memcmp
+          (target, &(queue->content->target),
+           sizeof (struct GNUNET_PeerIdentity)) == 0)
       {
         free_session (plugin, queue, GNUNET_YES);
       }
@@ -2067,28 +2532,42 @@ wlan_plugin_address_pretty_printer (void *cls, const char *type,
                                     GNUNET_TRANSPORT_AddressStringCallback asc,
                                     void *asc_cls)
 {
-  char ret[92];
+  char *ret;
   const unsigned char *input;
 
   //GNUNET_assert(cls !=NULL);
-  if (addrlen != 6)
+  if (addrlen != sizeof (struct MacAddress))
   {
-    /* invalid address (MAC addresses have 6 bytes) */ GNUNET_break (0);
+    /* invalid address (MAC addresses have 6 bytes) */
+    //GNUNET_break (0);
+#if DEBUG_wlan
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
+                     addrlen);
+#endif
     asc (asc_cls, NULL);
     return;
   }
   input = (const unsigned char *) addr;
-  GNUNET_snprintf (ret, sizeof (ret),
-                   "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
-                   PROTOCOL_PREFIX, input[0], input[1], input[2], input[3],
-                   input[4], input[5]);
+  GNUNET_asprintf (&ret,
+                   "Transport %s: %s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+                   type, PROTOCOL_PREFIX, input[0], input[1], input[2],
+                   input[3], input[4], input[5]);
+#if DEBUG_wlan
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Func wlan_plugin_address_pretty_printer got size: %u, nummeric %u, type %s; made string: %s\n",
+                   addrlen, numeric, type, ret);
+#endif
   asc (asc_cls, ret);
+  //only one mac address per plugin
+  asc (asc_cls, NULL);
 }
 
+
+
 /**
  * handels the data after all fragments are put together
- * @param plugin
- * @param session_light
+ * @param cls macendpoint this messages belongs to
  * @param hdr pointer to the data
  */
 static void
@@ -2099,11 +2578,12 @@ wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
   struct WlanHeader *wlanheader;
   struct Session *session;
 
-  //const char * tempmsg;
   const struct GNUNET_MessageHeader *temp_hdr;
   struct GNUNET_PeerIdentity tmpsource;
   int crc;
 
+  GNUNET_assert (plugin != NULL);
+
   if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
   {
 
@@ -2113,18 +2593,20 @@ wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
                      ntohs (hdr->size));
 #endif
 
-    if (ntohs (hdr->size) < sizeof (struct WlanHeader)
-        + sizeof (struct GNUNET_MessageHeader))
+    if (ntohs (hdr->size) <
+        sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
     {
       //packet not big enought
       return;
     }
 
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan whole messages received"), 1,
+                              GNUNET_NO);
     wlanheader = (struct WlanHeader *) hdr;
 
     session = search_session (plugin, endpoint, &wlanheader->source);
 
-    //tempmsg = (char*) &wlanheader[1];
     temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
     crc = ntohl (wlanheader->crc);
     wlanheader->crc = 0;
@@ -2149,13 +2631,14 @@ wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
                        sizeof (struct WlanHeader));
 #endif
       //try if it is a hello message
-      if (ntohs (wlanheader->header.size) >= ntohs (temp_hdr->size)
-          + sizeof (struct WlanHeader))
+      if (ntohs (wlanheader->header.size) >=
+          ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
       {
         if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
         {
-          if (GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
-                                   temp_hdr, &tmpsource) == GNUNET_OK)
+          if (GNUNET_HELLO_get_id
+              ((const struct GNUNET_HELLO_Message *) temp_hdr,
+               &tmpsource) == GNUNET_OK)
           {
             session = create_session (plugin, endpoint, &tmpsource);
           }
@@ -2186,8 +2669,9 @@ wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
 
     //"receive" the message
 
-    if (memcmp (&wlanheader->source, &session->target,
-                sizeof (struct GNUNET_PeerIdentity)) != 0)
+    if (memcmp
+        (&wlanheader->source, &session->target,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
       //wrong peer id
 #if DEBUG_wlan
@@ -2198,8 +2682,9 @@ wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
       return;
     }
 
-    if (memcmp (&wlanheader->target, plugin->env->my_identity,
-                sizeof (struct GNUNET_PeerIdentity)) != 0)
+    if (memcmp
+        (&wlanheader->target, plugin->env->my_identity,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
       //wrong peer id
 #if DEBUG_wlan
@@ -2220,7 +2705,8 @@ wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
   else
   {
     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
-                     "wlan_data_message_handler got wrong message type\n");
+                     "wlan_data_message_handler got wrong message type: %u\n",
+                     ntohs (hdr->size));
     return;
   }
 }
@@ -2241,12 +2727,10 @@ process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
   struct Session *session = (struct Session *) client;
   struct Plugin *plugin = (struct Plugin *) cls;
 
-  struct GNUNET_TRANSPORT_ATS_Information distance[2];
+  struct GNUNET_ATS_Information distance;
 
-  distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
-  distance[0].value = htonl (1);
-  distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
-  distance[1].value = htonl (0);
+  distance.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
+  distance.value = htonl (1);
 
 #if DEBUG_wlan
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
@@ -2258,9 +2742,8 @@ process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
 #endif
 
   plugin->env->receive (plugin->env->cls, &(session->target), hdr,
-                        (const struct GNUNET_TRANSPORT_ATS_Information *)
-                        &distance, 2, session,
-                        (const char *) &session->mac->addr,
+                        (const struct GNUNET_ATS_Information *) &distance, 1,
+                        session, (const char *) &session->mac->addr,
                         sizeof (session->mac->addr));
 }
 
@@ -2268,8 +2751,9 @@ process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
  * Function used for to process the data received from the wlan interface
  *
  * @param cls the plugin handle
- * @param session_light FIXME: document
+ * @param session_light pointer to the struct holding known informations
  * @param hdr hdr of the GNUNET_MessageHeader
+ * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS for info
  */
 static void
 wlan_data_helper (void *cls, struct Session_light *session_light,
@@ -2279,9 +2763,12 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
   struct Plugin *plugin = cls;
   struct FragmentMessage *fm;
   struct FragmentMessage *fm2;
+  struct GNUNET_PeerIdentity tmpsource;
+
+  GNUNET_assert (plugin != NULL);
 
   //ADVERTISEMENT
-  if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
+  if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
   {
 
     //TODO better DOS protection, error handling
@@ -2290,24 +2777,43 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
 
 #if DEBUG_wlan
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
-                     ntohs (hdr->size),
-                     wlan_plugin_address_to_string (NULL,
-                                                    session_light->addr.mac,
-                                                    6));
+                     "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_HELLO size: %u; %s\n",
+                     ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
+                                                                       session_light->addr.
+                                                                       mac, 6));
 #endif
 
     if (session_light->macendpoint == NULL)
     {
-      session_light->macendpoint = get_macendpoint (plugin,
-                                                    &session_light->addr,
-                                                    GNUNET_NO);
+      session_light->macendpoint =
+          get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
     }
-    GNUNET_assert (GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
-                                        &hdr[1],
-                                        &(session_light->session->target)) !=
-                   GNUNET_SYSERR);
 
+
+    if (GNUNET_HELLO_get_id
+        ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
+    {
+      session_light->session =
+          search_session (plugin, session_light->macendpoint, &tmpsource);
+      if (session_light->session == NULL)
+      {
+        session_light->session =
+            create_session (plugin, session_light->macendpoint, &tmpsource);
+      }
+      GNUNET_STATISTICS_update (plugin->env->stats,
+                                _("# wlan hello messages received"), 1,
+                                GNUNET_NO);
+      plugin->env->receive (plugin->env->cls, &session_light->session->target,
+                            hdr, NULL, 0, session_light->session,
+                            (const char *) &session_light->session->mac->addr,
+                            sizeof (session_light->session->mac->addr));
+    }
+    else
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                       "WLAN client not in session list and hello message is not okay\n");
+      return;
+    }
   }
 
   //FRAGMENT
@@ -2318,9 +2824,8 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
     GNUNET_assert (session_light != NULL);
     if (session_light->macendpoint == NULL)
     {
-      session_light->macendpoint = get_macendpoint (plugin,
-                                                    &session_light->addr,
-                                                    GNUNET_YES);
+      session_light->macendpoint =
+          get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
     }
 
 #if DEBUG_wlan
@@ -2332,6 +2837,8 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
                                                     6));
 #endif
 
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan fragments received"), 1, GNUNET_NO);
     int ret =
         GNUNET_DEFRAGMENT_process_fragment (session_light->macendpoint->defrag,
                                             hdr);
@@ -2355,9 +2862,8 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
     GNUNET_assert (session_light != NULL);
     if (session_light->macendpoint == NULL)
     {
-      session_light->macendpoint = get_macendpoint (plugin,
-                                                    &session_light->addr,
-                                                    GNUNET_NO);
+      session_light->macendpoint =
+          get_macendpoint (plugin, &session_light->addr, GNUNET_NO);
     }
 
     if (session_light->macendpoint == NULL)
@@ -2365,10 +2871,9 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
 #if DEBUG_wlan
       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                        "Macendpoint does not exist for this GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; %s\n",
-                       ntohs (hdr->size),
-                       wlan_plugin_address_to_string (NULL,
-                                                      session_light->addr.mac,
-                                                      6));
+                       ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
+                                                                         session_light->addr.mac,
+                                                                         6));
 #endif
       return;
     }
@@ -2385,11 +2890,13 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
     while (fm != NULL)
     {
       fm2 = fm->next;
+      GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks received"),
+                                1, GNUNET_NO);
       int ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
 
       if (ret == GNUNET_OK)
       {
-#if DEBUG_wlan_retransmission
+#if DEBUG_wlan_retransmission > 1
         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                          "Got last ack, finished fragment message %p\n", fm);
 #endif
@@ -2402,7 +2909,7 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
       }
       if (ret == GNUNET_NO)
       {
-#if DEBUG_wlan_retransmission
+#if DEBUG_wlan_retransmission > 1
         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                          "Got ack for: %p\n", fm);
 #endif
@@ -2417,7 +2924,7 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
       fm = fm2;
     }
 
-#if DEBUG_wlan_retransmission
+#if DEBUG_wlan_retransmission > 1
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                      "WLAN fragment not in fragment list\n");
 #endif
@@ -2441,7 +2948,11 @@ wlan_data_helper (void *cls, struct Session_light *session_light,
 
 }
 
-//TODO DOXIGEN
+/**
+ * Function to print mac addresses nice *
+ * @param pointer to 6 byte with the mac address
+ * @return pointer to the chars which hold the print out
+ */
 const char *
 macprinter (const u_int8_t * mac)
 {
@@ -2472,13 +2983,16 @@ macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       (GNUNET_TIME_absolute_add
        (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
   {
+    GNUNET_assert (endpoint->plugin != NULL);
+    GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
+                              _("# wlan mac endpoints timeouts"), 1, GNUNET_NO);
     free_macendpoint (endpoint->plugin, endpoint);
   }
   else
   {
-    endpoint->timeout_task = GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT,
-                                                           &macendpoint_timeout,
-                                                           endpoint);
+    endpoint->timeout_task =
+        GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
+                                      endpoint);
   }
 }
 
@@ -2493,22 +3007,26 @@ create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr)
 {
   struct MacEndpoint *newend = GNUNET_malloc (sizeof (struct MacEndpoint));
 
+  GNUNET_assert (plugin != NULL);
+  GNUNET_STATISTICS_update (plugin->env->stats,
+                            _("# wlan mac endpoints created"), 1, GNUNET_NO);
   newend->addr = *addr;
   newend->plugin = plugin;
   newend->addr = *addr;
   newend->fragment_messages_out_count = 0;
-  newend->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats,
-                                                     WLAN_MTU,
-                                                     MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
-                                                     newend,
-                                                     &wlan_data_message_handler,
-                                                     &add_ack_for_send);
+  newend->defrag =
+      GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
+                                        MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
+                                        newend, &wlan_data_message_handler,
+                                        &add_ack_for_send);
   newend->last_activity = GNUNET_TIME_absolute_get ();
-  newend->timeout_task = GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT,
-                                                       &macendpoint_timeout,
-                                                       newend);
+  newend->timeout_task =
+      GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
+                                    newend);
 
   plugin->mac_count++;
+  GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
+                         plugin->mac_count, GNUNET_NO);
   GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend);
 #if DEBUG_wlan
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
@@ -2538,64 +3056,96 @@ wlan_process_helper (void *cls, void *client,
   int datasize = 0;
   int pos;
 
+  GNUNET_assert (plugin != NULL);
   switch (ntohs (hdr->type))
   {
   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
 #if DEBUG_wlan
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
+                     "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
                      ntohs (hdr->size));
 #endif
 
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan WLAN_HELPER_DATA received"), 1,
+                              GNUNET_NO);
     //call wlan_process_helper with the message inside, later with wlan: analyze signal
-    if (ntohs (hdr->size) < sizeof (struct ieee80211_frame)
-        + sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_rx))
+    if (ntohs (hdr->size) <
+        sizeof (struct ieee80211_frame) +
+        2 * sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_rx))
     {
 #if DEBUG_wlan
       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                        "Size of packet is too small; size: %u min size: %u\n",
                        ntohs (hdr->size),
-                       sizeof (struct ieee80211_frame)
-                       sizeof (struct GNUNET_MessageHeader));
+                       sizeof (struct ieee80211_frame) +
+                       sizeof (struct GNUNET_MessageHeader));
 #endif
       //GNUNET_break (0);
       /* FIXME: restart SUID process */
       return;
     }
+
     rxinfo = (struct Radiotap_rx *) &hdr[1];
     wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
 
     //process only if it is an broadcast or for this computer both with the gnunet bssid
 
     //check for bssid
-    if (memcmp (&(wlanIeeeHeader->i_addr3), &mac_bssid,
-                sizeof (struct MacAddress)) == 0)
+    if (memcmp
+        (&(wlanIeeeHeader->i_addr3), &mac_bssid,
+         sizeof (struct MacAddress)) == 0)
     {
       //check for broadcast or mac
-      if (memcmp (&(wlanIeeeHeader->i_addr1), &bc_all_mac,
-                  sizeof (struct MacAddress) == 0) ||
-          memcmp (&(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
-                  sizeof (struct MacAddress)) == 0)
+      if ((memcmp
+           (&(wlanIeeeHeader->i_addr1), &bc_all_mac,
+            sizeof (struct MacAddress)) == 0) ||
+          (memcmp
+           (&(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
+            sizeof (struct MacAddress)) == 0))
       {
-
+        //if packet is from us return
+        if ((memcmp
+             (&(wlanIeeeHeader->i_addr2), &(plugin->mac_address),
+              sizeof (struct MacAddress)) == 0))
+        {
+          return;
+        }
         // process the inner data
 
 
-        datasize = ntohs (hdr->size) - sizeof (struct ieee80211_frame)
-            - sizeof (struct GNUNET_MessageHeader)
-            - sizeof (struct Radiotap_rx);
+        datasize =
+            ntohs (hdr->size) - sizeof (struct ieee80211_frame) -
+            sizeof (struct GNUNET_MessageHeader) - sizeof (struct Radiotap_rx);
 
         session_light = GNUNET_malloc (sizeof (struct Session_light));
         memcpy (&session_light->addr, &(wlanIeeeHeader->i_addr2),
                 sizeof (struct MacAddress));
         //session_light->session = search_session(plugin,session_light->addr);
+        GNUNET_STATISTICS_update (plugin->env->stats,
+                                  _("# wlan messages for this client received"),
+                                  1, GNUNET_NO);
 
         pos = 0;
         while (pos < datasize)
         {
           temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1] + pos;
-
-          wlan_data_helper (plugin, session_light, temp_hdr, rxinfo);
+          if (ntohs (temp_hdr->size) <= datasize + pos)
+          {
+            GNUNET_STATISTICS_update (plugin->env->stats,
+                                      _
+                                      ("# wlan messages inside WLAN_HELPER_DATA received"),
+                                      1, GNUNET_NO);
+            wlan_data_helper (plugin, session_light, temp_hdr, rxinfo);
+          }
+          else
+          {
+#if DEBUG_wlan
+            GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                             "Size of packet is too small; size: %u > size of packet: %u\n",
+                             ntohs (temp_hdr->size), datasize + pos);
+#endif
+          }
           pos += ntohs (temp_hdr->size);
 
         }
@@ -2623,7 +3173,6 @@ wlan_process_helper (void *cls, void *client,
     break;
   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
     //TODO more control messages
-    //TODO use struct wlan_helper_control
     if (ntohs (hdr->size) != sizeof (struct Wlan_Helper_Control_Message))
     {
       GNUNET_break (0);
@@ -2643,152 +3192,18 @@ wlan_process_helper (void *cls, void *client,
                                  sizeof (struct MacAddress));
     break;
   default:
-    GNUNET_break (0);
-    return;
-  }
-}
-
-/**
- * We have been notified that wlan-helper has written something to stdout.
- * Handle the output, then reschedule this function to be called again once
- * more is available.
- *
- * @param cls the plugin handle
- * @param tc the scheduling context
- */
-static void
-wlan_plugin_helper_read (void *cls,
-                         const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct Plugin *plugin = cls;
-
-  plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-
-  char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)];
-  ssize_t bytes;
-
-  bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf,
-                                 sizeof (mybuf));
-  if (bytes <= 0)
-  {
 #if DEBUG_wlan
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     _
-                     ("Finished reading from wlan-helper stdout with code: %d\n"),
-                     bytes);
-#endif
-    return;
-  }
-  GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes,
-                             GNUNET_NO, GNUNET_NO);
-
-  GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
-  plugin->server_read_task =
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      plugin->server_stdout_handle,
-                                      &wlan_plugin_helper_read, plugin);
-}
-
-/**
- * Start the gnunet-wlan-helper process.
- *
- * @param plugin the transport plugin
- * @param testmode should we use the dummy driver for testing?
- * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
- */
-static int
-wlan_transport_start_wlan_helper (struct Plugin *plugin, int testmode)
-{
-  const char *filenamehw = "gnunet-transport-wlan-helper";
-  const char *filenameloopback = "gnunet-transport-wlan-helper-dummy";
-
-  plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
-  if (plugin->server_stdout == NULL)
-    return GNUNET_SYSERR;
-
-  plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
-  if (plugin->server_stdin == NULL)
-    return GNUNET_SYSERR;
-
-  /* Start the server process */
-
-  if (testmode == 0)
-  {
-
-#if DEBUG_wlan
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Starting gnunet-wlan-helper process cmd: %s %s %i\n",
-                     filenamehw, plugin->interface, testmode);
-#endif
-
-    plugin->server_proc = GNUNET_OS_start_process (plugin->server_stdin,
-                                                   plugin->server_stdout,
-                                                   filenamehw, filenamehw,
-                                                   plugin->interface, NULL);
-  }
-  else if (testmode == 1)
-  {
-
-#if DEBUG_wlan
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Starting gnunet-wlan-helper loopback 1 process cmd: %s %s %i\n",
-                     filenameloopback, plugin->interface, testmode);
-#endif
+                     "Func wlan_process_helper got unknown message with number %u, size %u\n",
+                     ntohs (hdr->type), ntohs (hdr->size));
 
-    plugin->server_proc = GNUNET_OS_start_process (plugin->server_stdin,
-                                                   plugin->server_stdout,
-                                                   filenameloopback,
-                                                   filenameloopback, "1", NULL);
-  }
-  else if (testmode == 2)
-  {
-#if DEBUG_wlan
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Starting gnunet-wlan-helper loopback 2 process cmd: %s %s %i\n",
-                     filenameloopback, plugin->interface, testmode);
 #endif
-    plugin->server_proc = GNUNET_OS_start_process (plugin->server_stdin,
-                                                   plugin->server_stdout,
-                                                   filenameloopback,
-                                                   filenameloopback, "2", NULL);
-  }
-  if (plugin->server_proc == NULL)
-  {
-#if DEBUG_wlan
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                     "Failed to start gnunet-wlan-helper process\n");
+#if DEBUG_wlan_msg_dump > 1
+    hexdump (hdr, GNUNET_MIN (ntohs (hdr->size), 256));
 #endif
-    return GNUNET_SYSERR;
+    GNUNET_break (0);
+    return;
   }
-
-  /* Close the write end of the read pipe */
-  GNUNET_DISK_pipe_close_end (plugin->server_stdout,
-                              GNUNET_DISK_PIPE_END_WRITE);
-
-  /* Close the read end of the write pipe */
-  GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
-
-  plugin->server_stdout_handle = GNUNET_DISK_pipe_handle (plugin->server_stdout,
-                                                          GNUNET_DISK_PIPE_END_READ);
-  plugin->server_stdin_handle = GNUNET_DISK_pipe_handle (plugin->server_stdin,
-                                                         GNUNET_DISK_PIPE_END_WRITE);
-
-  GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
-
-#if DEBUG_wlan
-  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
-                   "Adding server_read_task for the wlan-helper\n");
-#endif
-
-  plugin->server_read_task =
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      plugin->server_stdout_handle,
-                                      &wlan_plugin_helper_read, plugin);
-
-  return GNUNET_YES;
 }
 
 /**
@@ -2810,10 +3225,7 @@ libgnunet_plugin_transport_wlan_done (void *cls)
                    "libgnunet_plugin_transport_wlan_done started\n");
 #endif
 
-  GNUNET_DISK_pipe_close (plugin->server_stdout);
-  GNUNET_DISK_pipe_close (plugin->server_stdin);
-  GNUNET_OS_process_kill (plugin->server_proc, 9);
-  GNUNET_OS_process_close (plugin->server_proc);
+  wlan_transport_stop_wlan_helper (plugin);
 
   GNUNET_assert (cls != NULL);
   //free sessions
@@ -2824,21 +3236,7 @@ libgnunet_plugin_transport_wlan_done (void *cls)
     endpoint = endpoint_next;
 
   }
-  if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
-    plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (plugin->server_write_task);
-    plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (plugin->server_read_task);
-    plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
-  }
+
 
   if (plugin->suid_tokenizer != NULL)
     GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
@@ -2865,14 +3263,17 @@ libgnunet_plugin_transport_wlan_init (void *cls)
   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *api;
   struct Plugin *plugin;
-  static unsigned long long testmode = 0;
 
   GNUNET_assert (cls != NULL);
 
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
   plugin->pendingsessions = 0;
+  GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                         plugin->pendingsessions, GNUNET_NO);
   plugin->mac_count = 0;
+  GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
+                         plugin->mac_count, GNUNET_NO);
   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
@@ -2880,8 +3281,8 @@ libgnunet_plugin_transport_wlan_init (void *cls)
                                  GNUNET_BANDWIDTH_value_init (100 * 1024 *
                                                               1024 / 8), 100);
 
-  plugin->suid_tokenizer = GNUNET_SERVER_mst_create (&wlan_process_helper,
-                                                     plugin);
+  plugin->suid_tokenizer =
+      GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
 
   plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
 
@@ -2895,23 +3296,22 @@ libgnunet_plugin_transport_wlan_init (void *cls)
   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
   api->check_address = &wlan_plugin_address_suggested;
   api->address_to_string = &wlan_plugin_address_to_string;
+
   //read config
 
   if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
   {
-    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (env->cfg,
-                                                                "transport-wlan",
-                                                                "TESTMODE",
-                                                                &testmode))
-      testmode = 0;             //default value
+    if (GNUNET_SYSERR ==
+        GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
+                                               "TESTMODE", &(plugin->testmode)))
+      plugin->testmode = 0;     //default value
   }
 
   if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE"))
   {
-    if (GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-wlan",
-                                               "INTERFACE",
-                                               &(plugin->interface)) !=
-        GNUNET_YES)
+    if (GNUNET_CONFIGURATION_get_value_string
+        (env->cfg, "transport-wlan", "INTERFACE",
+         &(plugin->interface)) != GNUNET_YES)
     {
       libgnunet_plugin_transport_wlan_done (api);
       return NULL;
@@ -2919,10 +3319,9 @@ libgnunet_plugin_transport_wlan_init (void *cls)
   }
 
   //start the plugin
+  wlan_transport_start_wlan_helper (plugin);
   set_next_beacon_time (plugin);
-
-  wlan_transport_start_wlan_helper (plugin, testmode);
-
+  set_next_send (plugin);
 #if DEBUG_wlan
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
                    "wlan init finished\n");