-makefile for new test_stream_local (commented)
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
index f8178f101cd4c6b8f6c8f2bc68787e705b02c5b5..a3d90b5982988cd25589e4f9a2b809eb5342762d 100644 (file)
@@ -1,29 +1,32 @@
 /*
- This file is part of GNUnet
(C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
 This file is part of GNUnet
 (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
 
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
 GNUnet is 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.
 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.
- */
 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/plugin_transport_wlan.c
  * @brief transport plugin for wlan
  * @author David Brodski
+ * @author Christian Grothoff
  */
 
+//TODO split rx and tx structures for better handling
+
 #include "platform.h"
 #include "gnunet_hello_lib.h"
 #include "gnunet_protocols.h"
 #include "plugin_transport_wlan.h"
 #include "gnunet_common.h"
 #include "gnunet_crypto_lib.h"
-#include "wlan/ieee80211.h"
+#include "gnunet_fragmentation_lib.h"
+#include "gnunet_constants.h"
+
+/**
+ * DEBUG switch
+ */
+#define DEBUG_WLAN GNUNET_EXTRA_LOGGING
 
-#include <string.h>
 
 #define PROTOCOL_PREFIX "wlan"
 
+#define PLUGIN_LOG_NAME "wlan-plugin"
+
 /**
- * Max size of packet from helper
+ * Max size of packet
  */
-#define WLAN_MTU 3000
+#define WLAN_MTU 1430
 
 /**
- * Time until retransmission of a fragment in ms
+ * time out of a session
  */
-#define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
+#define SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
 
-#define FRAGMENT_QUEUE_SIZE 10
-#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
+/**
+ * time out of a mac endpoint
+ */
+#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
 
-#define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
+/**
+ * scaling factor for hello beacon
+ */
+#define HELLO_BEACON_SCALING_FACTOR 30
 
-#define MESSAGES_IN_QUEUE_SIZE 10
-#define MESSAGES_IN_QUEUE_PER_SESSION 1
+/**
+ * scaling factor for restarting the helper
+ */
+#define HELPER_RESTART_SCALING_FACTOR 2
 
-#define HALLO_BEACON_SCALING_FACTOR 900
+/**
+ * max size of fragment queue
+ */
+#define FRAGMENT_QUEUE_SIZE 10
+/**
+ * max messages in fragment queue per session/client
+ */
+#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
 
-#define DEBUG_wlan GNUNET_YES
-#define DEBUG_wlan_retransmission GNUNET_NO
+/**
+ * max messages in fragment queue per MAC
+ */
+#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT 1
 
-#define MESSAGE_LENGHT_UNKNOWN -1
-//#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
+/**
+ * max messages in in queue
+ */
+#define MESSAGES_IN_QUEUE_SIZE 10
 
 /**
- * After how long do we expire an address that we
- * learned from another peer if it is not reconfirmed
- * by anyone?
+ * max messages in in queue per session/client
  */
-#define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
+#define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 1
 
 /**
- * Initial handshake message for a session.
+ * Link layer control fields for better compatibility
+ * (i.e. GNUnet over WLAN is not IP-over-WLAN).
  */
-struct WelcomeMessage
-{
-  /**
-   * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
-   */
-  struct GNUNET_MessageHeader header;
+#define WLAN_LLC_DSAP_FIELD 0x1f
+#define WLAN_LLC_SSAP_FIELD 0x1f
 
-  /**
-   * Identit*mac_y of the node connecting (TCP client)
-   */
-  struct GNUNET_PeerIdentity clientIdentity;
 
-};
 
 /**
  * Encapsulation of all of the state of the plugin.
@@ -101,47 +119,47 @@ struct Plugin
   struct GNUNET_TRANSPORT_PluginEnvironment *env;
 
   /**
-   * List of open sessions. head
+   * List of open connections. head
    */
-  struct Sessionqueue *sessions;
+  struct MacEndpoint *mac_head;
 
   /**
-   * List of open sessions. tail
+   * List of open connections. tail
    */
-  struct Sessionqueue *sessions_tail;
+  struct MacEndpoint *mac_tail;
 
   /**
-   * Number of sessions
+   * Number of connections
    */
-  unsigned int session_count;
+  unsigned int mac_count;
 
   /**
    * encapsulation of data from the local wlan helper program
    */
-  struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
+  struct GNUNET_SERVER_MessageStreamTokenizer *suid_tokenizer;
 
   /**
-   * encapsulation of packets received
+   * encapsulation of packets received from the wlan helper
    */
-  struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
+  struct GNUNET_SERVER_MessageStreamTokenizer *data_tokenizer;
 
   /**
-   * stdout pipe handle for the gnunet-wlan-helper process
+   * stdout pipe handle for the gnunet-helper-transport-wlan process
    */
   struct GNUNET_DISK_PipeHandle *server_stdout;
 
   /**
-   * stdout file handle for the gnunet-wlan-helper process
+   * stdout file handle for the gnunet-helper-transport-wlan process
    */
   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
 
   /**
-   * stdin pipe handle for the gnunet-wlan-helper process
+   * stdin pipe handle for the gnunet-helper-transport-wlan process
    */
   struct GNUNET_DISK_PipeHandle *server_stdin;
 
   /**
-   * stdin file handle for the gnunet-wlan-helper process
+   * stdin file handle for the gnunet-helper-transport-wlan process
    */
   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
 
@@ -170,22 +188,27 @@ 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.
    */
-  struct MacAddress mac_address;
+  struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address;
 
   /**
    * Sessions currently pending for transmission
-   * to this peer, if any.
+   * to a peer, if any.
    */
-  struct Sessionqueue * pending_Sessions;
+  struct Sessionqueue *pending_Sessions_head;
 
   /**
    * Sessions currently pending for transmission
-   * to this peer (tail), if any.
+   * to a peer (tail), if any.
    */
-  struct Sessionqueue * pending_Sessions_tail;
+  struct Sessionqueue *pending_Sessions_tail;
 
   /**
    * number of pending sessions
@@ -193,24 +216,19 @@ struct Plugin
   unsigned int pendingsessions;
 
   /**
-   * Messages in the fragmentation queue, head
-   */
-  struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
-
-  /**
-   * Messages in the in Queue, head
+   * Messages in the sending queues
    */
-  struct Receive_Message_Queue * receive_messages_head;
+  int pending_Fragment_Messages;
 
   /**
-   * Messages in the in Queue, tail
+   * messages ready for send, head
    */
-  struct Receive_Message_Queue * receive_messages_teil;
+  struct FragmentMessage_queue *sending_messages_head;
 
   /**
-   * number of messages in the in queue
+   * messages ready for send, tail
    */
-  unsigned int pending_receive_messages;
+  struct FragmentMessage_queue *sending_messages_tail;
 
   /**
    * time of the next "hello-beacon"
@@ -220,13 +238,22 @@ struct Plugin
   /**
    * queue to send acks for received fragments (head)
    */
-  struct AckSendQueue * ack_send_queue_head;
+  struct AckSendQueue *ack_send_queue_head;
 
   /**
    * queue to send acks for received fragments (tail)
    */
-  struct AckSendQueue * ack_send_queue_tail;
+  struct AckSendQueue *ack_send_queue_tail;
+
+  /**
+   * Tracker for bandwidth limit
+   */
+  struct GNUNET_BANDWIDTH_Tracker tracker;
 
+  /**
+   * saves the current state of the helper process
+   */
+  int helper_is_running;
 };
 
 /**
@@ -234,99 +261,119 @@ struct Plugin
  */
 struct Finish_send
 {
-  struct Plugin * plugin;
-  char * msgheader;
-  struct GNUNET_MessageHeader * msgstart;
+  /**
+   * pointer to the global plugin struct
+   */
+  struct Plugin *plugin;
+
+  /**
+   * head of the next part to send to the helper
+   */
+  const 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;
-  struct GNUNET_TIME_Absolute next_send;
 };
 
 /**
  * Queue of sessions, for the general session queue and the pending session queue
  */
-
+//TODO DOXYGEN
 struct Sessionqueue
 {
-  struct Sessionqueue * next;
-  struct Sessionqueue * prev;
-  struct Session * content;
+  struct Sessionqueue *next;
+  struct Sessionqueue *prev;
+  struct Session *content;
+#if !HAVE_UNALIGNED_64_ACCESS
+  void *dummy;                  /* for alignment, see #1909 */
+#endif
+};
+
+
+/**
+ * Queue of fragmented messages, for the sending queue of the plugin
+ */
+//TODO DOXYGEN
+struct FragmentMessage_queue
+{
+  struct FragmentMessage_queue *next;
+  struct FragmentMessage_queue *prev;
+  struct FragmentMessage *content;
 };
 
+
 /**
  * Queue for the fragments received
  */
+//TODO DOXYGEN
 struct Receive_Fragment_Queue
 {
-  struct Receive_Fragment_Queue * next;
-  struct Receive_Fragment_Queue * prev;
+  struct Receive_Fragment_Queue *next;
+  struct Receive_Fragment_Queue *prev;
+
   uint16_t num;
-  const char * msg;
-  uint16_t size;
-  struct Radiotap_rx rxinfo;
+  // const char *msg;
+  //   uint16_t size;
+  struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rx_msg;
 };
 
-struct Session_id_pair
+
+//TODO DOXYGEN
+struct MacEndpoint_id_fragment_triple
 {
-  struct Session * session;
+  struct MacEndpoint *endpoint;
   uint32_t message_id;
+  struct FragmentMessage *fm;
 };
 
+//TODO DOXYGEN
 struct Plugin_Session_pair
 {
-  struct Plugin * plugin;
-  struct Session * session;
+  struct Plugin *plugin;
+  struct Session *session;
 };
 
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
 /**
- * Queue for the fragments received
+ * Header for messages which need fragmentation
  */
-struct Receive_Message_Queue
+struct WlanHeader
 {
-  struct Receive_Message_Queue * next;
-
-  struct Receive_Message_Queue * prev;
-
-  /**
-   * current number for message incoming, to distinguish between the messages
-   */
-  uint32_t message_id_in;
 
   /**
-   * size of the message received,
-   * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
-   * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
+   * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA.
    */
-  int rec_size;
-
-  /**
-   * Sorted queue with the fragments received; head
-   */
-
-  struct Receive_Fragment_Queue * frag_head;
+  struct GNUNET_MessageHeader header;
 
   /**
-   * Sorted queue with the fragments received; tail
+   * checksum/error correction
    */
-
-  struct Receive_Fragment_Queue * frag_tail;
+  uint32_t crc GNUNET_PACKED;
 
   /**
-   * Session this fragment belongs to
+   * To whom are we talking to (set to our identity
+   * if we are still waiting for the welcome message)
    */
-
-  struct Session * session;
+  struct GNUNET_PeerIdentity target;
 
   /**
-   * Timeout value for the pending message.
+   *  Where the packet came from
    */
-  struct GNUNET_TIME_Absolute timeout;
+  struct GNUNET_PeerIdentity source;
 
-  /**
-   * Bitfield of received fragments
-   */
+// followed by payload
 
-  uint64_t received_fragments;
 };
+GNUNET_NETWORK_STRUCT_END
 
 /**
  * Information kept for each message that is yet to
@@ -334,11 +381,20 @@ struct Receive_Message_Queue
  */
 struct PendingMessage
 {
+  /**
+   * dll next
+   */
+  struct PendingMessage *next;
+
+  /**
+   * dll prev
+   */
+  struct PendingMessage *prev;
 
   /**
    * The pending message
    */
-  char *msg;
+  struct WlanHeader *msg;
 
   /**
    * Size of the message
@@ -355,7 +411,7 @@ struct PendingMessage
   /**
    * Cls for transmit_cont
    */
-  void * transmit_cont_cls;
+  void *transmit_cont_cls;
 
   /**
    * Timeout value for the pending message.
@@ -364,45 +420,40 @@ struct PendingMessage
 
 };
 
+
 /**
  * Queue for acks to send for fragments recived
  */
-//TODO comments
 struct AckSendQueue
 {
 
-  struct AckSendQueue * next;
-  struct AckSendQueue * prev;
-
-  struct Session * session;
   /**
-   * ID of message, to distinguish between the messages, picked randomly.
+   * next ack in the ack send queue
    */
-  uint32_t message_id;
+  struct AckSendQueue *next;
 
   /**
-   * Bit field for received fragments
+   * previous ack in the ack send queue
    */
-  uint64_t fragments_field;
-
-};
+  struct AckSendQueue *prev;
 
-/**
- * Session infos gathered from a messages
- */
+  /**
+   * pointer to the session this ack belongs to
+   */
+  struct MacEndpoint *endpoint;
 
-struct Session_light
-{
   /**
-   * the session this message belongs to
+   * ID of message, to distinguish between the messages, picked randomly.
    */
-  struct Session * session;
+  uint32_t message_id;
+
   /**
-   * peer mac address
+   * pointer to the radiotap header with the ACK Message.
    */
-  struct MacAddress addr;
+  const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
 };
 
+
 /**
  * Session handle for connections.
  */
@@ -414,22 +465,17 @@ struct Session
    */
   struct SessionHeader header;
 
-  /**
-   * Pointer to the global plugin struct.
-   */
-  struct Plugin *plugin;
-
   /**
    * Message currently pending for transmission
-   * to this peer, if any.
+   * to this peer, if any. head
    */
-  struct PendingMessage *pending_message;
+  struct PendingMessage *pending_message_head;
 
   /**
    * Message currently pending for transmission
-   * to this peer, if any.
+   * to this peer, if any. tail
    */
-  struct PendingMessage *pending_message2;
+  struct PendingMessage *pending_message_tail;
 
   /**
    * To whom are we talking to (set to our identity
@@ -437,11 +483,6 @@ struct Session
    */
   struct GNUNET_PeerIdentity target;
 
-  /**
-   * peer mac address
-   */
-  struct MacAddress addr;
-
   /**
    * Address of the other peer (either based on our 'connect'
    * call or on our 'accept' call).
@@ -450,193 +491,288 @@ struct Session
 
   /**
    * Last activity on this connection.  Used to select preferred
-   * connection.
+   * connection and timeout
    */
   struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   * count of messages in the fragment out queue for this session
+   * Timeout task.
    */
-
-  int fragment_messages_out_count;
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
   /**
-   * count of messages in the fragment in queue for this session
+   * peer connection
    */
+  struct MacEndpoint *mac;
 
-  int fragment_messages_in_count;
+  /**
+   * count of messages in the fragment out queue for this session
+   */
 
-  //TODO DOXIGEN
-  uint8_t rate;
-  uint16_t tx_power;
-  uint8_t antenna;
+  int fragment_messages_out_count;
 
 };
 
 /**
- * Struct for Messages in the fragment queue
+ * Struct to represent one network card connection
  */
-
-struct FragmentMessage
+struct MacEndpoint
 {
   /**
-   * heap pointer of this message
+   * Pointer to the global plugin struct.
    */
-  struct GNUNET_CONTAINER_HeapNode * node;
+  struct Plugin *plugin;
 
   /**
-   * Session this message belongs to
+   * Struct to hold the session reachable over this mac; head
    */
+  struct Sessionqueue *sessions_head;
 
-  struct Session *session;
+  /**
+   * Struct to hold the session reachable over this mac; tail
+   */
+  struct Sessionqueue *sessions_tail;
 
   /**
-   * This is a doubly-linked list.
+   * Messages currently sending
+   * to a peer, if any.
    */
-  struct FragmentMessage *next;
+  struct FragmentMessage *sending_messages_head;
 
   /**
-   * This is a doubly-linked list.
+   * Messages currently sending
+   * to a peer (tail), if any.
    */
-  struct FragmentMessage *prev;
+  struct FragmentMessage *sending_messages_tail;
 
   /**
-   * The pending message
+   * dll next
+   */
+  struct MacEndpoint *next;
+
+  /**
+   * dll prev
    */
-  char *msg;
+  struct MacEndpoint *prev;
 
   /**
-   * 0 if not in ack queue
-   * 1 if in ack queue
+   * peer mac address
    */
+  struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
 
-  char in_ack_queue;
+  /**
+   * Defrag context for this mac endpoint
+   */
+  struct GNUNET_DEFRAGMENT_Context *defrag;
 
   /**
-   * Timeout value for the pending message.
+   * count of messages in the fragment out queue for this mac endpoint
    */
-  struct GNUNET_TIME_Absolute timeout;
+  int fragment_messages_out_count;
+
+  //TODO DOXYGEN
+  uint8_t rate;
+  uint16_t tx_power;
+  uint8_t antenna;
 
   /**
-   * Timeout value for the pending fragments.
-   * Stores the time when the next msg fragment ack has to be received
+   * Duplicates received
    */
-  struct GNUNET_TIME_Absolute next_ack;
+  int dups;
 
   /**
-   * bitfield with all acks received for this message
+   * Fragments received
    */
-  uint64_t ack_bitfield;
+  int fragc;
 
   /**
-   * Size of the message
+   * Acks received
    */
-  size_t message_size;
+  int acks;
 
   /**
-   * pos / next fragment number in the message, for fragmentation/segmentation,
-   * some acks can be missing but there is still time
+   * Last activity on this endpoint.  Used to select preferred
+   * connection.
    */
-  uint32_t message_pos;
+  struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   * current number for message outgoing, to distinguish between the messages
+   * Timeout task.
    */
-  uint32_t message_id_out;
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 };
 
 /**
- * Header for messages which need fragmentation
+ * Struct for Messages in the fragment queue
  */
-struct FragmentationAckHeader
+struct FragmentMessage
 {
 
-  struct GNUNET_MessageHeader header;
+  /**
+   * Session this message belongs to
+   */
+  struct Session *session;
 
   /**
-   * ID of message, to distinguish between the messages, picked randomly.
+   * This is a doubly-linked list.
+   */
+  struct FragmentMessage *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct FragmentMessage *prev;
+
+  /**
+   * Fragmentation context
+   */
+  struct GNUNET_FRAGMENT_Context *fragcontext;
+
+  /**
+   * Timeout value for the message.
    */
-  uint32_t message_id GNUNET_PACKED;
+  struct GNUNET_TIME_Absolute timeout;
 
   /**
-   * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
+   * Timeout task.
    */
-  uint64_t fragment_field GNUNET_PACKED;
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
+  /**
+   * pointer to the radiotap header
+   */
+  struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
 };
 
-static struct FragmentMessage * return_val;
 
 static void
-do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
 
-/**
- * Sets a bit active in the bitArray. Increment bit-specific
- * usage counter on disk only if below 4bit max (==15).
- *
- * @param bitArray memory area to set the bit in
- * @param bitIdx which bit to set
- */
 static void
-setBit(char *bitArray, unsigned int bitIdx)
-{
-  size_t arraySlot;
-  unsigned int targetBit;
+free_session (struct Plugin *plugin, struct Sessionqueue *queue,
+              int do_free_macendpoint);
+
+
+static struct MacEndpoint *
+create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr);
+
+
+static void
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
-  arraySlot = bitIdx / 8;
-  targetBit = (1L << (bitIdx % 8));
-  bitArray[arraySlot] |= targetBit;
-}
 
 /**
- * Checks if a bit is active in the bitArray
+ * Generates a nice hexdump of a memory area.
  *
- * @param bitArray memory area to set the bit in
- * @param bitIdx which bit to test
- * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
+ * \param  mem     pointer to memory to dump
+ * \param  length  how many bytes to dump
  */
-static int
-testBit(char *bitArray, unsigned int bitIdx)
+static void
+hexdump (const void *mem, unsigned length)
 {
-  size_t slot;
-  unsigned int targetBit;
+  char line[80];
+  char *src = (char *) mem;
 
-  slot = bitIdx / 8;
-  targetBit = (1L << (bitIdx % 8));
-  if (bitArray[slot] & targetBit)
-    return GNUNET_YES;
-  return GNUNET_NO;
+  printf ("dumping %u bytes from %p\r\n"
+          "       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF\r\n",
+          length, src);
+  unsigned i;
+  int j;
+
+  for (i = 0; i < length; i += 16, src += 16)
+  {
+    char *t = line;
+
+    t += sprintf (t, "%04x:  ", i);
+    for (j = 0; j < 16; j++)
+    {
+      if (i + j < length)
+        t += sprintf (t, "%02X", src[j] & 0xff);
+      else
+        t += sprintf (t, "  ");
+
+      t += sprintf (t, (j % 2) ? " " : "-");
+    }
+
+    t += sprintf (t, "  ");
+    for (j = 0; j < 16; j++)
+    {
+      if (i + j < length)
+      {
+        if (isprint ((unsigned char) src[j]))
+          t += sprintf (t, "%c", src[j]);
+        else
+          t += sprintf (t, ".");
+      }
+      else
+      {
+        t += sprintf (t, " ");
+      }
+    }
+
+    t += sprintf (t, "\r\n");
+    printf ("%s", line);
+  }
 }
 
+
 /**
- * get the next message number, at the moment just a random one
- * @return returns the next valid message-number for sending packets
+ * Function to find a MacEndpoint with a specific mac addr
+ * @param plugin pointer to the plugin struct
+ * @param addr pointer to the mac address
+ * @param create_new GNUNET_YES if a new end point should be created
+ * @return
  */
-static uint32_t
-get_next_message_id()
+static struct MacEndpoint *
+get_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
+                 int create_new)
 {
-  return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+  struct MacEndpoint *queue = plugin->mac_head;
+
+  while (queue != NULL)
+  {
+    //GNUNET_assert (queue->sessions_head != NULL);
+    if (memcmp (addr, &queue->addr, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
+      return queue;             /* session found */
+    queue = queue->next;
+  }
+
+  if (create_new == GNUNET_YES)
+  {
+    return create_macendpoint (plugin, addr);
+  }
+  else
+  {
+    return NULL;
+  }
 }
 
+
 /**
- * search for a session with the addr
+ * 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
  */
 static struct Session *
-search_session(struct Plugin *plugin, const struct MacAddress *addr)
+search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
+                const struct GNUNET_PeerIdentity *peer)
 {
-  struct Sessionqueue * queue = plugin->sessions;
+  GNUNET_assert (endpoint != NULL);
+  struct Sessionqueue *queue = endpoint->sessions_head;
 
   while (queue != NULL)
-    {
-      GNUNET_assert (queue->content != NULL);
-      if (memcmp(addr, &queue->content->addr, sizeof(struct MacAddress)) == 0)
-        return queue->content; /* session found */
-      queue = queue->next;
-    }
+  {
+    GNUNET_assert (queue->content != NULL);
+    if (memcmp
+        (peer, &queue->content->target,
+         sizeof (struct GNUNET_PeerIdentity)) == 0)
+      return queue->content;    /* session found */
+    queue = queue->next;
+  }
   return NULL;
 }
 
@@ -651,69 +787,117 @@ search_session(struct Plugin *plugin, const struct MacAddress *addr)
  * @param addrlen length of the address
  * @return string representing the same address
  */
-static const char*
-wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
+static const char *
+wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
 {
   static char ret[40];
-  const struct MacAddress *mac;
+  const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
 
-  if (addrlen != sizeof(struct MacAddress))
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
+  if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
   mac = addr;
-  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]);
+  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;
 }
 
+/**
+ * Function for the scheduler if a session times out
+ * @param cls pointer to the Sessionqueue
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ */
+static void
+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)
+  {
+    return;
+  }
+  if (GNUNET_TIME_absolute_get_remaining
+      (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
+  {
+    queue->content->timeout_task =
+        GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
+  }
+}
+
 /**
  * create a new session
  *
  * @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 peer identity to use for this session
  * @return returns the session
  */
-
 static struct Session *
-create_session(struct Plugin *plugin, const struct MacAddress * addr)
-{
-  struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
-
-  GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
-
-  queue->content = GNUNET_malloc (sizeof (struct Session));
-  queue->content->plugin = plugin;
-  queue->content->addr = *addr;
-  queue->content->fragment_messages_out_count = 0;
-  queue->content->fragment_messages_in_count = 0;
-
-  plugin->session_count++;
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
-      queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
-#endif
-
-  return queue->content;
-}
+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));
+
+  GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
+                                    endpoint->sessions_tail, queue);
+
+  queue->content = (struct Session *) &queue[1];
+  queue->content->mac = endpoint;
+  queue->content->target = *peer;
+  queue->content->last_activity = GNUNET_TIME_absolute_get ();
+  queue->content->timeout_task =
+      GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "New session %p with endpoint %p: %s\n", queue->content,
+                   endpoint, wlan_plugin_address_to_string (NULL,
+                                                            endpoint->addr.mac,
+                                                            6));
+  return queue->content;
+}
 
 /**
  * Get session from address, create if no session exists
  *
  * @param plugin pointer to the plugin struct
  * @param addr pointer to the mac address of the peer
+ * @param peer pointer to the peerid
  * @return returns the session
  */
 static struct Session *
-get_session(struct Plugin *plugin, const struct MacAddress *addr)
+get_session (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
+             const struct GNUNET_PeerIdentity *peer)
 {
-  struct Session * session = search_session(plugin, addr);
+  struct MacEndpoint *mac;
+
+  mac = get_macendpoint (plugin, addr, GNUNET_YES);
+  struct Session *session = search_session (plugin, mac, peer);
+
   if (session != NULL)
     return session;
-  return create_session(plugin, addr);
+  return create_session (plugin, mac, peer);
 }
 
 /**
@@ -724,164 +908,161 @@ get_session(struct Plugin *plugin, const struct MacAddress *addr)
  * @param session pointer to the session to add
  */
 static void
-queue_session(struct Plugin *plugin, struct Session * session)
+queue_session (struct Plugin *plugin, struct Session *session)
 {
-  struct Sessionqueue * queue = plugin->pending_Sessions;
-  struct Sessionqueue * lastitem = NULL;
+  struct Sessionqueue *queue = plugin->pending_Sessions_head;
 
-  if (session->pending_message != NULL)
+  if (session->pending_message_head != NULL)
+  {
+    while (queue != NULL)
     {
-      while (queue != NULL)
-        {
-          // content is never NULL
-          GNUNET_assert (queue->content != NULL);
-          // is session already in queue?
-          if (session == queue->content)
-            {
-              return;
-            }
-          // try next
-          lastitem = queue;
-          queue = queue->next;
-        }
+      // content is never NULL
+      GNUNET_assert (queue->content != NULL);
+      // is session already in queue?
+      if (session == queue->content)
+      {
+        return;
+      }
+      // try next
+      queue = queue->next;
+    }
 
-      // Session is not in the queue
+    // Session is not in the queue
 
-      queue = GNUNET_malloc (sizeof (struct Sessionqueue));
-      queue->content = session;
+    queue = GNUNET_malloc (sizeof (struct Sessionqueue));
+    queue->content = session;
 
-      //insert at the tail
-      GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions,
-          plugin->pending_Sessions_tail, queue);
-      plugin->pendingsessions++;
-    }
+    //insert at the tail
+    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);
+  }
 
 }
 
-//TODO doxigen
 /**
  * Function to schedule the write task, executed after a delay
+ * @param cls pointer to the plugin struct
+ * @param tc GNUNET_SCHEDULER_TaskContext pointer
  */
 static void
-delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct Plugin * plugin = cls;
+  struct Plugin *plugin = cls;
+
   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
 
   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
   if (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,
-          &do_transmit, plugin);
-    }
+  {
+    plugin->server_write_task =
+        GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         plugin->server_stdin_handle,
+                                         &do_transmit, plugin);
+  }
 }
 
-//TODO doxigen
 /**
  * Function to calculate the time of the next periodic "hello-beacon"
+ * @param plugin pointer to the plugin struct
  */
 static void
-set_next_beacon_time(struct Plugin * const plugin)
+set_next_beacon_time (struct Plugin *const plugin)
 {
   //under 10 known peers: once a second
-  if (plugin->session_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));
-    }
+  if (plugin->mac_count < 10)
+  {
+    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->session_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));
-    }
+  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 * 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));
+  }
 }
 
-//TODO doxigen
-/*
- static struct GNUNET_TIME_Relative
- get_next_frag_timeout(struct FragmentMessage * fm)
- {
- return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
- fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
- }
- */
-
-//TODO doxigen
-/**
- * Function to get the timeout value for acks for this session
- */
-
-static struct GNUNET_TIME_Relative
-get_ack_timeout(struct FragmentMessage * fm)
-{
-  return FRAGMENT_TIMEOUT;
-}
 
 /**
  * Function to set the timer for the next timeout of the fragment queue
  * @param plugin the handle to the plugin struct
  */
-
 static void
-set_next_send(struct Plugin * const plugin)
+set_next_send (struct Plugin *plugin)
 {
-  struct FragmentMessage * fm;
   struct GNUNET_TIME_Relative next_send;
-  struct GNUNET_TIME_Absolute next_send_tmp;
+
+  //abort if helper is not running
+  if (plugin->helper_is_running == GNUNET_NO)
+  {
+    return;
+  }
 
   //cancel old task
   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;
-    }
-
-  fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
+  {
+    GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
+    plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
+  }
 
   //check if some acks are in the queue
   if (plugin->ack_send_queue_head != NULL)
-    {
-      next_send = GNUNET_TIME_UNIT_ZERO;
-    }
+  {
+    next_send = GNUNET_TIME_UNIT_ZERO;
+  }
 
   //check if there are some fragments in the queue
+  else if (plugin->sending_messages_head != NULL)
+  {
+    next_send = GNUNET_TIME_UNIT_ZERO;
+  }
   else
+  {
+    next_send = GNUNET_TIME_absolute_get_remaining (plugin->beacon_time);
+  }
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Next packet is send in: %u\n", next_send.rel_value);
+  if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
+  {
+    if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
     {
-      next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
-      if (fm != NULL)
-        {
-          next_send_tmp.abs_value = GNUNET_CONTAINER_heap_node_get_cost(
-              fm->node);
-          next_send = GNUNET_TIME_relative_min(next_send,
-              GNUNET_TIME_absolute_get_remaining(next_send_tmp));
-
-        }
+      plugin->server_write_task =
+          GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                           plugin->server_stdin_handle,
+                                           &do_transmit, plugin);
     }
-
-#if DEBUG_wlan
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
-      next_send.rel_value);
-
-#endif
-
-  plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
-      &delay_fragment_task, plugin);
-
+  }
+  else
+  {
+    if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
+    {
+      plugin->server_write_delay_task =
+          GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
+                                        plugin);
+    }
+  }
 }
 
 /**
@@ -890,78 +1071,93 @@ set_next_send(struct Plugin * const plugin)
  * @return pointer to the session found, returns NULL if there is now session in the queue
  */
 static struct Session *
-get_next_queue_session(struct Plugin * plugin)
+get_next_queue_session (struct Plugin *plugin)
 {
-  struct Session * session;
-  struct Sessionqueue * sessionqueue;
-  struct Sessionqueue * sessionqueue_alt;
-  struct PendingMessage * pm;
-  sessionqueue = plugin->pending_Sessions;
+  struct Session *session;
+  struct Sessionqueue *sessionqueue;
+  struct Sessionqueue *sessionqueue_alt;
+  struct PendingMessage *pm;
+
+  sessionqueue = plugin->pending_Sessions_head;
 
   while (sessionqueue != NULL)
-    {
-      session = sessionqueue->content;
+  {
+    session = sessionqueue->content;
 
-      GNUNET_assert(session != NULL);
-      pm = session->pending_message;
+    GNUNET_assert (session != NULL);
+    pm = session->pending_message_head;
 
-#if DEBUG_wlan
-      if (pm == NULL)
-        {
-          GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-              "pending message is empty, should not happen. session %p\n",
-              session);
-        }
-#endif
+    if (pm == NULL)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                       "pending message is empty, should not happen. session %p\n",
+                       session);
+      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->fragment_messages_out_count
-              < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
-            {
-              plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-                  plugin->pending_Sessions_tail, sessionqueue);
-              GNUNET_free(sessionqueue);
-
-              return session;
-            }
-          else
-            {
-              sessionqueue = sessionqueue->next;
-            }
-        }
+    //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))
+      {
+        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);
+        GNUNET_free (sessionqueue);
+
+        return session;
+      }
       else
-        {
-
-          session->pending_message = session->pending_message2;
-          session->pending_message2 = NULL;
-
-          //call the cont func that it did not work
-          if (pm->transmit_cont != NULL)
-            pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
-                GNUNET_SYSERR);
-          GNUNET_free(pm->msg);
-          GNUNET_free(pm);
-
-          if (session->pending_message == NULL)
-            {
-              sessionqueue_alt = sessionqueue;
-              sessionqueue = sessionqueue->next;
-              plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-                  plugin->pending_Sessions_tail, sessionqueue_alt);
-
-              GNUNET_free(sessionqueue_alt);
-            }
+      {
+        sessionqueue = sessionqueue->next;
+      }
+    }
+    else
+    {
+      GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
+                                   session->pending_message_tail, pm);
 
-        }
+      //call the cont func that it did not work
+      if (pm->transmit_cont != NULL)
+        pm->transmit_cont (pm->transmit_cont_cls, &(session->target),
+                           GNUNET_SYSERR);
+      GNUNET_free (pm->msg);
+      GNUNET_free (pm);
 
+      if (session->pending_message_head == NULL)
+      {
+        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);
+      }
     }
+
+  }
   return NULL;
 }
 
@@ -971,401 +1167,729 @@ get_next_queue_session(struct Plugin * plugin)
  * @param fm message to free
  */
 static void
-free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
-{
-  struct Session * session = fm->session;
-
-  if (fm != NULL)
+free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
+{
+  struct Session *session = fm->session;
+  struct MacEndpoint *endpoint = session->mac;
+  struct FragmentMessage_queue *fmq;
+  struct FragmentMessage_queue *fmq_next;
+
+  fmq = plugin->sending_messages_head;
+  while (fmq != NULL)
+  {
+    fmq_next = fmq->next;
+    if (fmq->content == fm)
     {
-      (session->fragment_messages_out_count)--;
-      GNUNET_free_non_null(fm->msg);
-      GNUNET_CONTAINER_heap_remove_node(fm->node);
-      GNUNET_free(fm);
-
-      queue_session(plugin, session);
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "free pending fragment messages, pending messages remaining %u\n",
-          GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
-#endif
+      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;
+  }
+  GNUNET_free (fm);
+  queue_session (plugin, session);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Free pending fragment messages %p, session %p\n", fm,
+                   session);
 }
 
+
 /**
- * Function to check if there is some space in the fragment queue
- * inserts a message if space is available
- * @param plugin the plugin struct
+ * function to fill the radiotap header
+ *
+ * @param plugin pointer to the plugin struct
+ * @param endpoint pointer to the endpoint
+ * @param header pointer to the radiotap header
+ * @param size total message size
+ * @return GNUNET_YES at success
  */
+static int
+getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
+                   struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
+                  uint16_t size)
+{
+  header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
+  header->header.size = ntohs (size);
+  if (endpoint != NULL)
+  {
+    header->rate = endpoint->rate;
+    header->tx_power = endpoint->tx_power;
+    header->antenna = endpoint->antenna;
+  }
+  else
+  {
+    header->rate = 255;
+    header->tx_power = 0;
+    header->antenna = 0;
+  }
 
-static void
-check_fragment_queue(struct Plugin * plugin)
-{
-  struct Session * session;
-  struct FragmentMessage * fm;
-  struct GNUNET_PeerIdentity pid;
+  return GNUNET_YES;
+}
 
-  struct PendingMessage * pm;
 
-  if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
-      < FRAGMENT_QUEUE_SIZE)
-    {
-      session = get_next_queue_session(plugin);
-      if (session != NULL)
-        {
-          pm = session->pending_message;
-          session->pending_message = NULL;
-          session->fragment_messages_out_count++;
-          GNUNET_assert(pm != NULL);
-
-          fm = GNUNET_malloc(sizeof(struct FragmentMessage));
-          fm->message_size = pm->message_size;
-          fm->msg = pm->msg;
-          fm->session = session;
-          fm->timeout.abs_value = pm->timeout.abs_value;
-          fm->message_pos = 0;
-          fm->next_ack = GNUNET_TIME_absolute_get();
-          fm->message_id_out = get_next_message_id();
-          fm->ack_bitfield = 0;
-          fm->node = GNUNET_CONTAINER_heap_insert(
-              plugin->pending_Fragment_Messages, fm,
-              GNUNET_TIME_absolute_get().abs_value);
-
-          GNUNET_assert(session !=NULL);
-
-          if (pm->transmit_cont != NULL)
-            {
-              pid = session->target;
-              pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
-#if DEBUG_wlan
-              GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                  "called pm->transmit_cont for %p\n", session);
-#endif
-            }
-          else
-            {
-#if DEBUG_wlan
-              GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                  "no pm->transmit_cont for %p\n", session);
-#endif
-            }
-          GNUNET_free(pm);
+/**
+ * function to generate the wlan hardware header for one packet
+ * @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
+ *        FIXME: 'size' is initialized inconsistently throughout the code (sometimes payload, sometimes everything)
+ * @return GNUNET_YES if there was no error
+ */
+static int
+getWlanHeader (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *Header,
+               const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, struct Plugin *plugin,
+               unsigned int size)
+{
+  const int rate = 11000000;
 
-          if (session->pending_message2 != NULL)
-            {
-              session->pending_message = session->pending_message2;
-              session->pending_message2 = NULL;
-              //requeue session
-              queue_session(plugin, session);
-            }
+  Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
+  Header->addr1 = *to_mac_addr;
+  Header->addr2 = plugin->mac_address;
+  Header->addr3 = mac_bssid_gnunet;
+  Header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
+  Header->sequence_control = 0; // FIXME?
+  Header->llc[0] = WLAN_LLC_DSAP_FIELD;
+  Header->llc[1] = WLAN_LLC_SSAP_FIELD;
+  Header->llc[2] = 0;  // FIXME?
+  Header->llc[3] = 0;  // FIXME?
+  return GNUNET_YES;
+}
 
-        }
-    }
 
-  //check if timeout changed
-  set_next_send(plugin);
+/**
+ * function to add a fragment of a message to send
+ * @param cls FragmentMessage this message belongs to
+ * @param hdr pointer to the start of the message
+ */
+static void
+add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
+{
+  struct FragmentMessage *fm = cls;
+  struct FragmentMessage_queue *fmqueue;
+  struct MacEndpoint *endpoint;
+  struct Plugin *plugin;
+  uint16_t size;
+
+  GNUNET_assert (cls != NULL);
+  endpoint = fm->session->mac;
+  plugin = endpoint->plugin;
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
+                   fm, fm->session, endpoint, hdr->type);
+  size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + ntohs (hdr->size);
+  fm->radioHeader = GNUNET_malloc (size);
+  getRadiotapHeader (plugin, fm->session->mac, fm->radioHeader, size);
+  getWlanHeader (&fm->radioHeader->frame, &(fm->session->mac->addr), plugin,
+                size);
+  memcpy (&fm->radioHeader[1], hdr, ntohs (hdr->size));
+  // FIXME: yucky allocation structure!
+  fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue));
+  fmqueue->content = fm;
+  GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head,
+                                    plugin->sending_messages_tail, fmqueue);
+  set_next_send (plugin);
 }
 
+
 /**
- * Funktion to check if all fragments where send and the acks received
- * frees the space if finished
- * @param plugin the plugin struct
- * @param fm the message to check
+ * We have been notified that gnunet-helper-transport-wlan 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
-check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
+wlan_plugin_helper_read (void *cls,
+                         const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
-  unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
-      - sizeof(struct FragmentationHeader)));
-  uint64_t tmpfield = UINT64_MAX;
-  tmpfield = tmpfield >> maxack;
-
-#if DEBUG_wlan
-  if (maxack != 63)
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-        "Test bitfields %X and %X, maxack is %u, fm size %u\n",
-        fm->ack_bitfield, tmpfield, maxack, fm->message_size);
-#endif
-
-  if (fm->ack_bitfield == tmpfield)
-    {
+  struct Plugin *plugin = cls;
 
-#if DEBUG_wlan_retransmission
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "Finished sending and got all acks; message_id %u\n",
-          fm->message_id_out);
-#endif
+  plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
 
-      free_fragment_message(plugin, fm);
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
 
-      check_fragment_queue(plugin);
+  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)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     _
+                     ("Finished reading from gnunet-helper-transport-wlan stdout with code: %d\n"),
+                     bytes);
+    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);
 }
 
 /**
- * Function to set the next fragment number
- * @param fm use this FragmentMessage
+ * Start the gnunet-helper-transport-wlan process.
+ *
+ * @param plugin the transport plugin
+ * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
  */
-
-static void
-set_next_message_fragment_pos(struct Plugin * plugin,
-    struct FragmentMessage * fm)
+static int
+wlan_transport_start_wlan_helper (struct Plugin *plugin)
 {
+  const char *filenamehw = "gnunet-helper-transport-wlan";
+  const char *filenameloopback = "gnunet-helper-transport-wlan-dummy";
+  char *absolute_filename = NULL;
 
-  fm->message_pos++;
+  if (plugin->helper_is_running == GNUNET_YES)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "wlan_transport_start_wlan_helper not needed, helper already running!");
+    return GNUNET_YES;
+  }
 
-  //check if retransmit is needed
-  if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
-    {
+  plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, 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_YES, GNUNET_NO);
+  if (plugin->server_stdin == NULL)
+    return GNUNET_SYSERR;
 
-      // be positive and try again later :-D
-      fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
-      // find first missing fragment
+  if ((plugin->testmode == 1) || (plugin->testmode == 2))
+  {
+    if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
+    {
+      absolute_filename = GNUNET_strdup (filenameloopback);
+    }
+    else
+    {
+      char cwd[FILENAME_MAX];
 
-      fm->message_pos = 0;
+      GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
 
-      GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
-          fm->node, 0);
+      GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
+                       filenameloopback);
 
-#if DEBUG_wlan_retransmission
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "Retransmit; message_id %u; fragment number %i, size: %u\n",
-          fm->message_id_out, fm->message_pos, fm->message_size);
-#endif
+      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);
+      }
     }
+  }
 
-  //test if ack 0 (or X) was already received
-  while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
-    {
-      fm->message_pos++;
-    }
+  /* Start the server process */
 
-}
+  if (plugin->testmode == 0)
+  {
 
-static int
-getRadiotapHeader(struct Plugin * plugin, struct Session * session,
-    struct Radiotap_Send * header)
-{
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Starting gnunet-helper-transport-wlan process cmd: %s %s %i\n",
+                     filenamehw, plugin->interface, plugin->testmode);
+    if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES)
+    {
+      plugin->server_proc =
+         GNUNET_OS_start_process (GNUNET_NO, 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-helper-transport-wlan 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-helper-transport-wlan not found, please look if it exists and is the $PATH variable!\n");
+      GNUNET_break (0);
+    }
 
-  if (session != NULL)
+  }
+  else if (plugin->testmode == 1)
+  {
+
+    GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
+                     "Starting gnunet-helper-transport-wlan-dummy loopback 1 process cmd: %s %s %i\n",
+                     absolute_filename, plugin->interface, plugin->testmode);
+    plugin->server_proc =
+        GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
+                                 absolute_filename, absolute_filename, "1",
+                                 NULL);
+    if (plugin->server_proc == NULL)
     {
-      header->rate = session->rate;
-      header->tx_power = session->tx_power;
-      header->antenna = session->antenna;
+      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
+  }
+  else if (plugin->testmode == 2)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
+                     "Starting gnunet-helper-transport-wlan-dummy loopback 2 process cmd: %s %s %i\n",
+                     absolute_filename, plugin->interface, plugin->testmode);
+    plugin->server_proc =
+        GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
+                                 absolute_filename, absolute_filename, "2",
+                                 NULL);
+    if (plugin->server_proc == NULL)
     {
-      header->rate = 255;
-      header->tx_power = 0;
-      header->antenna = 0;
+      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)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Failed to start gnunet-helper-transport-wlan process\n");
+    return GNUNET_SYSERR;
+  }
+
+
 
+  /* 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);
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Adding server_read_task for the gnunet-helper-transport-wlan\n");
+  plugin->server_read_task =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      plugin->server_stdout_handle,
+                                      &wlan_plugin_helper_read, plugin);
+
+  plugin->helper_is_running = GNUNET_YES;
   return GNUNET_YES;
 }
 
 /**
- * function to generate the wlan hardware header for one packet
- * @param Header address to write the header to
- * @param to_mac_addr address of the recipient
- * @param plugin pointer to the plugin struct
- * @return GNUNET_YES if there was no error
+ * Stops the gnunet-helper-transport-wlan process.
+ *
+ * @param plugin the transport plugin
+ * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
  */
 static int
-getWlanHeader(struct ieee80211_frame * Header,
-    const struct MacAddress * to_mac_addr, struct Plugin * plugin,
-    unsigned int size)
+wlan_transport_stop_wlan_helper (struct Plugin *plugin)
 {
-  uint16_t * tmp16;
-  const int rate = 11000000;
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Stoping WLAN helper process\n");
 
-  Header->i_fc[0] = 0x08;
-  Header->i_fc[1] = 0x00;
-  memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
-  memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
-  memcpy(&Header->i_addr1, to_mac_addr, sizeof(struct MacAddress));
+  if (plugin->helper_is_running == GNUNET_NO)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "wlan_transport_stop_wlan_helper not needed, helper already stopped!");
+    return GNUNET_YES;
+  }
 
-  tmp16 = (uint16_t*) Header->i_dur;
-  *tmp16 = (uint16_t) htole16((size * 1000000) / rate + 290);
+  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;
+  }
+
+  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);
+
+  plugin->helper_is_running = GNUNET_NO;
 
   return GNUNET_YES;
 }
 
 /**
- * 32bit CRC
- *
- * @param msgbuf pointer tor the data
- * @param msgbuf_size size of the data
- *
- * @return 32bit crc value
+ * function for delayed restart of the helper process
+ * @param cls Finish_send struct if message should be finished
+ * @param tc TaskContext
  */
-
-uint32_t
-getcrc32(const char *msgbuf, size_t msgbuf_size)
+static void
+delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  //TODO calc some crc
-  return 0;
+  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);
+  }
+
 }
 
 /**
- * 16bit CRC
- *
- * @param msgbuf pointer tor the data
- * @param msgbuf_size size of the data
- *
- * @return 16bit crc value
+ * Function to restart the helper
+ * @param plugin pointer to the global plugin struct
+ * @param finish pointer to the Finish_send struct to finish
  */
-
-uint16_t
-getcrc16(const char *msgbuf, size_t msgbuf_size)
+static void
+restart_helper (struct Plugin *plugin, struct Finish_send *finish)
 {
-  //TODO calc some crc
-  return 0;
+  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
-send_hello_beacon(struct Plugin * plugin)
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
-#endif
-
-  uint16_t size;
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
   ssize_t bytes;
-  uint16_t hallo_size;
-  struct GNUNET_MessageHeader * msgheader;
-  struct ieee80211_frame * ieeewlanheader;
-  struct Radiotap_Send * radioHeader;
-  struct GNUNET_MessageHeader * msgheader2;
-
-  hallo_size = GNUNET_HELLO_size(*(plugin->env->our_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;
-
-  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(*(plugin->env->our_hello))
-      + sizeof(struct GNUNET_MessageHeader));
-
-  msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
-  memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
+  plugin = finish->plugin;
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
 
-  bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
+  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 == GNUNET_SYSERR)
+  if (bytes != finish->size)
+  {
+    if (bytes != GNUNET_SYSERR)
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-          _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
-          errno, strerror(errno));
-
+      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);
     }
-  GNUNET_assert(bytes != GNUNET_SYSERR);
-  GNUNET_assert(bytes == size);
-  GNUNET_free(msgheader);
-
-  set_next_beacon_time(plugin);
-  set_next_send(plugin);
+    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_ack(struct Plugin * plugin, struct AckSendQueue * ack)
+send_hello_beacon (struct Plugin *plugin)
 {
-
   uint16_t size;
   ssize_t bytes;
-  struct GNUNET_MessageHeader * msgheader;
-  struct ieee80211_frame * ieeewlanheader;
-  struct Radiotap_Send * radioHeader;
-  struct FragmentationAckHeader * msgheader2;
-
-  GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
-
-  size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
-      + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
+  uint16_t hello_size;
+  struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
+  const struct GNUNET_MessageHeader *hello;
+  struct Finish_send *finish;
+
+  GNUNET_assert (plugin != NULL);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Sending hello beacon\n");
+  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_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size;
+  radioHeader = GNUNET_malloc (size);
+  getRadiotapHeader (plugin, NULL, radioHeader, size);
+  getWlanHeader (&radioHeader->frame, &bc_all_mac, plugin, size);
+  memcpy (&radioHeader[1], hello, hello_size);
+  bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, radioHeader, size);
+  GNUNET_free (radioHeader);
+  if (bytes == GNUNET_SYSERR)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                     _
+                     ("Error writing to wlan helper. 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);
+  }
+}
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Sending ack for message_id %u with fragment field %u, size %u\n",
-      ack->message_id, ack->fragments_field, size
-          - sizeof(struct Radiotap_Send));
-#endif
 
-  msgheader = GNUNET_malloc(size);
-  msgheader->size = htons(size);
-  msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+/**
+ * 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 MacEndpoint *endpoint = cls;
+  struct Plugin *plugin = endpoint->plugin;
+  struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radioHeader;
+  struct AckSendQueue *ack;
+  struct GNUNET_MessageHeader *msgheader;
+  uint16_t size;
 
-  radioHeader = (struct Radiotap_Send*) &msgheader[1];
-  getRadiotapHeader(plugin, ack->session, radioHeader);
-  ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
-  getWlanHeader(ieeewlanheader, &ack->session->addr, plugin, size);
+  GNUNET_assert (endpoint != NULL);
+  size = sizeof (struct AckSendQueue) + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + ntohs (hdr->size);
+  ack = GNUNET_malloc (size);
+  ack->message_id = msg_id;
+  ack->endpoint = endpoint;
+  radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) &ack[1];
+  ack->radioHeader = radioHeader;
+  getRadiotapHeader (plugin, ack->endpoint, radioHeader, size - sizeof (struct AckSendQueue));
+  size = ntohs (hdr->size);
+  getWlanHeader (&radioHeader->frame, 
+                &ack->endpoint->addr, 
+                plugin,
+                 size);
+  msgheader = (struct GNUNET_MessageHeader *) &radioHeader[1];
+  memcpy (msgheader, hdr, size);
+  GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
+                                    plugin->ack_send_queue_tail, ack);
+  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);
+  set_next_send (plugin);
+}
 
-  msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
-  msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
-  msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
-  msgheader2->message_id = htonl(ack->message_id);
-  msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
 
-  bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
-  if (bytes == GNUNET_SYSERR)
-    {
-      GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-          _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
-          errno, strerror(errno));
+/**
+ * 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(bytes != GNUNET_SYSERR);
-  GNUNET_assert(bytes == size);
-  GNUNET_free(msgheader);
-  set_next_send(plugin);
+  GNUNET_assert (fm != NULL);
+  fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))  
+    return;  
+  free_fragment_message (fm->session->mac->plugin, fm);
 }
 
+/**
+ * Function to check if there is some space in the fragment queue
+ * inserts a message if space is available
+ * @param plugin the plugin struct
+ */
+
 static void
-finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+check_fragment_queue (struct Plugin *plugin)
 {
-  struct Finish_send * finish;
-  struct Plugin * plugin;
-  ssize_t bytes;
-
-  finish = cls;
-  plugin = finish->plugin;
-
-  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  struct Session *session;
+  struct FragmentMessage *fm;
+  struct GNUNET_PeerIdentity pid;
 
-  bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
-      finish->msgheader, finish->size);
-  GNUNET_assert(bytes != GNUNET_SYSERR);
+  struct PendingMessage *pm;
 
-  if (bytes != finish->size)
+  if (plugin->pending_Fragment_Messages < FRAGMENT_QUEUE_SIZE)
+  {
+    session = get_next_queue_session (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_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->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,
+                                        fm);
+      GNUNET_CONTAINER_DLL_insert_tail (session->mac->sending_messages_head,
+                                        session->mac->sending_messages_tail,
+                                        fm);
+
+      if (pm->transmit_cont != NULL)
+      {
+        pid = session->target;
+        pm->transmit_cont (pm->transmit_cont_cls, &pid, GNUNET_OK);
+        GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                         "called pm->transmit_cont for %p\n", session);
+      }
+      else
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                         "no pm->transmit_cont for %p\n", session);
+      }
+      GNUNET_free (pm);
+
+      if (session->pending_message_head != NULL)
+      {
+        //requeue session
+        queue_session (plugin, session);
+      }
 
-      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);
     }
-  else
-    {
-      GNUNET_free(finish->msgstart);
-      GNUNET_free(finish);
+  }
 
-      set_next_send(plugin);
+  //check if timeout changed
+  set_next_send (plugin);
+}
 
-    }
 
+/**
+ * Function to send an ack, does not free the ack
+ * @param plugin pointer to the plugin
+ */
+static void
+send_ack (struct Plugin *plugin)
+{
+  ssize_t bytes;
+  struct AckSendQueue *ack;
+  struct Finish_send *finish;
+
+  GNUNET_assert (plugin != NULL);
+  ack = plugin->ack_send_queue_head;
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Sending ack for message_id %u for mac endpoint %p, size %u\n",
+                   ack->message_id, ack->endpoint,
+                   ntohs (ack->radioHeader->header.size));
+  GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1,
+                            GNUNET_NO);
+  bytes =
+      GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->radioHeader,
+                              ntohs (ack->radioHeader->header.size));
+  if (bytes == GNUNET_SYSERR)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                     _
+                     ("Error writing to wlan helper. 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);
+    return;
+  }
+  GNUNET_assert (bytes == ntohs (ack->radioHeader->header.size));
+  GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
+                              plugin->ack_send_queue_tail, ack);
+  GNUNET_free (ack);
+  set_next_send (plugin);
 }
 
+
 /**
  * Function called when wlan helper is ready to get some data
  *
@@ -1373,218 +1897,90 @@ finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  * @param tc GNUNET_SCHEDULER_TaskContext
  */
 static void
-do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct Plugin *plugin = cls;
+  struct Session *session;
+  struct FragmentMessage *fm;
+  struct Finish_send *finish;
+  struct FragmentMessage_queue *fmq;
+  ssize_t bytes;
 
-  struct Plugin * plugin = cls;
+  GNUNET_assert (plugin != NULL);
   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
-
-  struct Session * session;
-  struct FragmentMessage * fm;
-  struct ieee80211_frame * ieeewlanheader;
-  struct Radiotap_Send * radioHeader;
-  struct GNUNET_MessageHeader * msgheader;
-
-  struct FragmentationHeader fragheader;
-  struct FragmentationHeader * fragheaderptr;
-  struct Finish_send * finish;
-  struct AckSendQueue * ack;
-  uint16_t size;
-  ssize_t bytes;
-  const char * copystart;
-  uint16_t copysize;
-  uint copyoffset;
-  struct GNUNET_TIME_Absolute next_send;
-
   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);
-      return;
-    }
-
+  {
+    send_ack (plugin);
+    return;
+  }
   //test if a "hello-beacon" has to be send
-  if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
+  if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0)
+  {
+    send_hello_beacon (plugin);
+    return;
+  }
+  if (NULL == plugin->sending_messages_head)
+  {
+    /* nothing to do right now, check when to go again */  
+    set_next_send (plugin);
+    return;
+  }
+  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,
+                              plugin->sending_messages_tail, fmq);
+  GNUNET_free (fmq);
+  
+  session = fm->session;
+  GNUNET_assert (session != NULL);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                  "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT for fragment message %p, size: %u\n",
+                  fm, ntohs (fm->radioHeader->header.size));
+  bytes =
+    GNUNET_DISK_file_write (plugin->server_stdin_handle, 
+                           fm->radioHeader,
+                           ntohs (fm->radioHeader->header.size));
+  if (bytes != ntohs (fm->radioHeader->header.size))
+  {
+    finish = GNUNET_malloc (sizeof (struct Finish_send));
+    finish->plugin = plugin;
+    finish->msgstart = &fm->radioHeader->header;
+    GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
+    if (bytes == GNUNET_SYSERR)
     {
-      send_hello_beacon(plugin);
-
-      return;
-
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                      _
+                      ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
+                      errno, strerror (errno));     
+      finish->head_of_next_write = (char*) fm->radioHeader;
+      finish->size = ntohs (fm->radioHeader->header.size);
+      restart_helper (plugin, finish);
     }
-
-  fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
-
-  if (fm != NULL)
+    else
     {
-      session = fm->session;
-      GNUNET_assert(session != NULL);
-
-      // test if message timed out
-      if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
-        {
-#if DEBUG_wlan
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
-#endif
-
-          free_fragment_message(plugin, fm);
-          check_fragment_queue(plugin);
-
-        }
-      else
-        {
-
-          //if (fm->message_size > WLAN_MTU)
-          // {
-          size = sizeof(struct FragmentationHeader);
-
-          set_next_message_fragment_pos(plugin, fm);
-
-          copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
-              * fm->message_pos;
-
-          fragheader.fragment_off_or_num = htons(fm->message_pos);
-          fragheader.message_id = htonl(fm->message_id_out);
-          copystart = fm->msg + copyoffset;
-          copysize = GNUNET_MIN(fm->message_size - copyoffset,
-              WLAN_MTU - sizeof(struct FragmentationHeader));
-
-#if DEBUG_wlan
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_DEBUG,
-              "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
-              fm->message_id_out, fm->message_pos, copysize
-                  + sizeof(struct FragmentationHeader), copyoffset,
-              GNUNET_TIME_absolute_get_remaining(fm->timeout));
-#endif
-
-          if (copyoffset >= fm->message_size)
-            {
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_ERROR,
-                  "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
-                  copyoffset, fm->message_size, WLAN_MTU
-                      - sizeof(struct FragmentationHeader), copysize,
-                  fm->message_pos);
-            }
-          GNUNET_assert(copyoffset < fm->message_size);
-          //FIXME remove later
-          GNUNET_assert(copystart < fm->msg + fm->message_size);
-
-          fragheader.header.size = htons(copysize
-              + sizeof(struct FragmentationHeader));
-          fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
-
-          /* }
-           else
-           {
-           // there is no need to split
-           copystart = fm->msg;
-           copysize = fm->message_size;
-           }*/
-
-          size += copysize;
-          size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
-              + sizeof(struct GNUNET_MessageHeader);
-          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, session, radioHeader);
-
-          ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
-          getWlanHeader(ieeewlanheader, &(fm->session->addr), plugin, size);
-
-          //could be faster if content is just send and not copyed before
-          //fragmentheader is needed
-          //if (fm->message_size > WLAN_MTU)
-          // {
-          fragheader.message_crc = htons(getcrc16(copystart, copysize));
-          memcpy(&ieeewlanheader[1], &fragheader,
-              sizeof(struct FragmentationHeader));
-          fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
-          memcpy(&fragheaderptr[1], copystart, copysize);
-          /* }
-           else
-           {
-           memcpy(&ieeewlanheader[1], copystart, copysize);
-           }*/
-
-          bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
-              msgheader, size);
-          if (bytes == GNUNET_SYSERR)
-            {
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_ERROR,
-                  _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
-                  errno, strerror(errno));
-
-            }
-          GNUNET_assert(bytes != GNUNET_SYSERR);
-
-          //check if this was the last fragment of this message, if true then queue at the end of the list
-          if (copysize + copyoffset >= fm->message_size)
-            {
-              GNUNET_assert(copysize + copyoffset == fm->message_size);
-
-              GNUNET_CONTAINER_heap_update_cost(
-                  plugin->pending_Fragment_Messages, fm->node, MIN(
-                      fm->timeout.abs_value, fm->next_ack.abs_value));
-              // if fragments have opimized timeouts
-              //sort_fragment_into_queue(plugin,fm);
-
-
-#if DEBUG_wlan_retransmission
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_DEBUG,
-                  "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
-                  fm->message_id_out, fm->message_id_out, fm->message_pos,
-                  fm->message_size, GNUNET_TIME_absolute_get_remaining(
-                      fm->timeout));
-#endif
-            }
-          else
-            {
-              GNUNET_CONTAINER_heap_update_cost(
-                  plugin->pending_Fragment_Messages, fm->node,
-                  GNUNET_TIME_absolute_get().abs_value);
-            }
-
-          if (bytes != size)
-            {
-              finish = GNUNET_malloc(sizeof( struct Finish_send));
-              finish->plugin = plugin;
-              finish->msgheader = (char *) msgheader + bytes;
-              finish->size = size - bytes;
-              finish->msgstart = msgheader;
-              finish ->next_send = next_send;
-
-              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);
-
-            }
-          else
-            {
-              GNUNET_free(msgheader);
-              set_next_send(plugin);
-            }
-
-        }
-      return;
-    }
-  GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-      "do_transmit did nothing, should not happen!\n");
+      finish->head_of_next_write = ((char*) fm->radioHeader) + bytes;
+      finish->size = ntohs (fm->radioHeader->header.size) - bytes;
+      plugin->server_write_task =
+       GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                        plugin->server_stdin_handle,
+                                        &finish_sending, finish);
+    }    
+  }
+  else
+  {
+    GNUNET_free (fm->radioHeader);
+    fm->radioHeader = NULL;
+    set_next_send (plugin);
+  }
+  GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
 }
 
+
 /**
  * Another peer has suggested an address for this
  * peer and transport plugin.  Check that this could be a valid
@@ -1598,346 +1994,286 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  *         and transport
  */
 static int
-wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
+wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
 {
   //struct Plugin *plugin = cls;
 
   /* check if the address is plausible; if so,
-   add it to our list! */
+   add it to our list! */
 
-  GNUNET_assert(cls !=NULL);
+  GNUNET_assert (cls != NULL);
   //FIXME mitm is not checked
   //Mac Address has 6 bytes
   if (addrlen == 6)
-    {
-      /* TODO check for bad addresses like multicast, broadcast, etc */
-      return GNUNET_OK;
-    }
-
+  {
+    /* TODO check for bad addresses like multicast, broadcast, etc */
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "wlan_plugin_address_suggested got good address, size %u!\n",
+                     addrlen);
+    return GNUNET_OK;
+  }
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "wlan_plugin_address_suggested got bad address, size %u!\n",
+                   addrlen);
   return GNUNET_SYSERR;
 }
 
+
+/**
+ * Creates a new outbound session the transport service will use to send data to the
+ * peer
+ *
+ * @param cls the plugin
+ * @param address the address
+ * @return the session or NULL of max connections exceeded
+ */
+
+static struct Session *
+wlan_plugin_get_session (void *cls,
+                  const struct GNUNET_HELLO_Address *address)
+{
+  struct Plugin *plugin = cls;
+  struct Session * s = NULL;
+
+  GNUNET_assert (plugin != NULL);
+  GNUNET_assert (address != NULL);
+
+  if (GNUNET_OK == wlan_plugin_address_suggested (plugin,
+            address->address,
+            address->address_length))
+  {
+    s = get_session (plugin, address->address, &address->peer);
+  }
+  else
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                     _("Wlan Address len %d is wrong\n"), address->address_length);
+    return s;
+  }
+
+  return s;
+}
+
 /**
  * Function that can be used by the transport service to transmit
- * a message using the plugin.
+ * a message using the plugin.   Note that in the case of a
+ * peer disconnecting, the continuation MUST be called
+ * prior to the disconnect notification itself.  This function
+ * will be called with this peer's HELLO message to initiate
+ * a fresh connection to another peer.
  *
  * @param cls closure
- * @param target who should receive this message
- * @param priority how important is the message
+ * @param session which session must be used
  * @param msgbuf the message to transmit
  * @param msgbuf_size number of bytes in 'msgbuf'
- * @param timeout when should we time out
- * @param session which session must be used (or NULL for "any")
- * @param addr the address to use (can be NULL if the plugin
- *                is "on its own" (i.e. re-use existing TCP connection))
- * @param addrlen length of the address in bytes
- * @param force_address GNUNET_YES if the plugin MUST use the given address,
- *                otherwise the plugin may use other addresses or
- *                existing connections (if available)
+ * @param priority how important is the message (most plugins will
+ *                 ignore message priority and just FIFO)
+ * @param to how long to wait at most for the transmission (does not
+ *                require plugins to discard the message after the timeout,
+ *                just advisory for the desired delay; most plugins will ignore
+ *                this as well)
  * @param cont continuation to call once the message has
  *        been transmitted (or if the transport is ready
  *        for the next transmission call; or if the
- *        peer disconnected...)
+ *        peer disconnected...); can be NULL
  * @param cont_cls closure for cont
  * @return number of bytes used (on the physical network, with overheads);
  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
  *         and does NOT mean that the message was not transmitted (DV)
  */
 static ssize_t
-wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
-    const char *msgbuf, size_t msgbuf_size, unsigned int priority,
-    struct GNUNET_TIME_Relative timeout, struct Session *session,
-    const void *addr, size_t addrlen, int force_address,
-    GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
+wlan_plugin_send (void *cls,
+                  struct Session *session,
+                  const char *msgbuf, size_t msgbuf_size,
+                  unsigned int priority,
+                  struct GNUNET_TIME_Relative to,
+                  GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
 {
-  struct Plugin * plugin = cls;
-  struct PendingMessage * newmsg;
-  struct WlanHeader * wlanheader;
-
-  //check if msglen > 0
-  GNUNET_assert(msgbuf_size > 0);
-
-  //get session if needed
-  if (session == NULL)
-    {
-      if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
-        {
-          session = get_session(plugin, addr);
-        }
-      else
-        {
-          GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-              _("Wlan Address len %d is wrong\n"), addrlen);
-          return -1;
-        }
-    }
-
-  //TODO target "problem" not solved
-  //if (session->target != NULL){
-  //  GNUNET_assert(session->target == *target);
-  //} else {
-  session->target = *target;
-  //}
+  struct Plugin *plugin = cls;
+  struct PendingMessage *newmsg;
+  struct WlanHeader *wlanheader;
 
+  GNUNET_assert (plugin != NULL);
+  GNUNET_assert (session != NULL);
+  GNUNET_assert (msgbuf_size > 0);
 
   //queue message:
 
   //queue message in session
   //test if there is no other message in the "queue"
   //FIXME: to many send requests
-  //GNUNET_assert (session->pending_message == NULL);
-  if (session->pending_message != NULL)
-    {
-      newmsg = session->pending_message;
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_ERROR,
-          "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 %u\n",
-          GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
-          session->fragment_messages_out_count);
-      if (session->pending_message2 != NULL)
-        {
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_ERROR,
-              "wlan_plugin_send: two pending messages are already in the queue for this client\n");
-          return -1;
-        }
-    }
-
-  newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
-  (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
-  wlanheader = (struct WlanHeader *) newmsg->msg;
+  if (session->pending_message_head != NULL)
+  {
+    newmsg = session->pending_message_head;
+    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,
+                     session->mac->fragment_messages_out_count);
+  }
+
+  newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
+  newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
+  wlanheader = newmsg->msg;
   //copy msg to buffer, not fragmented / segmented yet, but with message header
-  wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
-  wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
-  memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
-  wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
-  memcpy(&wlanheader[1], msgbuf, msgbuf_size);
+  wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
+  wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
+  memcpy (&(wlanheader->target), &session->target, sizeof (struct GNUNET_PeerIdentity));
+  memcpy (&(wlanheader->source), plugin->env->my_identity,
+          sizeof (struct GNUNET_PeerIdentity));
+  wlanheader->crc = 0;
+  memcpy (&wlanheader[1], msgbuf, msgbuf_size);
+  wlanheader->crc =
+      htonl (GNUNET_CRYPTO_crc32_n
+             ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
+
   newmsg->transmit_cont = cont;
   newmsg->transmit_cont_cls = cont_cls;
-  newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
+  newmsg->timeout = GNUNET_TIME_relative_to_absolute (to);
 
   newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
 
-  newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
+  newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
 
-  if (session->pending_message == NULL)
-    {
-      session->pending_message = newmsg;
-    }
-  else
-    {
-      session->pending_message2 = newmsg;
-    }
+  GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
+                                    session->pending_message_tail, newmsg);
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "New message for %p with size (incl wlan header) %u added\n", session,
-      newmsg->message_size);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "New message for %p with size (incl wlan header) %u added\n",
+                   session, newmsg->message_size);
+#if DEBUG_WLAN > 1
+  hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
 #endif
-
   //queue session
-  queue_session(plugin, session);
+  queue_session (plugin, session);
 
-  check_fragment_queue(plugin);
+  check_fragment_queue (plugin);
   //FIXME not the correct size
   return msgbuf_size;
-
-}
-
-/**
- * Iterate over the fragment messages of the given session.
- *
- * @param cls argument to give to iterator
- * @param node node to iterate over
- * @param element value stored at the node
- * @param cost cost associated with the node
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
- */
-static int
-free_fragment_message_from_session(void *cls,
-    struct GNUNET_CONTAINER_HeapNode *node, void *element,
-    GNUNET_CONTAINER_HeapCostType cost)
-{
-  struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
-  struct FragmentMessage * fm = (struct FragmentMessage*) element;
-
-  if (fm->session == pair->session)
-    {
-
-      free_fragment_message(pair->plugin, fm);
-    }
-  return GNUNET_YES;
-
-}
-
-/**
- * Search for fragment message with given id and session
- *
- * @param cls argument to give to iterator
- * @param node node to iterate over
- * @param element value stored at the node
- * @param cost cost associated with the node
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
- */
-static int
-search_fragment_message_from_session_and_id(void *cls,
-    struct GNUNET_CONTAINER_HeapNode *node, void *element,
-    GNUNET_CONTAINER_HeapCostType cost)
-{
-  struct Session_id_pair * pair = (struct Session_id_pair *) cls;
-  struct FragmentMessage * fm = (struct FragmentMessage*) element;
-
-  if ((fm->session == pair->session)
-      && (fm->message_id_out == pair->message_id))
-    {
-      return_val = fm;
-      return GNUNET_NO;
-    }
-  return GNUNET_YES;
-
-}
-
-/**
- * function to get the message in the fragement queue (out) of a session with a specific id
- * @param session pointer to the session
- * @param message_id id of the message
- * @return pointer to the struct FragmentMessage
- */
-static struct FragmentMessage *
-get_fragment_message_from_session_and_id(struct Plugin * plugin,
-    struct Session * session, uint32_t message_id)
-{
-  struct Session_id_pair pair;
-  pair.session = session;
-  pair.message_id = message_id;
-  GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
-      &search_fragment_message_from_session_and_id, &pair);
-  return return_val;
 }
 
-/**
- * function to get the receive message of a session
- * @param plugin pointer to the plugin struct
- * @param session session this fragment belongs to
- */
-struct Receive_Message_Queue *
-get_receive_message_from_session(struct Plugin * plugin,
-    struct Session * session)
-{
-  struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
-  while (rec_message != NULL)
-    {
-      if (rec_message->session == session)
-        {
-          return rec_message;
-        }
-      rec_message = rec_message->next;
-    }
-  return NULL;
-}
 
 /**
- * Function to dispose the fragments received for a message and the message
+ * function to free a mac endpoint
  * @param plugin pointer to the plugin struct
- * @param rec_message pointer to the struct holding the message which should be freed
+ * @param endpoint pointer to the MacEndpoint to free
  */
 static void
-free_receive_message(struct Plugin* plugin,
-    struct Receive_Message_Queue * rx_message)
+free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
 {
-  GNUNET_assert(rx_message !=NULL);
-  struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
-  struct Receive_Fragment_Queue * rec_queue2;
-
-  while (rec_queue != NULL)
-    {
-      rec_queue2 = rec_queue;
-      rec_queue = rec_queue->next;
-      GNUNET_free(rec_queue2);
-    }
-
-  GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
-
-  GNUNET_assert(plugin->pending_receive_messages > 0);
-  GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
+  struct Sessionqueue *sessions;
+  struct Sessionqueue *sessions_next;
+
+  GNUNET_assert (endpoint != NULL);
+
+  sessions = endpoint->sessions_head;
+  while (sessions != NULL)
+  {
+    sessions_next = sessions->next;
+    free_session (plugin, sessions, GNUNET_NO);
+    sessions = sessions_next;
+  }
+
+  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);
 
-  plugin->pending_receive_messages--;
-  rx_message->session->fragment_messages_in_count--;
-  GNUNET_free(rx_message);
 }
 
+/**
+ * function to free a session
+ * @param plugin pointer to the plugin
+ * @param queue pointer to the sessionqueue element to free
+ * @param do_free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
+ */
 static void
-free_session(struct Plugin * plugin, struct Sessionqueue * queue)
-{
-  struct Sessionqueue * pendingsession = plugin->pending_Sessions;
-  struct PendingMessage * pm;
-  struct Receive_Message_Queue * receive_queue;
-  struct Plugin_Session_pair pair;
+free_session (struct Plugin *plugin, struct Sessionqueue *queue,
+              int do_free_macendpoint)
+{
+  struct Sessionqueue *pendingsession;
+  struct Sessionqueue *pendingsession_tmp;
+  struct PendingMessage *pm;
+  struct MacEndpoint *endpoint;
+  struct FragmentMessage *fm;
+  struct FragmentMessage *fmnext;
   int check = 0;
 
-  GNUNET_assert(queue != NULL);
+  GNUNET_assert (plugin != NULL);
+  GNUNET_assert (queue != NULL);
+  GNUNET_assert (queue->content != NULL);
 
   //session found
   //is this session pending for send
+  pendingsession = plugin->pending_Sessions_head;
   while (pendingsession != NULL)
+  {
+    pendingsession_tmp = pendingsession;
+    pendingsession = pendingsession->next;
+    GNUNET_assert (pendingsession_tmp->content != NULL);
+    if (pendingsession_tmp->content == queue->content)
     {
-      if (pendingsession->content == queue->content)
-        {
-          plugin->pendingsessions--;
-          GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-              plugin->pending_Sessions_tail, pendingsession);
-          GNUNET_free(pendingsession);
-
-          if (check == 1)
-            {
-              GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-                  "Session is more then once in pending session\n");
-            }
-
-          check = 1;
-        }
-      pendingsession = pendingsession->next;
-    }
-
-  //is something of this session in the fragment queue?
-  pair.plugin = plugin;
-  pair.session = queue->content;
-  GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
-      &free_fragment_message_from_session, &pair);
-
-  //dispose all received fragments
-  receive_queue = get_receive_message_from_session(plugin, queue->content);
-  while (receive_queue != NULL)
-    {
-      free_receive_message(plugin, receive_queue);
-      receive_queue = get_receive_message_from_session(plugin, 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_tmp);
+      GNUNET_free (pendingsession_tmp);
+
+      GNUNET_assert (check == 0);
+      check = 1;
     }
+  }
 
-  // remove PendingMessage
-  pm = queue->content->pending_message;
-  if (pm != NULL)
-    {
-      GNUNET_free_non_null(pm->msg);
-      GNUNET_free(pm);
-    }
+  endpoint = queue->content->mac;
+  fm = endpoint->sending_messages_head;
+  while (fm != NULL)
+  {
+    fmnext = fm->next;
+    if (fm->session == queue->content)    
+      free_fragment_message (plugin, fm);    
+    fm = fmnext;
+  }
 
   // remove PendingMessage
-  pm = queue->content->pending_message2;
-  if (pm != NULL)
-    {
-      GNUNET_free_non_null(pm->msg);
-      GNUNET_free(pm);
-    }
-
-  GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
-  GNUNET_free(queue->content);
-  GNUNET_free(queue);
-  plugin->session_count--;
-
-  check_fragment_queue(plugin);
-
+  pm = queue->content->pending_message_head;
+  while (pm != NULL)
+  {
+    GNUNET_CONTAINER_DLL_remove (queue->content->pending_message_head,
+                                 queue->content->pending_message_tail, pm);
+    GNUNET_free (pm->msg);
+    GNUNET_free (pm);
+    pm = queue->content->pending_message_head;
+  }
+
+  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);
 }
 
 /**
@@ -1949,25 +2285,35 @@ free_session(struct Plugin * plugin, struct Sessionqueue * queue)
  * @param target peer from which to disconnect
  */
 static void
-wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
+wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
 {
   struct Plugin *plugin = cls;
-  struct Sessionqueue * queue = plugin->sessions;
+  struct Sessionqueue *queue;
+  struct Sessionqueue *queue_next;
+  struct MacEndpoint *endpoint = plugin->mac_head;
+  struct MacEndpoint *endpoint_next;
 
   // just look at all the session for the needed one
-  while (queue != NULL)
+  while (endpoint != NULL)
+  {
+    queue = endpoint->sessions_head;
+    endpoint_next = endpoint->next;
+    while (queue != NULL)
     {
       // content is never NULL
       GNUNET_assert (queue->content != NULL);
-      if (memcmp(target, &(queue->content->target),
-          sizeof(struct GNUNET_PeerIdentity)) == 0)
-        {
-          free_session(plugin, queue);
-          return;
-        }
+      queue_next = queue->next;
+      if (memcmp
+          (target, &(queue->content->target),
+           sizeof (struct GNUNET_PeerIdentity)) == 0)
+      {
+        free_session (plugin, queue, GNUNET_YES);
+      }
       // try next
-      queue = queue->next;
+      queue = queue_next;
     }
+    endpoint = endpoint_next;
+  }
 }
 
 /**
@@ -1985,689 +2331,425 @@ wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
  * @param asc_cls closure for asc
  */
 static void
-wlan_plugin_address_pretty_printer(void *cls, const char *type,
-    const void *addr, size_t addrlen, int numeric,
-    struct GNUNET_TIME_Relative timeout,
-    GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
+wlan_plugin_address_pretty_printer (void *cls, const char *type,
+                                    const void *addr, size_t addrlen,
+                                    int numeric,
+                                    struct GNUNET_TIME_Relative timeout,
+                                    GNUNET_TRANSPORT_AddressStringCallback asc,
+                                    void *asc_cls)
 {
-  char ret[92];
-  const unsigned char * input;
+  char *ret;
+  const unsigned char *input;
 
   //GNUNET_assert(cls !=NULL);
-  if (addrlen != 6)
-    {
-      /* invalid address (MAC addresses have 6 bytes) */
-      GNUNET_break (0);
-      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]);
-  asc(asc_cls, ret);
+  if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
+  {
+    /* invalid address (MAC addresses have 6 bytes) */
+    //GNUNET_break (0);
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
+                     addrlen);
+    asc (asc_cls, NULL);
+    return;
+  }
+  input = (const unsigned char *) addr;
+  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]);
+  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);
+  asc (asc_cls, ret);
+  //only one mac address per plugin
+  asc (asc_cls, NULL);
 }
 
-/**
- * function to check if bitfield is representation of fragments of the message
- * @param rec_message message to check
- */
-
-void
-check_message_fragment_bitfield(struct Receive_Message_Queue * rx_msg)
-{
-  uint64_t checkfragments = 0;
-  struct Receive_Fragment_Queue * rx_frag = rx_msg->frag_head;
 
-  while (rx_frag != NULL)
-    {
-      setBit((char*) &checkfragments, rx_frag->num);
-      rx_frag = rx_frag->next;
-
-    }
-  GNUNET_assert(checkfragments == rx_msg->received_fragments);
-}
 
 /**
- * Function to test if fragment number already exists in the fragments received
- *
- * @param rec_message message this fragment belongs to
- * @param fh Fragmentheader of the fragment
- * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
+ * handels the data after all fragments are put together
+ * @param cls macendpoint this messages belongs to
+ * @param hdr pointer to the data
  */
-
-static const int
-is_double_msg(struct Receive_Message_Queue * rx_msg,
-    struct FragmentationHeader * fh)
+static void
+wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
 {
-  //test if bitfield is okay
-#if DEBUG_wlan
-  check_message_fragment_bitfield(rx_msg);
-#endif
-
-  return testBit((char *) &rx_msg->received_fragments, ntohs(
-      fh->fragment_off_or_num));
+  struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
+  struct Plugin *plugin = endpoint->plugin;
+  struct WlanHeader *wlanheader;
+  struct Session *session;
 
-}
+  const struct GNUNET_MessageHeader *temp_hdr;
+  struct GNUNET_PeerIdentity tmpsource;
+  int crc;
 
-/**
- * Function to insert a fragment in a queue of a message
- * @param session session the fragment belongs to
- * @param rec_queue fragment to add
- */
+  GNUNET_assert (plugin != NULL);
 
-static void
-insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
-    struct Receive_Fragment_Queue * rx_frag)
-{
-  GNUNET_assert(rx_message != NULL);
-  GNUNET_assert(rx_frag != NULL);
+  if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
+  {
 
-  struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
-  struct WlanHeader * wlanheader;
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
+                     ntohs (hdr->size));
 
-  //this is the first fragment of the message (fragment id 0)
-  if (rx_frag->num == 0)
+    if (ntohs (hdr->size) <
+        sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
     {
-      wlanheader = (struct WlanHeader *) rx_frag->msg;
-      rx_message->rec_size = ntohs(wlanheader->header.size);
+      //packet not big enought
+      return;
     }
 
-  //sort into list
-  while (rx_frag2 != NULL)
-    {
-      if (rx_frag2->num > rx_frag->num)
-        {
-          //next element number is grater than the current num
-          GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
-          setBit((char *) &rx_message->received_fragments, rx_frag->num);
-          return;
-        }
-      rx_frag2 = rx_frag2->next;
-    }
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan whole messages received"), 1,
+                              GNUNET_NO);
+    wlanheader = (struct WlanHeader *) hdr;
 
-  //no element has a grater number
-  GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
+    session = search_session (plugin, endpoint, &wlanheader->source);
 
-  setBit((char *) &rx_message->received_fragments, rx_frag->num);
-}
+    temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
+    crc = ntohl (wlanheader->crc);
+    wlanheader->crc = 0;
+    if (GNUNET_CRYPTO_crc32_n
+        ((char *) wlanheader, ntohs (wlanheader->header.size)) != crc)
+    {
+      //wrong crc, dispose message
+      GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
+                       "Wlan message header crc was wrong: %u != %u\n",
+                       GNUNET_CRYPTO_crc32_n ((char *) wlanheader,
+                                              ntohs (wlanheader->header.size)),
+                       crc);
+      hexdump ((void *) hdr, ntohs (hdr->size));
+      return;
+    }
 
-/**
- * handels the data after all fragments are put together
- * @param plugin
- * @param session_light
- * @param hdr pointer to the data
- */
-static void
-wlan_data_message_handler(struct Plugin * plugin,
-    struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr)
-{
-  struct WlanHeader * wlanheader;
-  struct Session * session;
-  const char * tempmsg;
-  const struct GNUNET_MessageHeader * temp_hdr;
-  struct GNUNET_PeerIdentity tmptarget;
-
-  if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
+    //if not in session list
+    if (session == NULL)
     {
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
-          ntohs(hdr->size));
-#endif
-
-      if (ntohs(hdr->size) < sizeof(struct WlanHeader)
-          + sizeof(struct GNUNET_MessageHeader))
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
+                       ntohs (wlanheader->header.size), ntohs (temp_hdr->size),
+                       sizeof (struct WlanHeader));
+      //try if it is a hello message
+      if (ntohs (wlanheader->header.size) >=
+          ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
+      {
+        if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
         {
-          //packet not big enought
-          return;
-        }
+          if (GNUNET_HELLO_get_id
+              ((const struct GNUNET_HELLO_Message *) temp_hdr,
+               &tmpsource) == GNUNET_OK)
+          {
+            session = create_session (plugin, endpoint, &tmpsource);
+          }
+          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;
+          }
 
-      GNUNET_assert(session_light != NULL);
-      if (session_light->session == NULL)
-        {
-          session_light->session = search_session(plugin, &session_light->addr);
         }
-      session = session_light->session;
-      wlanheader = (struct WlanHeader *) hdr;
-
-      tempmsg = (char*) &wlanheader[1];
-      temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
-
-      if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
-          wlanheader->crc))
+        else
         {
-          //wrong crc, dispose message
-          GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-              "Wlan message Header crc was wrong\n");
+          GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                           "WLAN client not in session list and not a hello message\n");
           return;
         }
-
-      //if not in session list
-      if (session == NULL)
-        {
-#if DEBUG_wlan
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_DEBUG,
-              "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
-              ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
-              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(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
-                {
-                  if (GNUNET_HELLO_get_id(
-                      (const struct GNUNET_HELLO_Message *) temp_hdr,
-                      &tmptarget) == GNUNET_OK)
-                    {
-                      session = create_session(plugin, &session_light->addr);
-                      session_light->session = session;
-                      memcpy(&session->target, &tmptarget,
-                          sizeof(struct GNUNET_PeerIdentity));
-                    }
-                  else
-                    {
-                      GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-                          "WLAN client not in session list and hello message not okay\n");
-                      return;
-                    }
-
-                }
-              else
-                {
-                  GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-                      "WLAN client not in session list and not a hello message\n");
-                  return;
-                }
-            }
-          else
-            {
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_WARNING,
-                  "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
-                  ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
-                  sizeof(struct WlanHeader));
-              return;
-            }
-        }
-
-      //"receive" the message
-
-
-      GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
-          (const char *) temp_hdr,
-          ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
-
-      return;
-    }
-  else
-    {
-      GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-          "wlan_data_message_handler got wrong message type\n");
-      return;
+      }
+      else
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                         "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
+                         ntohs (wlanheader->header.size),
+                         ntohs (temp_hdr->size), sizeof (struct WlanHeader));
+        return;
+      }
     }
-}
 
-/**
- * Function to check if all fragments of a message have been received
- * @param plugin the plugin handle
- * @param session_light information of the message sender
- * @param session session the message belongs to
- * @param rec_message pointer to the message that should be checked
- */
+    //"receive" the message
 
-static void
-check_rx_finished_msg(struct Plugin* plugin,
-    struct Session_light * session_light, struct Session * session,
-    struct Receive_Message_Queue * rx_message)
-{
-  GNUNET_assert(rx_message !=NULL);
-
-  struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
-  int packetsize = rx_message->rec_size;
-  int sum;
-  int aktnum;
-  uint64_t bitfield = 0;
-  char * msg;
-
-  //check if first fragment is present
-  if (packetsize == MESSAGE_LENGHT_UNKNOWN)
+    if (memcmp
+        (&wlanheader->source, &session->target,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
+      //wrong peer id
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "WLAN peer source id doesn't match packet peer source id: session %p\n",
+                       session);
       return;
     }
-  // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
 
-  else if (packetsize < sizeof(struct WlanHeader)
-      + sizeof(struct GNUNET_MessageHeader))
+    if (memcmp
+        (&wlanheader->target, plugin->env->my_identity,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
-#endif
-      free_receive_message(plugin, rx_message);
+      //wrong peer id
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "WLAN peer target id doesn't match our peer id: session %p\n",
+                       session);
       return;
     }
 
-#if DEBUG_wlan
-  check_message_fragment_bitfield(rx_message);
-#endif
-
-  //  if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
-  //    {
-  bitfield = ~bitfield;
-  bitfield = bitfield >> (63 - rx_message->frag_tail->num);
-  if (rx_message->received_fragments == bitfield)
-    {
-      sum = 0;
-      while (rx_frag != NULL)
-        {
-          sum += rx_frag->size;
-          rx_frag = rx_frag->next;
-        }
-      //sum should always be smaller or equal of
-      GNUNET_assert(sum <= packetsize);
-      if (sum == packetsize)
-        {
-
-#if DEBUG_wlan
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-              "check_rec_finished_msg: A message for %p is complete\n", session);
-#endif
-
-          //TODO use mst
-          //copy fragments together
-          msg = GNUNET_malloc(packetsize);
-          rx_frag = rx_message->frag_head;
-          aktnum = 0;
-          while (rx_frag != NULL)
-            {
-              //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
-              memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
-              aktnum += rx_frag->size;
-              rx_frag = rx_frag->next;
-            }
-
-          free_receive_message(plugin, rx_message);
-          //call wlan_process_helper to process the message
-          wlan_data_message_handler(plugin, session_light,
-              (struct GNUNET_MessageHeader*) msg);
-          //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
-
-          GNUNET_free(msg);
-        }
-    }
-  //    }
-}
-
-static void
-process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
-{
-
-  GNUNET_assert(client != NULL);
-  GNUNET_assert(cls != NULL);
-  struct Session * session = (struct Session *) client;
-  struct Plugin * plugin = (struct Plugin *) cls;
-
-  struct GNUNET_TRANSPORT_ATS_Information distance[2];
-  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);
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
-      wlan_plugin_address_to_string(NULL, session->addr.mac, 6), htons(
-          hdr->size));
-#endif
+    GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
+                               (const char *) temp_hdr,
+                               ntohs (hdr->size) - sizeof (struct WlanHeader),
+                               GNUNET_YES, GNUNET_NO);
 
-  plugin->env->receive(plugin->env->cls, &(session->target), hdr,
-      (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
-      (const char*) &session->addr, sizeof(session->addr));
-}
-
-/**
- * function to add an ack to send it for a received fragment
- * @param plugin pointer to the global plugin structure
- * @param session pointer to the session this ack belongs to
- * @param bitfield bitfield to send
- * @param fh pointer to the fragmentation header which we would like to acknolage
- */
-
-void
-add_ack_for_send(struct Plugin * plugin, struct Session * session,
-    uint64_t bitfield, struct FragmentationHeader * fh)
-{
-  struct AckSendQueue * ack;
-
-  GNUNET_assert(plugin != NULL);
-  GNUNET_assert(session != NULL);
-  GNUNET_assert(fh != NULL);
-
-  ack = GNUNET_malloc(sizeof(struct AckSendQueue));
-  ack->fragments_field = bitfield;
-  ack->message_id = ntohl(fh->message_id);
-  ack->session = session;
-
-  GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
-      plugin->ack_send_queue_tail, ack);
-
-}
-
-/**
- * function to get the receive message from the message id and the session
- * @param plugin pointer to the plugin struct
- * @param session session this fragment belongs to
- * @param message_id id of the message
- */
-
-struct Receive_Message_Queue *
-get_receive_message(struct Plugin * plugin, struct Session * session,
-    uint32_t message_id)
-{
-  struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
-  while (rec_message != NULL)
-    {
-      if ((rec_message->message_id_in == message_id) && (rec_message->session
-          == session))
-        {
-          return rec_message;
-        }
-      rec_message = rec_message->next;
-    }
-  return NULL;
+    return;
+  }
+  else
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                     "wlan_data_message_handler got wrong message type: %u\n",
+                     ntohs (hdr->size));
+    return;
+  }
 }
 
 /**
- * function to insert a received fragment into the right fragment queue of the right message
- * @param plugin pointer to the plugin struct
- * @param session_light pointer to the session_light struct of this message
- * @param session session this fragment belongs to
- * @param fh pointer to the header of the fragment
- * @return new fragment bitfield for the message
+ * function to process the a message, give it to the higher layer
+ * @param cls pointer to the plugin
+ * @param client pointer to the session this message belongs to
+ * @param hdr start of the message
  */
-
-uint64_t
-insert_fragment_in_in_message_queue(struct Plugin * plugin,
-    struct Session_light * session_light, struct Session * session,
-    struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
-{
-  struct Receive_Fragment_Queue * rx_frag = NULL;
-  struct Receive_Message_Queue * rx_message;
-  const char * tempmsg = (char*) &fh[1];
-  uint64_t retval = 0;
-
-  //TODO fragments do not timeout
-  //check if message_id is right or it is a new msg
-  GNUNET_assert(fh != NULL);
-
-  rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
-
-  if (rx_message == NULL)
-    {
-      if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
-        {
-
-          //new message incoming
-          rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
-          rx_message->message_id_in = ntohl(fh->message_id);
-          rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
-          rx_message->session = session;
-          rx_message->timeout = GNUNET_TIME_absolute_add(
-              GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
-          rx_message->received_fragments = 0;
-
-          GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
-
-          session->fragment_messages_in_count++;
-          plugin->pending_receive_messages++;
-
-#if DEBUG_wlan
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_DEBUG,
-              "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
-              rx_message->message_id_in, session->fragment_messages_in_count,
-              plugin->pending_receive_messages);
-#endif
-        }
-      else
-        {
-
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_INFO,
-              "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached, akt in message_id %u\n",
-              get_receive_message_from_session(plugin, session)->message_id_in);
-          setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
-          return retval;
-        }
-    }
-
-  if (is_double_msg(rx_message, fh) != GNUNET_YES)
-    {
-
-      //report size
-      rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
-          ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
-      rx_frag->size = ntohs(fh->header.size)
-          - sizeof(struct FragmentationHeader);
-      rx_frag->num = ntohs(fh->fragment_off_or_num);
-      rx_frag->msg = (char*) &(rx_frag[1]);
-      //copy msg to buffer
-      memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
-      memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
-      insert_fragment_in_queue(rx_message, rx_frag);
-      //save bitfield
-      retval = rx_message->received_fragments;
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "New fragment:  size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
-          rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
-          rx_message->received_fragments, session);
-#endif
-
-      check_rx_finished_msg(plugin, session_light, session, rx_message);
-    }
-  else
-    {
-      GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
-      retval = rx_message->received_fragments;
-
-    }
-  return retval;
-
+//TODO ATS informations
+static void
+process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
+{
+
+  GNUNET_assert (client != NULL);
+  GNUNET_assert (cls != NULL);
+  struct Session *session = (struct Session *) client;
+  struct Plugin *plugin = (struct Plugin *) cls;
+  struct GNUNET_ATS_Information ats[2];
+
+  ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
+  ats[0].value = htonl (1);
+  ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
+  ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Calling plugin->env->receive for session %p; %s; size: %u\n",
+                   session, wlan_plugin_address_to_string (NULL,
+                                                           session->mac->
+                                                           addr.mac, 6),
+                   htons (hdr->size));
+  plugin->env->receive (plugin->env->cls, &(session->target), hdr,
+                        (const struct GNUNET_ATS_Information *) &ats, 2,
+                        session, (const char *) &session->mac->addr,
+                        sizeof (session->mac->addr));
 }
 
 /**
  * Function used for to process the data received from the wlan interface
  *
  * @param cls the plugin handle
- * @param session_light FIXME: document
  * @param hdr hdr of the GNUNET_MessageHeader
+ * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS info
  */
 static void
-wlan_data_helper(void *cls, struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
+wlan_data_helper (void *cls, 
+                  const struct GNUNET_MessageHeader *hdr,
+                 const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo)
 {
   struct Plugin *plugin = cls;
-  struct Session * session;
-
-  struct FragmentationHeader * fh;
-  struct FragmentationAckHeader * fah;
-  struct FragmentMessage * fm;
-
-  const char * tempmsg;
-
-  uint64_t fragment_bitfield = 0;
+  struct FragmentMessage *fm;
+  struct FragmentMessage *fm2;
+  struct GNUNET_PeerIdentity tmpsource;
+  struct MacEndpoint *macendpoint;
+  struct Session *session;
 
-  //ADVERTISEMENT
-  if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
+  // NOTE: session_light->addr = rxinfo->frame.addr2;
+  macendpoint = get_macendpoint (plugin, &rxinfo->frame.addr2, GNUNET_YES);
+
+  switch (ntohs (hdr->type))
+  {
+  case GNUNET_MESSAGE_TYPE_HELLO:
+    //ADVERTISEMENT
+    //TODO better DOS protection, error handling
+    //TODO test first then create session
+    if (GNUNET_HELLO_get_id
+        ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
     {
-
-      //TODO better DOS protection, error handling
-      //TODO test first than create session
-      GNUNET_assert(session_light != NULL);
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "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));
-#endif
-
-      if (session_light->session == NULL)
-        {
-          session_light->session = get_session(plugin, &session_light->addr);
-        }
-      GNUNET_assert(GNUNET_HELLO_get_id(
-              (const struct GNUNET_HELLO_Message *) &hdr[1],
-              &(session_light->session->target) ) != GNUNET_SYSERR);
-
+      session = search_session (plugin, macendpoint, &tmpsource);
+      if (session == NULL)
+      {
+        session = create_session (plugin, macendpoint, &tmpsource);
+      }
+      GNUNET_STATISTICS_update (plugin->env->stats,
+                                _("# wlan hello messages received"), 1,
+                                GNUNET_NO);
+      plugin->env->receive (plugin->env->cls, &session->target,
+                            hdr, NULL, 0, session,
+                            (const char *) &session->mac->addr,
+                            sizeof (session->mac->addr));
     }
-
-  //FRAGMENT
-
-  else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
+    else
     {
-
-      GNUNET_assert(session_light != NULL);
-      if (session_light->session == NULL)
-        {
-          session_light->session = search_session(plugin, &session_light->addr);
-        }
-      session = session_light->session;
-
-      fh = (struct FragmentationHeader *) hdr;
-      tempmsg = (char*) &fh[1];
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
-          ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
-              hdr->size), wlan_plugin_address_to_string(NULL,
-              session_light->addr.mac, 6));
-#endif
-
-      if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
-        {
-          //wrong crc, dispose message
-          GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
-          return;
-        }
-
-      //if in the session list
-      if (session != NULL)
-        {
-          fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
-              session_light, session, fh, rxinfo);
-        }
-      else
-        {
-          // new session
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_INFO,
-              "WLAN client not in session list, fragment num %u, message id %u\n",
-              ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
-          wlan_data_message_handler(plugin, session_light,
-              (struct GNUNET_MessageHeader *) tempmsg);
-          session = session_light->session;
-          //test if a session was created
-          if (session == NULL)
-            {
-              return;
-            }
-          setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
-        }
-
-      add_ack_for_send(plugin, session, fragment_bitfield, fh);
-      set_next_send(plugin);
-
+      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                       "WLAN client not in session list and HELLO message is not okay\n");
+      return;
     }
-
-  //ACK
-
-  else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
+    break;
+  case GNUNET_MESSAGE_TYPE_FRAGMENT:
+    macendpoint = get_macendpoint (plugin, &rxinfo->frame.addr2, GNUNET_YES);
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan fragments received"), 1, GNUNET_NO);
+    int ret =
+        GNUNET_DEFRAGMENT_process_fragment (macendpoint->defrag,
+                                            hdr);
+
+    if (ret == GNUNET_NO)
     {
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
-          ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
-              session_light->addr.mac, 6));
-#endif
-
-      GNUNET_assert(session_light != NULL);
-      if (session_light->session == NULL)
-        {
-          session_light->session = search_session(plugin, &session_light->addr);
-          GNUNET_assert(session_light->session != NULL);
-        }
-      session = session_light->session;
-      fah = (struct FragmentationAckHeader *) hdr;
-      fm = get_fragment_message_from_session_and_id(plugin, session, ntohl(
-          fah->message_id));
-
-      if (fm != NULL)
-        {
-
-          fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
-              fah->fragment_field);
-          fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
-
-#if DEBUG_wlan_retransmission
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
-              fm->message_id_out, fm->ack_bitfield);
-#endif
-          check_finished_fragment(plugin, fm);
-          set_next_send(plugin);
-
-        }
-      else
-        {
-          GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-              "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
-                  fah->message_id));
-          return;
-        }
-
+      macendpoint->dups++;
     }
-  else
+    else if (ret == GNUNET_OK)
+    {
+      macendpoint->fragc++;
+    }
+    set_next_send (plugin);
+    break;
+  case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
+    if (NULL == macendpoint)
     {
-      // TODO Wrong data?
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_INFO,
-          "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
-          ntohs(hdr->type), ntohs(hdr->size));
-      GNUNET_break(0);
+      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,
+                                                                         &rxinfo->frame.addr2.mac,
+                                                                         6));
       return;
     }
+    fm = macendpoint->sending_messages_head;
+    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 0
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Helper finished\n");
-#endif
-
+      if (ret == GNUNET_OK)
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                         "Got last ack, finished fragment message %p\n", fm);
+        macendpoint->acks++;
+        fm->session->last_activity = GNUNET_TIME_absolute_get ();
+        macendpoint->last_activity = fm->session->last_activity;
+        free_fragment_message (plugin, fm);
+        check_fragment_queue (plugin);
+        return;
+      }
+      if (ret == GNUNET_NO)
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                         "Got ack for: %p\n", fm);
+        macendpoint->acks++;
+        return;
+      }
+      fm = fm2;
+    }
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "WLAN fragment not in fragment list\n");
+    return;
+  default:
+    // TODO Wrong data?
+    GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
+                     "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
+                     ntohs (hdr->type), ntohs (hdr->size));
+    GNUNET_break (0);
+    return;
+  }
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Helper finished\n");
 }
 
-const char *
-macprinter(const u_int8_t * mac)
+/**
+ * Function to print mac addresses nicely.
+ *
+ * @param mac the mac address
+ * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function
+ */
+static const char *
+macprinter (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
 {
   static char macstr[20];
 
-  GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
-      mac[2], mac[3], mac[4], mac[5]);
+  GNUNET_snprintf (macstr, sizeof (macstr), "%2X:%2X:%2X:%2X:%2X:%2X", mac->mac[0], mac->mac[1],
+                   mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]);
   return macstr;
 }
 
+/**
+ * Function for the scheduler if a mac endpoint times out
+ * @param cls pointer to the MacEndpoint
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ */
+static void
+macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct MacEndpoint *endpoint = cls;
+
+  GNUNET_assert (endpoint != NULL);
+  endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  {
+    return;
+  }
+  if (GNUNET_TIME_absolute_get_remaining
+      (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);
+  }
+}
+
+/**
+ * function to create an macendpoint
+ * @param plugin pointer to the plugin struct
+ * @param addr pointer to the macaddress
+ * @return returns a macendpoint
+ */
+static struct MacEndpoint *
+create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_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->last_activity = GNUNET_TIME_absolute_get ();
+  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);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "New Mac Endpoint %p: %s\n", newend,
+                   wlan_plugin_address_to_string (NULL, newend->addr.mac, 6));
+  return newend;
+}
+
 /**
  * Function used for to process the data from the suid process
  *
@@ -2676,291 +2758,177 @@ macprinter(const u_int8_t * mac)
  * @param hdr header of the GNUNET_MessageHeader
  */
 static void
-wlan_process_helper(void *cls, void *client,
-    const struct GNUNET_MessageHeader *hdr)
+wlan_process_helper (void *cls, void *client,
+                     const struct GNUNET_MessageHeader *hdr)
 {
   struct Plugin *plugin = cls;
-  struct ieee80211_frame * wlanIeeeHeader = NULL;
-  struct Session_light * session_light = NULL;
-  struct Radiotap_rx * rxinfo;
-  const struct GNUNET_MessageHeader * temp_hdr = NULL;
-
+  const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo;
+  const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm;
+  const struct GNUNET_MessageHeader *temp_hdr = NULL;
+  const char *end;
   int datasize = 0;
   int pos;
 
-  switch (ntohs(hdr->type))
-    {
-  case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
-#if DEBUG_wlan
-    GNUNET_log(
-        GNUNET_ERROR_TYPE_DEBUG,
-        "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
-        ntohs(hdr->size));
-#endif
-
+  GNUNET_assert (plugin != NULL);
+  switch (ntohs (hdr->type))
+  {
+  case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER:
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Got data message from helper with %u bytes\n",
+                     ntohs (hdr->size));
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan data messages 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 DEBUG_wlan
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-            "Size of packet is too small; size: %u min size: %u\n", ntohs(
-                hdr->size), 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];
+    if (ntohs (hdr->size) < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "Size of packet is too small; size: %u\n",
+                       ntohs (hdr->size));
+      GNUNET_break (0);
+      /* FIXME: restart SUID process */
+      return;
+    }
 
+    rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr;
     //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
+        (&rxinfo->frame.addr3, &mac_bssid_gnunet,
+         sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
+    {
+      //check for broadcast or mac
+      if ((memcmp
+           (&rxinfo->frame.addr1, &bc_all_mac,
+            sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0) ||
+          (memcmp
+           (&rxinfo->frame.addr1, &plugin->mac_address,
+            sizeof (struct GNUNET_TRANSPORT_WLAN_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 packet is from us return
+        if ((memcmp
+             (&rxinfo->frame.addr2, &plugin->mac_address,
+              sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0))
+        {
+         /* not for us */
+          return;
+        }
+        datasize = ntohs (hdr->size) - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage);
+        GNUNET_STATISTICS_update (plugin->env->stats,
+                                  _("# wlan messages for this client received"),
+                                  1, GNUNET_NO);
+       // FIXME: this is a job for SERVER_mst -- 
+       // what we are doing here is not good for alignment...
+        pos = 0;
+       end = (const char*) &rxinfo[1];
+        while (pos < datasize - sizeof (struct GNUNET_MessageHeader))
+        {
+          temp_hdr = (struct GNUNET_MessageHeader *) &end[pos];
+          if (ntohs (temp_hdr->size) <= datasize - pos)
           {
-
-            // process the inner data
-
-
-            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);
-
-            pos = 0;
-            while (pos < datasize)
-              {
-                temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
-                    + pos;
-
-                wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
-                pos += ntohs(temp_hdr->size);
-
-              }
-
-            //clean up
-            GNUNET_free(session_light);
+            GNUNET_STATISTICS_update (plugin->env->stats,
+                                      _
+                                      ("# wlan messages inside WLAN_HELPER_DATA received"),
+                                      1, GNUNET_NO);
+            wlan_data_helper (plugin, temp_hdr, rxinfo);
           }
-        else
+          else
           {
-#if DEBUG_wlan
-            GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
-                    wlanIeeeHeader->i_addr1));
-#endif
+            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);
           }
+          pos += ntohs (temp_hdr->size);
+        }
       }
-    else
+      else
       {
-#if DEBUG_wlan
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-            "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
-                wlanIeeeHeader->i_addr2));
-#endif
+        GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                         "Func wlan_process_helper got wrong MAC: %s\n",
+                         macprinter (&rxinfo->frame.addr1));
       }
+    }
+    else
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "Func wlan_process_helper got wrong BSSID: %s\n",
+                       macprinter (&rxinfo->frame.addr2));
+    }
     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);
-        /* FIXME: restart SUID process */
-        return;
-      }
-    memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
-#if DEBUG_wlan
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-        "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
-        wlan_plugin_address_to_string(cls, &plugin->mac_address,
-            sizeof(struct MacAddress)));
-#endif
-    plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
-        sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
+    if (ntohs (hdr->size) != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
+    {
+      GNUNET_break (0);
+      /* FIXME: restart SUID process */
+      return;
+    }
+    cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr;
+    plugin->mac_address = cm->mac;
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
+                     wlan_plugin_address_to_string (cls, &plugin->mac_address,
+                                                    sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)));
+    plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
+                                 &plugin->mac_address,
+                                 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
     break;
   default:
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "Func wlan_process_helper got unknown message with number %u, size %u\n",
+                     ntohs (hdr->type), ntohs (hdr->size));
     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 DEBUG_wlan
-   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-   "Start reading from STDIN\n");
-   #endif
-   */
-  if (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(GNUNET_ERROR_TYPE_DEBUG,
-          _("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 * filename = "gnunet-transport-wlan-helper";
-  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;
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
-      plugin->interface, testmode);
-#endif
-  /* Start the server process */
-
-  plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
-      plugin->server_stdout, filename, filename, plugin->interface, ((testmode
-          == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
-  if (plugin->server_proc == NULL)
-    {
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "Failed to start gnunet-wlan-helper process\n");
-#endif
-      return GNUNET_SYSERR;
-    }
-
-  /* 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(GNUNET_ERROR_TYPE_DEBUG,
-      "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;
-}
 
 /**
  * Exit point from the plugin.
  * @param cls pointer to the api struct
  */
-
 //FIXME cleanup
 void *
-libgnunet_plugin_transport_wlan_done(void *cls)
+libgnunet_plugin_transport_wlan_done (void *cls)
 {
   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
-  struct Sessionqueue * queue = plugin->sessions;
-  struct Sessionqueue * queue_next;
-  struct FragmentMessage * fm;
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "libgnunet_plugin_transport_wlan_done started\n");
-#endif
-
-  GNUNET_assert(cls !=NULL);
-
+  struct MacEndpoint *endpoint;
+  struct MacEndpoint *endpoint_next;
+
+  if (NULL == plugin)
+  {
+    GNUNET_free (api);
+    return NULL;
+  }
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "libgnunet_plugin_transport_wlan_done started\n");
+  wlan_transport_stop_wlan_helper (plugin);
+
+  GNUNET_assert (cls != NULL);
+  //free sessions
+  endpoint = plugin->mac_head;
+  while (endpoint != NULL)
+  {
+    endpoint_next = endpoint->next;
+    free_macendpoint (plugin, endpoint);
+    endpoint = endpoint_next;
+
+  }
   if (plugin->suid_tokenizer != NULL)
-    GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
+    GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
 
   if (plugin->data_tokenizer != NULL)
-    GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
-
-  fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
-      plugin->pending_Fragment_Messages);
+    GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
 
-  while (fm != NULL)
-    {
-      free_fragment_message(plugin, fm);
-      fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
-          plugin->pending_Fragment_Messages);
-    }
-
-  //free sessions
-  while (queue != NULL)
-    {
-      queue_next = queue->next;
-      free_session(plugin, queue);
-      queue = queue_next;
-
-    }
-
-  GNUNET_free_non_null(plugin->interface);
-  GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
+  GNUNET_free_non_null (plugin->interface);
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;
 }
 
+
 /**
  * Entry point for the plugin.
  *
@@ -2968,37 +2936,51 @@ libgnunet_plugin_transport_wlan_done(void *cls)
  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
  */
 void *
-libgnunet_plugin_transport_wlan_init(void *cls)
+libgnunet_plugin_transport_wlan_init (void *cls)
 {
-  //struct GNUNET_SERVICE_Context *service;
   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *api;
   struct Plugin *plugin;
-  static unsigned long long testmode = 0;
 
-  GNUNET_assert(cls !=NULL);
+  if (NULL == env->receive)
+  {
+    /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+       initialze the plugin or the API */
+    api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+    api->cls = NULL;
+    api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
+    api->address_to_string = &wlan_plugin_address_to_string;
+    api->string_to_address = NULL; // FIXME!
+    return api;
+  }
 
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
   plugin->pendingsessions = 0;
-  plugin->session_count = 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;
-  plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
-      GNUNET_CONTAINER_HEAP_ORDER_MIN);
+  GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
+                                 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);
+  plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
 
   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
-  //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
+  //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
 
   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
   api->cls = plugin;
   api->send = &wlan_plugin_send;
+  api->get_session = &wlan_plugin_get_session;
   api->disconnect = &wlan_plugin_disconnect;
   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
   api->check_address = &wlan_plugin_address_suggested;
@@ -3006,33 +2988,35 @@ libgnunet_plugin_transport_wlan_init(void *cls)
 
   //read config
 
-  if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
+  if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
+  {
+    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_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
-          "transport-wlan", "TESTMODE", &testmode))
-        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)
-        {
-          libgnunet_plugin_transport_wlan_done(api);
-          return NULL;
-        }
+      libgnunet_plugin_transport_wlan_done (api);
+      return NULL;
     }
+  }
 
   //start the plugin
-  set_next_beacon_time(plugin);
+  wlan_transport_start_wlan_helper (plugin);
+  set_next_beacon_time (plugin);
+  set_next_send (plugin);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "wlan init finished\n");
+  return api;
+}
 
-  wlan_transport_start_wlan_helper(plugin, testmode);
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
-#endif
 
-  return api;
-}
 
 /* end of plugin_transport_wlan.c */