-makefile for new test_stream_local (commented)
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
index f184ff47aeaa217fcc09dbe5d03762066c5f0d89..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 "gnunet_fragmentation_lib.h"
+#include "gnunet_constants.h"
+
+/**
+ * DEBUG switch
+ */
+#define DEBUG_WLAN GNUNET_EXTRA_LOGGING
+
 
 #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
+/**
+ * time out of a mac endpoint
+ */
+#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
+
+/**
+ * scaling factor for hello beacon
+ */
+#define HELLO_BEACON_SCALING_FACTOR 30
+
+/**
+ * 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_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.
@@ -91,50 +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
    */
-
-  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;
 
@@ -163,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
@@ -186,81 +216,164 @@ struct Plugin
   unsigned int pendingsessions;
 
   /**
-   * Messages in the fragmentation queue, head
+   * Messages in the sending queues
    */
-
-  struct FragmentMessage * pending_Fragment_Messages_head;
+  int pending_Fragment_Messages;
 
   /**
-   * Messages in the fragmentation queue, tail
+   * messages ready for send, head
    */
-
-  struct FragmentMessage * pending_Fragment_Messages_tail;
+  struct FragmentMessage_queue *sending_messages_head;
 
   /**
-   * number of pending fragment message
+   * messages ready for send, tail
    */
-
-  unsigned int pending_fragment_messages;
+  struct FragmentMessage_queue *sending_messages_tail;
 
   /**
    * time of the next "hello-beacon"
    */
-
   struct GNUNET_TIME_Absolute beacon_time;
 
   /**
-   * queue to send acks for received fragments
+   * 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;
 };
 
+/**
+ * Struct to store data if file write did not accept the whole packet
+ */
 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;
 };
 
 /**
  * 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 ack received for messages send
+ * Queue of fragmented messages, for the sending queue of the plugin
  */
-
-struct AckQueue
+//TODO DOXYGEN
+struct FragmentMessage_queue
 {
-  struct AckQueue * next;
-  struct AckQueue * prev;
-  int fragment_num; //TODO change it to offset if better
+  struct FragmentMessage_queue *next;
+  struct FragmentMessage_queue *prev;
+  struct FragmentMessage *content;
 };
 
+
 /**
  * Queue for the fragments received
  */
-
-struct RecQueue
+//TODO DOXYGEN
+struct Receive_Fragment_Queue
 {
-  struct RecQueue * next;
-  struct RecQueue * prev;
+  struct Receive_Fragment_Queue *next;
+  struct Receive_Fragment_Queue *prev;
+
   uint16_t num;
-  const char * msg;
-  uint16_t size;
+  // const char *msg;
+  //   uint16_t size;
+  struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rx_msg;
+};
+
+
+//TODO DOXYGEN
+struct MacEndpoint_id_fragment_triple
+{
+  struct MacEndpoint *endpoint;
+  uint32_t message_id;
+  struct FragmentMessage *fm;
+};
+
+//TODO DOXYGEN
+struct Plugin_Session_pair
+{
+  struct Plugin *plugin;
+  struct Session *session;
+};
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Header for messages which need fragmentation
+ */
+struct WlanHeader
+{
+
+  /**
+   * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * checksum/error correction
+   */
+  uint32_t crc GNUNET_PACKED;
+
+  /**
+   * To whom are we talking to (set to our identity
+   * if we are still waiting for the welcome message)
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   *  Where the packet came from
+   */
+  struct GNUNET_PeerIdentity source;
+
+// followed by payload
+
 };
+GNUNET_NETWORK_STRUCT_END
 
 /**
  * Information kept for each message that is yet to
@@ -268,11 +381,20 @@ struct RecQueue
  */
 struct PendingMessage
 {
+  /**
+   * dll next
+   */
+  struct PendingMessage *next;
+
+  /**
+   * dll prev
+   */
+  struct PendingMessage *prev;
 
   /**
    * The pending message
    */
-  char *msg;
+  struct WlanHeader *msg;
 
   /**
    * Size of the message
@@ -289,7 +411,7 @@ struct PendingMessage
   /**
    * Cls for transmit_cont
    */
-  void * transmit_cont_cls;
+  void *transmit_cont_cls;
 
   /**
    * Timeout value for the pending message.
@@ -298,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 GNUNET_PACKED;
+  struct AckSendQueue *next;
 
   /**
-   * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
+   * previous ack in the ack send queue
    */
-  uint16_t fragment_off_or_num GNUNET_PACKED;
-
-};
+  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.
    */
-  uint8_t addr[6];
+  const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
 };
 
+
 /**
  * Session handle for connections.
  */
@@ -349,15 +466,16 @@ struct Session
   struct SessionHeader header;
 
   /**
-   * Pointer to the global plugin struct.
+   * Message currently pending for transmission
+   * to this peer, if any. head
    */
-  struct Plugin *plugin;
+  struct PendingMessage *pending_message_head;
 
   /**
    * Message currently pending for transmission
-   * to this peer, if any.
+   * to this peer, if any. tail
    */
-  struct PendingMessage *pending_message;
+  struct PendingMessage *pending_message_tail;
 
   /**
    * To whom are we talking to (set to our identity
@@ -365,42 +483,6 @@ struct Session
    */
   struct GNUNET_PeerIdentity target;
 
-  /**
-   * encapsulation of the receive data
-   */
-  //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
-
-  /**
-   * offset of the next fragment for the receive_token, -1 means last message finished
-   */
-
-  //int rec_offset;
-
-  /**
-   * size of the message received,
-   * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
-   * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
-   */
-
-  int rec_size;
-
-  /**
-   * Sorted queue with the fragments received; head
-   */
-
-  struct RecQueue * frag_head;
-
-  /**
-   * Sorted queue with the fragments received; tail
-   */
-
-  struct RecQueue * frag_tail;
-
-  /**
-   * peer mac address
-   */
-  char addr[6];
-
   /**
    * Address of the other peer (either based on our 'connect'
    * call or on our 'accept' call).
@@ -409,578 +491,674 @@ struct Session
 
   /**
    * Last activity on this connection.  Used to select preferred
-   * connection.
+   * connection and timeout
    */
   struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   * current number for message incoming, to distinguish between the messages
+   * Timeout task.
    */
-  uint32_t message_id_in;
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
   /**
-   * current number for message outgoing, to distinguish between the messages
+   * peer connection
    */
-  uint32_t message_id_out;
+  struct MacEndpoint *mac;
 
   /**
-   * does this session have a message in the fragment queue
+   * count of messages in the fragment out queue for this session
    */
 
-  int has_fragment;
+  int fragment_messages_out_count;
 
 };
 
 /**
- * Struct for Messages in the fragment queue
+ * Struct to represent one network card connection
  */
-
-struct FragmentMessage
+struct MacEndpoint
 {
   /**
-   * Session this message belongs to
+   * Pointer to the global plugin struct.
    */
-
-  struct Session *session;
+  struct Plugin *plugin;
 
   /**
-   * This is a doubly-linked list.
+   * Struct to hold the session reachable over this mac; head
    */
-  struct FragmentMessage *next;
+  struct Sessionqueue *sessions_head;
 
   /**
-   * This is a doubly-linked list.
+   * Struct to hold the session reachable over this mac; tail
    */
-  struct FragmentMessage *prev;
+  struct Sessionqueue *sessions_tail;
 
   /**
-   * The pending message
+   * Messages currently sending
+   * to a peer, if any.
    */
-  char *msg;
+  struct FragmentMessage *sending_messages_head;
 
   /**
-   * Timeout value for the pending message.
+   * Messages currently sending
+   * to a peer (tail), if any.
    */
-  struct GNUNET_TIME_Absolute timeout;
+  struct FragmentMessage *sending_messages_tail;
 
   /**
-   * Timeout value for the pending fragments.
-   * Stores the time when the next msg fragment ack has to be received
+   * dll next
    */
-  struct GNUNET_TIME_Absolute next_ack;
+  struct MacEndpoint *next;
 
   /**
-   * Sorted queue with the acks received for fragments; head
+   * dll prev
    */
-
-  struct AckQueue * head;
+  struct MacEndpoint *prev;
 
   /**
-   * Sorted queue with the acks received for fragments; tail
+   * peer mac address
    */
-
-  struct AckQueue * tail;
+  struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
 
   /**
-   * Size of the message
+   * Defrag context for this mac endpoint
    */
-  size_t message_size;
+  struct GNUNET_DEFRAGMENT_Context *defrag;
 
   /**
-   * pos / next fragment number in the message, for fragmentation/segmentation,
-   * some acks can be missing but there is still time
+   * count of messages in the fragment out queue for this mac endpoint
    */
-  uint32_t message_pos;
-
-};
+  int fragment_messages_out_count;
 
-/**
- * Header for messages which need fragmentation
- */
-struct WlanHeader
-{
+  //TODO DOXYGEN
+  uint8_t rate;
+  uint16_t tx_power;
+  uint8_t antenna;
 
-  struct GNUNET_MessageHeader header;
+  /**
+   * Duplicates received
+   */
+  int dups;
 
   /**
-   * checksum/error correction
+   * Fragments received
    */
-  uint32_t crc GNUNET_PACKED;
+  int fragc;
 
   /**
-   * To whom are we talking to (set to our identity
-   * if we are still waiting for the welcome message)
+   * Acks received
    */
-  struct GNUNET_PeerIdentity target;
+  int acks;
 
-// followed by payload
+  /**
+   * Last activity on this endpoint.  Used to select preferred
+   * connection.
+   */
+  struct GNUNET_TIME_Absolute last_activity;
 
+  /**
+   * Timeout task.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 };
 
 /**
- * Header for messages which need fragmentation
+ * Struct for Messages in the fragment queue
  */
-struct FragmentationHeader
+struct FragmentMessage
 {
 
-  struct GNUNET_MessageHeader header;
+  /**
+   * Session this message belongs to
+   */
+  struct Session *session;
 
   /**
-   * To whom are we talking to (set to our identity
-   * if we are still waiting for the welcome message)
+   * This is a doubly-linked list.
    */
-  // struct GNUNET_PeerIdentity target GNUNET_PACKED;
+  struct FragmentMessage *next;
 
   /**
-   * ID of message, to distinguish between the messages, picked randomly.
+   * This is a doubly-linked list.
    */
-  uint32_t message_id GNUNET_PACKED;
+  struct FragmentMessage *prev;
 
   /**
-   * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
+   * Fragmentation context
    */
-  uint16_t fragment_off_or_num GNUNET_PACKED;
+  struct GNUNET_FRAGMENT_Context *fragcontext;
 
   /**
-   * CRC of fragment (for error checking)
+   * Timeout value for the message.
    */
-  uint16_t message_crc GNUNET_PACKED;
+  struct GNUNET_TIME_Absolute timeout;
 
-/**
- * Flags
- * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
- * // 0x2 has data (not only ack)
- * // 0x4 last fragment of message
- * // 0x8 new message
- */
-//  uint32_t flags GNUNET_PACKED;
+  /**
+   * Timeout task.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
-/**
- * checksum/error correction
- */
-// uint32_t crc GNUNET_PACKED;
+  /**
+   * pointer to the radiotap header
+   */
+  struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
+};
 
-// followed by payload unless ACK
 
-};
+static void
+do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
-int
-getRadiotapHeader(struct RadiotapHeader * Header);
 
-int
-getWlanHeader(struct IeeeHeader * Header,const char * to_mac_addr,
-    struct Plugin * plugin);
+static void
+free_session (struct Plugin *plugin, struct Sessionqueue *queue,
+              int do_free_macendpoint);
 
-static int
-wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
 
-uint16_t
-getcrc16(const char *msgbuf, size_t msgbuf_size);
+static struct MacEndpoint *
+create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr);
 
-static void
-do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
 static void
-check_fragment_queue(struct Plugin * plugin);
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
-uint32_t
-getcrc32(const char *msgbuf, size_t msgbuf_size);
 
+/**
+ * Generates a nice hexdump of a memory area.
+ *
+ * \param  mem     pointer to memory to dump
+ * \param  length  how many bytes to dump
+ */
 static void
-free_rec_frag_queue(struct Session * session);
+hexdump (const void *mem, unsigned length)
+{
+  char line[80];
+  char *src = (char *) mem;
 
-static void
-wlan_data_helper(void *cls, struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr);
+  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;
 
-static void
-wlan_process_helper(void *cls, void *client,
-    const struct GNUNET_MessageHeader *hdr);
+  for (i = 0; i < length; i += 16, src += 16)
+  {
+    char *t = line;
 
-static void
-finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+    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, "  ");
 
-static void
-wlan_data_massage_handler(struct Plugin * plugin,
-    struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr);
+      t += sprintf (t, (j % 2) ? " " : "-");
+    }
 
-static const char *
-wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen);
+    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, " ");
+      }
+    }
 
-/**
- * get the next message number, at the moment just a random one
- * @return returns the next valid message-number for sending packets
- */
-uint32_t
-get_next_message_id()
-{
-  return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+    t += sprintf (t, "\r\n");
+    printf ("%s", line);
+  }
 }
 
+
 /**
- * start next message number generator
- * (not necessary at the moment)
+ * 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
  */
-void
-start_next_message_id()
+static struct MacEndpoint *
+get_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
+                 int create_new)
 {
-  //GNUNET_CRYPTO_random_init;
+  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 uint8_t * addr)
+search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
+                const struct GNUNET_PeerIdentity *peer)
 {
-  struct Sessionqueue * queue = plugin->sessions;
-  struct Sessionqueue * lastitem = NULL;
+  GNUNET_assert (endpoint != NULL);
+  struct Sessionqueue *queue = endpoint->sessions_head;
 
-  //just look at all the session for the needed one
   while (queue != NULL)
-    {
-      // content is never NULL
-      GNUNET_assert (queue->content != NULL);
-      char * addr2 = queue->content->addr;
-      if (memcmp(addr, addr2, 6) == 0)
-        {
-          //sesion found
-          return queue->content;
-        }
-      // try next
-      lastitem = queue;
-      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;
 }
 
 /**
- * create a new session
+ * Function called for a quick conversion of the binary address to
+ * a numeric address.  Note that the caller must not free the
+ * address and that the next call to this function is allowed
+ * to override the address again.
  *
- * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac address of the peer
- * @return returns the session
+ * @param cls closure
+ * @param addr binary address
+ * @param addrlen length of the address
+ * @return string representing the same address
  */
-
-static struct Session *
-create_session(struct Plugin *plugin, const uint8_t * addr)
+static const char *
+wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
 {
-  struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
-
-  GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
+  static char ret[40];
+  const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
+
+  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]);
 
-  queue->content = GNUNET_malloc (sizeof (struct Session));
-  queue->content->plugin = plugin;
-  memcpy(queue->content->addr, addr, 6);
-  queue->content->message_id_out = get_next_message_id();
-  queue->content->has_fragment = 0;
-  queue->content->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
+  return ret;
+}
 
-  plugin->session_count++;
+/**
+ * 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;
 
-#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
+  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 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, 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
+ * 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
  */
-//TODO add other possibilities to find the right session (are there other?)
 static struct Session *
-get_Session(struct Plugin *plugin, const uint8_t * 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;
-    }
-  // new session
-  return create_session(plugin, addr);
-
-  /* -- not needed, layer above already has it--
-   //queue welcome message for new sessions, not realy needed
-   //struct WelcomeMessage welcome;
-   struct PendingMessage *pm;
-   pm = GNUNET_malloc (sizeof (struct PendingMessage));
-   pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
-   pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
-   //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
-   //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
-   //welcome.clientIdentity = *plugin->env->my_identity;
-   memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
-   pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
-   queue->content->pending_message = pm;
-   plugin->pendingsessions ++;
-   GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
-
-   check_fragment_queue(plugin);
-   */
+    return session;
+  return create_session (plugin, mac, peer);
 }
 
 /**
  * Queue the session to send data
+ * checks if there is a message pending
+ * checks if this session is not allready in the queue
+ * @param plugin pointer to the plugin
+ * @param session pointer to the session to add
  */
-//TODO doxigen
 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;
 
-  while (queue != NULL)
+  if (session->pending_message_head != NULL)
+  {
+    while (queue != NULL)
     {
       // content is never NULL
       GNUNET_assert (queue->content != NULL);
       // is session already in queue?
       if (session == queue->content)
-        {
-          return;
-        }
+      {
+        return;
+      }
       // try next
-      lastitem = queue;
       queue = queue->next;
     }
 
-  // Session is not in the queue
-
-  queue = GNUNET_malloc (sizeof (struct Sessionqueue));
-  queue->content = session;
+    // Session is not in the queue
 
-  //insert at the tail
-  GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
-      plugin->pending_Sessions_tail,
-      plugin->pending_Sessions_tail, queue);
-  plugin->pendingsessions++;
+    queue = GNUNET_malloc (sizeof (struct Sessionqueue));
+    queue->content = session;
 
-}
+    //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
-static void
-free_acks(struct FragmentMessage * fm)
-{
-  struct AckQueue * fq;
-  while (fm->head != NULL)
-    {
-      fq = fm->head;
-      GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
-      GNUNET_free(fq);
-    }
-  //needed?
-  fm->head = NULL;
-  fm->tail = NULL;
 }
 
-//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));
-    }
-}
-
-//TODO doxigen
-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));
+  {
+    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
-/**
- * Function to get the timeout value for acks for this session
- */
-
-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
-check_next_fragment_timeout(struct Plugin * const plugin)
+set_next_send (struct Plugin *plugin)
 {
-  struct FragmentMessage * fm;
   struct GNUNET_TIME_Relative next_send;
 
-  next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
+  //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 = plugin->pending_Fragment_Messages_head;
-
-  GNUNET_assert(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;
+  }
 
   //check if some acks are in the queue
   if (plugin->ack_send_queue_head != NULL)
+  {
+    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_relative_get_zero();
+      plugin->server_write_task =
+          GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                           plugin->server_stdin_handle,
+                                           &do_transmit, plugin);
     }
-  //check if there are some fragments in the queue
-  else if (fm != NULL)
+  }
+  else
+  {
+    if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
     {
-      next_send
-          = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
+      plugin->server_write_delay_task =
+          GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
+                                        plugin);
     }
-  plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
-      &delay_fragment_task, plugin);
+  }
 }
 
-//TODO doxigen
 /**
  * Function to get the next queued Session, removes the session from the queue
+ * @param plugin pointer to the plugin struct
+ * @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;
-  while (sessionqueue != NULL)
-    {
-      session = sessionqueue->content;
-      pm = session->pending_message;
-
-      //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->has_fragment)
-            {
-              plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-                  plugin->pending_Sessions_tail, sessionqueue);
-              GNUNET_free(sessionqueue);
-
-              return session;
-            }
-          else
-            {
-              sessionqueue = sessionqueue->next;
-            }
-        }
-      else
-        {
+  struct Session *session;
+  struct Sessionqueue *sessionqueue;
+  struct Sessionqueue *sessionqueue_alt;
+  struct PendingMessage *pm;
 
-          session->pending_message = 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);
+  sessionqueue = plugin->pending_Sessions_head;
 
-          sessionqueue_alt = sessionqueue;
-          sessionqueue = sessionqueue->next;
-          plugin->pendingsessions--;
-          GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-              plugin->pending_Sessions_tail, sessionqueue_alt);
+  while (sessionqueue != NULL)
+  {
+    session = sessionqueue->content;
 
-          GNUNET_free(sessionqueue_alt);
+    GNUNET_assert (session != NULL);
+    pm = session->pending_message_head;
 
-        }
+    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;
 
     }
-  return NULL;
-}
-
-/**
- * Function to sort the message into the message fragment queue
- * @param plugin the plugin struct
- * @param fm message to sort into the queue
- */
-static void
-sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
-{
-  struct FragmentMessage * fm2;
-  //sort into the list at the right position
 
-  fm2 = plugin->pending_Fragment_Messages_head;
-
-  while (fm2 != NULL)
+    //check for message timeout
+    if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
     {
-      if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value
-          == 0)
-        {
-          break;
-        }
+      //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
-        {
-          fm2 = fm2->next;
-        }
+      {
+        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);
+      }
     }
 
-  GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
-      plugin->pending_Fragment_Messages_tail,fm2,fm);
+  }
+  return NULL;
 }
 
 /**
@@ -989,693 +1167,1113 @@ sort_fragment_into_queue(struct Plugin * plugin, struct FragmentMessage * fm)
  * @param fm message to free
  */
 static void
-free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
+free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
 {
-  if (fm != NULL)
+  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)
     {
-      free_acks(fm);
-      GNUNET_free_non_null(fm->msg);
-      GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
-          plugin->pending_Fragment_Messages_tail, fm);
-      GNUNET_free(fm);
-      plugin->pending_fragment_messages--;
-      check_fragment_queue(plugin);
-
-#if DEBUG_wlan
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Pending fragment messages: %u\n", 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 void
-check_fragment_queue(struct Plugin * plugin)
+static int
+getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
+                   struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
+                  uint16_t size)
 {
-  struct Session * session;
-  struct FragmentMessage * fm;
-  struct GNUNET_PeerIdentity pid;
+  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;
+  }
 
-  struct PendingMessage * pm;
+  return GNUNET_YES;
+}
 
-  if (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->has_fragment = 1;
-          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();
-
-          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);
 
-          sort_fragment_into_queue(plugin, fm);
-          plugin->pending_fragment_messages++;
+/**
+ * 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;
+
+  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;
+}
+
 
-          //generate new message id
-          session->message_id_out = get_next_message_id();
+/**
+ * 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;
 
-          //check if timeout changed
-          check_next_fragment_timeout(plugin);
-        }
-    }
+  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)
 {
-  struct AckQueue * ack;
-  int counter = 0;
-
-  if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
-      * fm->tail->fragment_num)
-    {
-      ack = fm->head;
-      counter = 0;
-      //check if all acks are present
-      while (ack != NULL)
-        {
-          if (counter == ack->fragment_num)
-            {
-              counter++;
-              ack = ack->next;
-            }
-          else
-            {
-              //ack is missing
-              return;
-            }
-        }
-      fm->session->has_fragment = 0;
-      free_fragment_message(plugin, fm);
+  struct Plugin *plugin = cls;
 
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Finished a fragmented message\n");
-#endif
+  plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
 
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
 
-      check_next_fragment_timeout(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
  */
-
-void
-set_next_message_fragment_pos(struct FragmentMessage * fm)
+static int
+wlan_transport_start_wlan_helper (struct Plugin *plugin)
 {
-  struct AckQueue * akt = NULL;
-  //check if retransmit is needed
-  if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
+  const char *filenamehw = "gnunet-helper-transport-wlan";
+  const char *filenameloopback = "gnunet-helper-transport-wlan-dummy";
+  char *absolute_filename = NULL;
+
+  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;
+  }
+
+  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;
+
+  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];
 
-      // be positive and try again later :-D
-      fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
-      // find first missing fragment
+      GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
 
-      fm->message_pos = 0;
+      GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
+                       filenameloopback);
+
+      if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                         "Helper `%s' not found! %i\n", absolute_filename);
+        GNUNET_break (0);
+      }
     }
+  }
 
-  akt = fm->head;
-  //test if ack 0 (or X) was already received
-  while (akt != NULL)
-    {
-      //if fragment is present, take next
-      if (akt->fragment_num == fm->message_pos)
-        {
-          fm->message_pos++;
-        }
-      //next ack is bigger then the fragment number
-      //in case there is something like this: (acks) 1, 2, 5, 6, ...
-      //and we send 3 again, the next number should be 4
-      else if (akt->fragment_num > fm->message_pos)
-        {
-          break;
-        }
+  /* Start the server process */
+
+  if (plugin->testmode == 0)
+  {
 
-      akt = akt->next;
+    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);
+    }
 
+  }
+  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)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
+                       "`%s' not found, please look if it exists and is in the $PATH variable!\n",
+                       absolute_filename);
+      GNUNET_break (0);
+    }
+  }
+  else if (plugin->testmode == 2)
+  {
+    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)
+    {
+      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;
 }
 
-void
-send_hello_beacon(struct Plugin * plugin)
+/**
+ * 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
+wlan_transport_stop_wlan_helper (struct Plugin *plugin)
 {
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Stoping WLAN helper process\n");
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
-#endif
+  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;
+  }
 
-   uint16_t size = 0;
-   ssize_t bytes;
-   struct GNUNET_MessageHeader * msgheader = NULL;
-   struct IeeeHeader * ieeewlanheader = NULL;
-   struct RadiotapHeader * radioHeader = NULL;
-   struct GNUNET_MessageHeader * msgheader2 = NULL;
-
-   GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
-   *(plugin->env->our_hello)) <= WLAN_MTU);
-   size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct RadiotapHeader)
-   + sizeof(struct IeeeHeader) + sizeof(struct GNUNET_MessageHeader)
-   + GNUNET_HELLO_size(*(plugin->env->our_hello));
-
-   msgheader = GNUNET_malloc(size);
-   msgheader->size = htons(size);
-   msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
-   radioHeader = (struct RadiotapHeader*) &msgheader[1];
-   getRadiotapHeader(radioHeader);
-   ieeewlanheader = (struct IeeeHeader*) &radioHeader[1];
-   getWlanHeader(ieeewlanheader, bc_all_mac, plugin);
-
-   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, GNUNET_HELLO_size(
-   *(plugin->env->our_hello)));
-
-   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);
-   GNUNET_assert(bytes == size);
-   GNUNET_free(msgheader);
-
-  set_next_beacon_time(plugin);
-  check_next_fragment_timeout(plugin);
+  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;
 }
 
+/**
+ * function for delayed restart of the helper process
+ * @param cls Finish_send struct if message should be finished
+ * @param tc TaskContext
+ */
 static void
-send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
+delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
 
-  uint16_t size = 0;
-  ssize_t bytes;
-  struct GNUNET_MessageHeader * msgheader = NULL;
-  struct IeeeHeader * ieeewlanheader = NULL;
-  struct RadiotapHeader * radioHeader = NULL;
-  struct FragmentationHeader * msgheader2 = NULL;
+  plugin = finish->plugin;
 
-  GNUNET_assert(sizeof(struct FragmentationHeader) <= WLAN_MTU);
+  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;
+  }
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Sending ack for message_id %u with fragment number %u\n",
-      ack->message_id, ack->fragment_off_or_num);
-#endif
+  wlan_transport_start_wlan_helper (plugin);
 
-  size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct RadiotapHeader)
-      + sizeof(struct IeeeHeader) + sizeof(struct FragmentationHeader);
-  msgheader = GNUNET_malloc(size);
-  msgheader->size = htons(size);
-  msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+  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);
+  }
 
-  radioHeader = (struct RadiotapHeader*) &msgheader[1];
-  getRadiotapHeader(radioHeader);
-  ieeewlanheader = (struct IeeeHeader*) &radioHeader[1];
-  getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
+}
 
-  msgheader2 = (struct FragmentationHeader*) &ieeewlanheader[1];
-  msgheader2->header.size = htons(sizeof(struct FragmentationHeader));
-  msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
-  msgheader2->message_id = htonl(ack->message_id);
-  msgheader2->fragment_off_or_num = htons(ack->fragment_off_or_num);
+/**
+ * Function to restart the helper
+ * @param plugin pointer to the global plugin struct
+ * @param finish pointer to the Finish_send struct to finish
+ */
+static void
+restart_helper (struct Plugin *plugin, struct Finish_send *finish)
+{
+  static struct GNUNET_TIME_Relative next_try = { 1000 };
+  GNUNET_assert (finish != NULL);
 
-  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));
+  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);
 
-    }
-  GNUNET_assert(bytes != GNUNET_SYSERR);
-  GNUNET_assert(bytes == size);
-  GNUNET_free(msgheader);
-  check_next_fragment_timeout(plugin);
 }
 
 /**
- * Function called when wlan helper is ready to get some data
- *
- * @param cls closure
- * @param tc GNUNET_SCHEDULER_TaskContext
+ * 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
-do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
+  ssize_t bytes;
 
-  struct Plugin * plugin = cls;
+  plugin = finish->plugin;
   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  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);
 
-  struct Session * session = NULL;
-  struct FragmentMessage * fm = NULL;
-  struct IeeeHeader * ieeewlanheader = NULL;
-  struct RadiotapHeader * radioHeader = NULL;
-  struct GNUNET_MessageHeader * msgheader = NULL;
-
-  struct FragmentationHeader fragheader;
-  struct FragmentationHeader * fragheaderptr = NULL;
-  struct Finish_send * finish = NULL;
-  struct AckSendQueue * ack;
-  uint16_t size = 0;
-  ssize_t bytes;
-  const char * copystart = NULL;
-  uint16_t copysize = 0;
-  uint copyoffset = 0;
-
-  if (plugin->ack_send_queue_head != NULL)
+  if (bytes != finish->size)
+  {
+    if (bytes != GNUNET_SYSERR)
     {
-      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;
+      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);
     }
-
-  //test if a "hello-beacon" has to be send
-  if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
+    else
     {
-      send_hello_beacon(plugin);
-
-      return;
-
+      restart_helper (plugin, finish);
     }
+  }
+  else
+  {
+    GNUNET_free (finish->msgstart);
+    GNUNET_free (finish);
+    set_next_send (plugin);
+  }
+}
 
-  fm = plugin->pending_Fragment_Messages_head;
-  if (fm != NULL)
-    {
-      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_acks(fm);
-          GNUNET_assert(plugin->pending_fragment_messages > 0);
-          plugin->pending_fragment_messages--;
-          GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
-              plugin->pending_Fragment_Messages_tail, fm);
-
-          GNUNET_free(fm->msg);
-
-          GNUNET_free(fm);
-          check_fragment_queue(plugin);
-        }
-      else
-        {
-
-          //if (fm->message_size > WLAN_MTU)
-          // {
-          size += sizeof(struct FragmentationHeader);
-
-          set_next_message_fragment_pos(fm);
-
-          copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
-              * fm->message_pos;
-          fragheader.fragment_off_or_num = htons(fm->message_pos);
-          fragheader.message_id = htonl(session->message_id_out);
-          GNUNET_assert(copyoffset < fm->message_size);
-          copystart = fm->msg + copyoffset;
-          copysize = GNUNET_MIN(fm->message_size - copyoffset,
-              WLAN_MTU - sizeof(struct FragmentationHeader));
-          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;
-           }*/
-
-#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, time until timeout %u\n",
-              session->message_id_out, fm->message_pos, copysize
-                  + sizeof(struct FragmentationHeader),
-              GNUNET_TIME_absolute_get_remaining(fm->timeout));
-#endif
 
-          size += copysize;
-          size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
-              + sizeof(struct GNUNET_MessageHeader);
-          msgheader = GNUNET_malloc(size);
-          msgheader->size = htons(size);
-          msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
-          radioHeader = (struct RadiotapHeader*) &msgheader[1];
-          getRadiotapHeader(radioHeader);
-
-          ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
-          getWlanHeader(ieeewlanheader, fm->session->addr, plugin);
-
-          //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);
-
-          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;
-
-              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_assert(bytes == size);
+/**
+ * function to send a hello beacon
+ * @param plugin pointer to the plugin struct
+ */
+static void
+send_hello_beacon (struct Plugin *plugin)
+{
+  uint16_t size;
+  ssize_t bytes;
+  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);
+  }
+}
 
-              GNUNET_free(msgheader);
-              check_next_fragment_timeout(plugin);
-            }
 
-          //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);
+/**
+ * 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;
 
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
-                  plugin->pending_Fragment_Messages_tail, fm);
+  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);
+}
 
-              GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
-                  plugin->pending_Fragment_Messages_tail, fm);
-              // if fragments have opimized timeouts
-              //sort_fragment_into_queue(plugin,fm);
 
-            }
+/**
+ * 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;
 
-        }
-      return;
-    }
-  GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-      "do_transmit did nothing, should not happen!\n");
+  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;
 
-  GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
-  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->plugin = plugin;
-      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);
-      check_next_fragment_timeout(plugin);
     }
+  }
 
+  //check if timeout changed
+  set_next_send (plugin);
 }
 
-int
-getRadiotapHeader(struct RadiotapHeader * Header)
+
+/**
+ * Function to send an ack, does not free the ack
+ * @param plugin pointer to the plugin
+ */
+static void
+send_ack (struct Plugin *plugin)
 {
-  return GNUNET_YES;
+  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 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
+ * Function called when wlan helper is ready to get some data
+ *
+ * @param cls closure
+ * @param tc GNUNET_SCHEDULER_TaskContext
  */
-
-int
-getWlanHeader(struct IeeeHeader * Header,const char * const to_mac_addr,
-    struct Plugin * plugin)
+static void
+do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  memcpy(&Header->mac2, macbc, sizeof(macbc));
-  memcpy(&Header->mac3, plugin->mac_address.mac, sizeof(plugin->mac_address));
-  memcpy(&Header->mac1, to_mac_addr, sizeof(plugin->mac_address));
-  return GNUNET_YES;
+  struct Plugin *plugin = cls;
+  struct Session *session;
+  struct FragmentMessage *fm;
+  struct Finish_send *finish;
+  struct FragmentMessage_queue *fmq;
+  ssize_t bytes;
+
+  GNUNET_assert (plugin != NULL);
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  if (plugin->ack_send_queue_head != NULL)
+  {
+    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)
+  {
+    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)
+    {
+      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);
+    }
+    else
+    {
+      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);
 }
 
+
 /**
- * 32bit CRC
- *
- * @param msgbuf pointer tor the data
- * @param msgbuf_size size of the data
+ * Another peer has suggested an address for this
+ * peer and transport plugin.  Check that this could be a valid
+ * address.  If so, consider adding it to the list
+ * of addresses.
  *
- * @return 32bit crc value
+ * @param cls closure
+ * @param addr pointer to the address
+ * @param addrlen length of addr
+ * @return GNUNET_OK if this is a plausible address for this peer
+ *         and transport
  */
-
-uint32_t
-getcrc32(const char *msgbuf, size_t msgbuf_size)
+static int
+wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
 {
-  //TODO calc some crc
-  return 0;
+  //struct Plugin *plugin = cls;
+
+  /* check if the address is plausible; if so,
+   * add it to our list! */
+
+  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 */
+    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;
 }
 
+
 /**
- * 16bit CRC
+ * Creates a new outbound session the transport service will use to send data to the
+ * peer
  *
- * @param msgbuf pointer tor the data
- * @param msgbuf_size size of the data
- *
- * @return 16bit crc value
+ * @param cls the plugin
+ * @param address the address
+ * @return the session or NULL of max connections exceeded
  */
 
-uint16_t
-getcrc16(const char *msgbuf, size_t msgbuf_size)
+static struct Session *
+wlan_plugin_get_session (void *cls,
+                  const struct GNUNET_HELLO_Address *address)
 {
-  //TODO calc some crc
-  return 0;
+  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 = NULL;
-  struct WlanHeader * wlanheader = NULL;
-  //struct GNUNET_MessageHeader * innermsg =
-   //    (struct GNUNET_MessageHeader *) msgbuf;
-
-  //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;
-        }
-    }
-
-#if DEBUG_wlan
-  GNUNET_log(
-      GNUNET_ERROR_TYPE_DEBUG,
-      "wlan_plugin_send got %u bytes data, packet says it has %u bytes for %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n",
-      msgbuf_size, ntohs(innermsg->size), session->addr[0], session->addr[1],
-      session->addr[2], session->addr[3], session->addr[4], session->addr[5]);
-#endif
+  struct Plugin *plugin = cls;
+  struct PendingMessage *newmsg;
+  struct WlanHeader *wlanheader;
 
-  //TODO target "problem" not solved
-  session->target = *target;
+  GNUNET_assert (plugin != NULL);
+  GNUNET_assert (session != NULL);
+  GNUNET_assert (msgbuf_size > 0);
 
   //queue message:
-  //first queue session
-  queue_Session(plugin, session);
 
   //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\n",
-          GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value);
-      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);
+
+  GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
+                                    session->pending_message_tail, newmsg);
 
-  session->pending_message = newmsg;
+  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);
 
-  check_fragment_queue(plugin);
+  check_fragment_queue (plugin);
   //FIXME not the correct size
   return msgbuf_size;
+}
+
+
+/**
+ * function to free a mac endpoint
+ * @param plugin pointer to the plugin struct
+ * @param endpoint pointer to the MacEndpoint to free
+ */
+static void
+free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
+{
+  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);
 
 }
 
-//TODO doxigen
-static struct FragmentMessage *
-get_fragment_message_from_session(struct Session * session)
+/**
+ * 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,
+              int do_free_macendpoint)
 {
-  struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
-  while (fm != NULL)
+  struct Sessionqueue *pendingsession;
+  struct Sessionqueue *pendingsession_tmp;
+  struct PendingMessage *pm;
+  struct MacEndpoint *endpoint;
+  struct FragmentMessage *fm;
+  struct FragmentMessage *fmnext;
+  int check = 0;
+
+  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 (fm->session == session)
-        {
-          return fm;
-        }
-      fm = fm->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,
+                                   pendingsession_tmp);
+      GNUNET_free (pendingsession_tmp);
+
+      GNUNET_assert (check == 0);
+      check = 1;
     }
-  return NULL;
+  }
+
+  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_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);
 }
 
 /**
@@ -1687,62 +2285,35 @@ get_fragment_message_from_session(struct Session * session)
  * @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 * pendingsession = plugin->pending_Sessions;
-  struct PendingMessage * pm = NULL;
-  struct FragmentMessage * fm;
+  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)
-        {
-          //session found
-          //is this session pending for send
-          while (pendingsession != NULL)
-            {
-              if (pendingsession->content == queue->content)
-                {
-                  plugin->pendingsessions--;
-                  GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-                      plugin->pending_Sessions_tail, pendingsession);
-                  GNUNET_free(pendingsession);
-                  break;
-                }
-              pendingsession = pendingsession->next;
-            }
-
-          //is something of this session in the fragment queue?
-          fm = get_fragment_message_from_session(queue->content);
-          free_fragment_message(plugin, fm);
-
-          //dispose all received fragments
-          free_rec_frag_queue(queue->content);
-
-          // remove PendingMessage
-          pm = queue->content->pending_message;
-          if (pm != NULL)
-            {
-              GNUNET_free_non_null(pm->msg);
-              GNUNET_free(pm);
-            }
-
-          GNUNET_free(queue->content);
-          GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
-          GNUNET_free(queue);
-          plugin->session_count--;
-
-          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;
+  }
 }
 
 /**
@@ -1760,650 +2331,423 @@ 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);
 }
 
+
+
 /**
- * Another peer has suggested an address for this
- * peer and transport plugin.  Check that this could be a valid
- * address.  If so, consider adding it to the list
- * of addresses.
- *
- * @param cls closure
- * @param addr pointer to the address
- * @param addrlen length of addr
- * @return GNUNET_OK if this is a plausible address for this peer
- *         and transport
+ * handels the data after all fragments are put together
+ * @param cls macendpoint this messages belongs to
+ * @param hdr pointer to the data
  */
-
-static int
-wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
+static void
+wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
 {
-  //struct Plugin *plugin = cls;
+  struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
+  struct Plugin *plugin = endpoint->plugin;
+  struct WlanHeader *wlanheader;
+  struct Session *session;
 
-  /* check if the address is plausible; if so,
-   add it to our list! */
+  const struct GNUNET_MessageHeader *temp_hdr;
+  struct GNUNET_PeerIdentity tmpsource;
+  int crc;
 
-  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;
-    }
-  else
+  GNUNET_assert (plugin != NULL);
+
+  if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
+  {
+
+    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));
+
+    if (ntohs (hdr->size) <
+        sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
     {
-      return GNUNET_SYSERR;
+      //packet not big enought
+      return;
     }
 
-  return GNUNET_SYSERR;
-}
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan whole messages received"), 1,
+                              GNUNET_NO);
+    wlanheader = (struct WlanHeader *) hdr;
 
-/**
- * Function called for a quick conversion of the binary address to
- * a numeric address.  Note that the caller must not free the 
- * address and that the next call to this function is allowed
- * to override the address again.
- *
- * @param cls closure
- * @param addr binary address
- * @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 char ret[40];
-  const unsigned char * input;
+    session = search_session (plugin, endpoint, &wlanheader->source);
 
-  //GNUNET_assert(cls !=NULL);
-  if (addrlen != 6)
+    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)
     {
-      /* invalid address (MAC addresses have 6 bytes) */
-      GNUNET_break (0);
-      return NULL;
+      //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;
     }
-  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]);
-  return ret;
-}
-
-/**
- * Function to test if fragment number already exists in the fragments received
- *
- * @param session session the 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
- */
 
-static const int
-is_double_msg(struct Session * session, struct FragmentationHeader * fh)
-{
-  struct RecQueue * rec_queue = session->frag_head;
-  while (rec_queue != NULL)
+    //if not in session list
+    if (session == NULL)
     {
-      if (rec_queue->num == fh->fragment_off_or_num)
+      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)
         {
-          return GNUNET_YES;
-        }
-      rec_queue = rec_queue->next;
+          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;
+          }
 
+        }
+        else
+        {
+          GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                           "WLAN client not in session list and not a hello message\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;
+      }
     }
-  return GNUNET_NO;
-}
 
-/**
- * Function to insert a fragment in a queue of a session
- * @param session session the fragment belongs to
- * @param rec_queue fragment to add
- */
+    //"receive" the message
 
-static void
-insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
-{
-  struct RecQueue * rec_queue2 = session->frag_head;
-  struct WlanHeader * wlanheader = NULL;
-  //first received fragment of message
-  if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
-    {
-      session->rec_size = MESSAGE_LENGHT_UNKNOWN;
-    }
-  //this is the first fragment of the message (fragment id 0)
-  if (rec_queue->num == 0)
+    if (memcmp
+        (&wlanheader->source, &session->target,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
-      wlanheader = (struct WlanHeader *) rec_queue->msg;
-      session->rec_size = ntohs(wlanheader->header.size);
+      //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;
     }
 
-  //sort into list
-  while (rec_queue2 != NULL)
+    if (memcmp
+        (&wlanheader->target, plugin->env->my_identity,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
-      if (rec_queue2->num > rec_queue->num)
-        {
-          //next element number is grater than the current num
-          GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
-          return;
-        }
-      rec_queue = rec_queue->next;
+      //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;
     }
-  //no element has a grater number
-  GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
-}
 
-/**
- * Function to dispose the fragments received for a message
- * @param session session to free the fragments from
- */
+    GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
+                               (const char *) temp_hdr,
+                               ntohs (hdr->size) - sizeof (struct WlanHeader),
+                               GNUNET_YES, GNUNET_NO);
 
-static void
-free_rec_frag_queue(struct Session * session)
-{
-  struct RecQueue * rec_queue = session->frag_head;
-  struct RecQueue * rec_queue2;
-  while (rec_queue != NULL)
-    {
-      rec_queue2 = rec_queue;
-      rec_queue = rec_queue->next;
-      GNUNET_free(rec_queue2);
-    }
-  session->frag_head = NULL;
-  session->frag_tail = NULL;
-  session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
+    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 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
+ * 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
  */
-
+//TODO ATS informations
 static void
-check_rec_finished_msg(struct Plugin* plugin,
-    struct Session_light * session_light, struct Session * session)
+process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
 {
-  struct RecQueue * rec_queue = session->frag_head;
-  int packetsize = session->rec_size;
-  int sum = 0;
-  int aktnum = 0;
-  char * msg;
-  //some fragment should be received
-  GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
-  //check if first fragment is present
-  if (session->rec_size == MESSAGE_LENGHT_UNKNOWN)
-    {
-      return;
-    }
-  while (rec_queue != NULL)
-    {
-      sum += rec_queue->size;
-      //check if all fragment numbers are present
-      if (rec_queue->num != aktnum)
-        {
-          return;
-        }
-      aktnum++;
-      rec_queue = rec_queue->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
-
-      //copy fragments together
-      msg = GNUNET_malloc(packetsize);
-      rec_queue = session->frag_head;
-      aktnum = 0;
-      while (rec_queue != NULL)
-        {
-          //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
-          memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
-          aktnum += rec_queue->size;
-          rec_queue = rec_queue->next;
-        }
-      free_rec_frag_queue(session);
-      //call wlan_process_helper to process the message
-      wlan_data_massage_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\n", session,
-          wlan_plugin_address_to_string(NULL, session->addr, 6));
-#endif
-
-  plugin->env->receive(plugin->env->cls, &(session->target), hdr,
-      (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
-      session, session->addr, sizeof(session->addr));
+  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));
 }
 
 /**
- * handels the data after all fragments are put together
- * @param plugin
- * @param session_light
- * @param hdr pointer to the data
+ * Function used for to process the data received from the wlan interface
+ *
+ * @param cls the plugin handle
+ * @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_massage_handler(struct Plugin * plugin,
-    struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr)
+wlan_data_helper (void *cls, 
+                  const struct GNUNET_MessageHeader *hdr,
+                 const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo)
 {
-  struct WlanHeader * wlanheader = NULL;
-  struct Session * session = NULL;
-  const char * tempmsg = NULL;
-  const struct GNUNET_MessageHeader * temp_hdr = NULL;
-  struct GNUNET_PeerIdentity tmptarget;
+  struct Plugin *plugin = cls;
+  struct FragmentMessage *fm;
+  struct FragmentMessage *fm2;
+  struct GNUNET_PeerIdentity tmpsource;
+  struct MacEndpoint *macendpoint;
+  struct Session *session;
 
-  if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
+  // 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)
     {
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "Func wlan_data_massage_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
-          ntohs(hdr->size));
-#endif
-
-      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))
-        {
-          //wrong crc, dispose message
-          GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-              "Wlan message Header crc was wrong\n");
-          return;
-        }
-
-      //if not in session list
+      session = search_session (plugin, macendpoint, &tmpsource);
       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);
-
-
+      {
+        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));
+    }
+    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;
     }
-  else
+    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)
+    {
+      macendpoint->dups++;
+    }
+    else if (ret == GNUNET_OK)
+    {
+      macendpoint->fragc++;
+    }
+    set_next_send (plugin);
+    break;
+  case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
+    if (NULL == macendpoint)
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-          "wlan_data_massage_handler got wrong message type\n");
+      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 (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");
 }
 
 /**
- * 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 fh pointer to the fragmentation header which we would like to acknolage
+ * 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
  */
-
-void
-add_ack_for_send(struct Plugin * plugin, struct Session * session,
-    struct FragmentationHeader * fh)
+static const char *
+macprinter (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
 {
-  struct AckSendQueue * ack;
-
-  GNUNET_assert(plugin != NULL);
-  GNUNET_assert(session != NULL);
-  GNUNET_assert(fh != NULL);
-
-  ack = GNUNET_malloc(sizeof(struct AckSendQueue));
-  ack->fragment_off_or_num = ntohs(fh->fragment_off_or_num);
-  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);
+  static char macstr[20];
 
+  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 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
+ * 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
-wlan_data_helper(void *cls, struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr)
+macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct Plugin *plugin = cls;
-  struct Session * session = NULL;
-
-  struct FragmentationHeader * fh = NULL;
-  struct FragmentMessage * fm = NULL;
-
-  const char * tempmsg = NULL;
-
-  struct AckQueue * ack = NULL;
-  struct AckQueue * ack2 = NULL;
-
-  struct RecQueue * rec_queue = NULL;
-  //ADVERTISEMENT
-  if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
-    {
-
-      //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, 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);
-
-    }
-
-  //FRAGMENT
-  else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
-    {
-
-      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, 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;
-        }
+  struct MacEndpoint *endpoint = cls;
 
-      //if in the session list
-      if (session != NULL)
-        {
-          //TODO fragments do not timeout
-          //check if message_id is right or it is a new msg
-          if ((session->message_id_in == ntohs(fh->message_id))
-              || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
-            {
-              session->message_id_in = ntohs(fh->message_id);
-              if (is_double_msg(session, fh) != GNUNET_YES)
-                {
-                  //report size
-                  //TODO ask if it is right like this
-                  if (plugin->env->traffic_report != NULL)
-                    {
-                      plugin->env->traffic_report(plugin->env->cls,
-                          &session->target, ntohs(fh->header.size));
-                    }
-                  rec_queue
-                      = GNUNET_malloc(sizeof (struct RecQueue) +
-                          ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
-                  rec_queue->size = ntohs(fh->header.size)
-                      - sizeof(struct FragmentationHeader);
-                  rec_queue->num = ntohs(fh->fragment_off_or_num);
-                  rec_queue->msg = (char*) &rec_queue[1];
-                  //copy msg to buffer
-                  memcpy((char *) rec_queue->msg, tempmsg, rec_queue->size);
-                  insert_fragment_in_queue(session, rec_queue);
-                  check_rec_finished_msg(plugin, session_light, session);
-                }
-              else
-                {
-                  GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-                      "WLAN fragment is a clone\n");
-
-                }
-            }
-          else
-            {
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_INFO,
-                  "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
-
-            }
-        }
-      else
-        {
-          GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-              "WLAN client not in session list\n");
-          wlan_data_massage_handler(plugin, session_light,
-              (struct GNUNET_MessageHeader *) tempmsg);
-          session = session_light->session;
-          //test if a session was created
-          if (session == NULL)
-            {
-              return;
-            }
-        }
-
-      //TODO make and send ack
-      add_ack_for_send(plugin, session, fh);
-      check_next_fragment_timeout(plugin);
-
-    }
-
-  //ACK
-  else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
-    {
-
-#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, 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;
-      fh = (struct FragmentationHeader *) hdr;
-      if (session->message_id_out == ntohl(fh->message_id))
-        {
-          fm = get_fragment_message_from_session(session);
-          if (fm != NULL)
-            {
-
-              ack2 = fm->head;
-              while (ack2 != NULL)
-                {
-                  // check for double
-                  if (ack2->fragment_num != ntohs(fh->fragment_off_or_num))
-                    {
-                      // check if next ack has bigger number
-                      if (ack2->fragment_num > ntohs(fh->fragment_off_or_num))
-                        {
-                          ack = GNUNET_malloc(sizeof(struct AckQueue));
-                          ack->fragment_num = ntohs(fh->fragment_off_or_num);
-                          GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
-                          //check if finished
-                          check_finished_fragment(plugin, fm);
-                          return;
-                        }
-                    }
-                  else
-                    {
-                      //double ack
-#if DEBUG_wlan
-                      GNUNET_log(
-                          GNUNET_ERROR_TYPE_DEBUG,
-                          "WLAN got double ack for message id %u and fragment num %u\n",
-                          session->message_id_out, ack2->fragment_num);
-#endif
-                      return;
-                    }
-                  ack2 = ack2->next;
-                }
-
-              //all acks are have smaller numbers
-              ack = GNUNET_malloc(sizeof(struct AckQueue));
-              ack->fragment_num = ntohs(fh->fragment_off_or_num);
-              GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
-              check_finished_fragment(plugin, fm);
-            }
-          else
-            {
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_WARNING,
-                  "WLAN fragment not in fragment list but id %u of ack is right\n",
-                  ntohl(fh->message_id));
-              return;
-            }
-
-        }
-      else
-        {
-#if DEBUG_wlan
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_DEBUG,
-              _("WLAN got ack but session->message_id_out %u and fragment id %u mismatch\n"),
-              session->message_id_out, ntohl(fh->message_id));
-#endif
-        }
-
-    }
+  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
-    {
-      // TODO Wrong data?
-      GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-          "WLAN packet inside the WLAN helper packet has not the right type\n");
-      return;
-    }
-
-#if 0
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Helper finished\n");
-#endif
+  {
+    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;
 }
 
 /**
@@ -2413,279 +2757,178 @@ wlan_data_helper(void *cls, struct Session_light * session_light,
  * @param client client that send the data (not used)
  * @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 IeeeHeader * wlanIeeeHeader = NULL;
-  struct Session_light * session_light = NULL;
-  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 = 0;
-
-  if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
+  int pos;
+
+  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 GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
     {
-#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
-
-      //call wlan_process_helper with the message inside, later with wlan: analyze signal
-      GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader) + sizeof(struct GNUNET_MessageHeader));
-      wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
-
-      //process only if it is an broadcast or for this computer both with the gnunet bssid
-
-      //check for bssid
-      if (memcmp(&(wlanIeeeHeader->mac2), macbc, sizeof(struct MacAddress))
-          == 0)
-        {
-          //check for broadcast or mac
-          if (memcmp(&(wlanIeeeHeader->mac1), bc_all_mac,
-              sizeof(struct MacAddress) == 0) || memcmp(
-              &(wlanIeeeHeader->mac1), &(plugin->mac_address),
-              sizeof(struct MacAddress)) == 0)
-            {
-
-              // process the inner data
-
-
-              datasize = ntohs(hdr->size) - sizeof(struct IeeeHeader)
-                  - sizeof(struct GNUNET_MessageHeader);
-
-              session_light = GNUNET_malloc(sizeof(struct Session_light));
-              memcpy(session_light->addr, &(wlanIeeeHeader->mac3),
-                  sizeof(struct MacAddress));
-              //session_light->session = search_session(plugin,session_light->addr);
-
-              pos = 0;
-              temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
-              while (pos < datasize)
-                {
-                  temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
-                      + pos;
-
-                  wlan_data_helper(plugin, session_light, temp_hdr);
-                  pos += ntohs(temp_hdr->size);
-
-                }
-
-              //clean up
-              GNUNET_free(session_light);
-            }
-          else
-            {
-#if DEBUG_wlan
-              GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                  "Func wlan_process_helper got wrong MAC: %s\n",
-                  wlanIeeeHeader->mac1);
-#endif
-            }
-        }
-      else
-        {
-#if DEBUG_wlan
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-              "Func wlan_process_helper got wrong BSSID: %s\n",
-              wlanIeeeHeader->mac2);
-#endif
-        }
-
-
-
+      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;
     }
 
-  else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
+    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
+        (&rxinfo->frame.addr3, &mac_bssid_gnunet,
+         sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
     {
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL size: %u\n",
-          ntohs(hdr->size));
-#endif
-
-      //TODO more control messages
-      //TODO use struct wlan_helper_control
-      if (ntohs(hdr->size) == sizeof(struct Wlan_Helper_Control_Message))
+      //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))
+      {
+        //if packet is from us return
+        if ((memcmp
+             (&rxinfo->frame.addr2, &plugin->mac_address,
+              sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0))
         {
-          //plugin->mac_address = GNUNET_malloc(sizeof(struct MacAddress));
-          memcpy(&(plugin->mac_address), &hdr[1], sizeof(struct MacAddress));
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-              "Notifying transport of address %s\n",
-              wlan_plugin_address_to_string(cls, &(plugin->mac_address), ntohs(
-                  hdr->size) - sizeof(struct GNUNET_MessageHeader)));
-          plugin->env->notify_address(plugin->env->cls, "wlan",
-              &plugin->mac_address, sizeof(struct MacAddress),
-              GNUNET_TIME_UNIT_FOREVER_REL);
+         /* not for us */
+          return;
         }
-      else
+        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))
         {
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
-              plugin->mac_address);
+          temp_hdr = (struct GNUNET_MessageHeader *) &end[pos];
+          if (ntohs (temp_hdr->size) <= datasize - pos)
+          {
+            GNUNET_STATISTICS_update (plugin->env->stats,
+                                      _
+                                      ("# wlan messages inside WLAN_HELPER_DATA received"),
+                                      1, GNUNET_NO);
+            wlan_data_helper (plugin, temp_hdr, rxinfo);
+          }
+          else
+          {
+            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
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                         "Func wlan_process_helper got wrong MAC: %s\n",
+                         macprinter (&rxinfo->frame.addr1));
+      }
     }
-
-  else
+    else
     {
-      // TODO Wrong data?
-      GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-          "WLAN helper packet has not the right type\n");
-      return;
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "Func wlan_process_helper got wrong BSSID: %s\n",
+                       macprinter (&rxinfo->frame.addr2));
     }
-}
-
-/**
- * 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)
+    break;
+  case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
+    //TODO more control messages
+    if (ntohs (hdr->size) != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
     {
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          _("Finished reading from wlan-helper stdout with code: %d\n"),
-          bytes);
-#endif
+      GNUNET_break (0);
+      /* FIXME: restart SUID process */
       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);
+    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;
+  }
 }
 
-/**
- * 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
-
-  sleep(2);
 
-  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;
-
-#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);
+    GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
 
-
-  GNUNET_free_non_null(plugin->interface);
+  GNUNET_free_non_null (plugin->interface);
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;
 }
 
+
 /**
  * Entry point for the plugin.
  *
@@ -2693,66 +2936,87 @@ 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;
+  GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
+                                 GNUNET_BANDWIDTH_value_init (100 * 1024 *
+                                                              1024 / 8), 100);
 
-  set_next_beacon_time(plugin);
+  plugin->suid_tokenizer =
+      GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
 
-  if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
-    {
-      if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
-          "transport-wlan", "TESTMODE", &testmode))
-        return NULL;
-    }
-
-  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(plugin);
-          return NULL;
-        }
-    }
-
-  wlan_transport_start_wlan_helper(plugin, testmode);
-  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;
   api->address_to_string = &wlan_plugin_address_to_string;
 
-  start_next_message_id();
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
-#endif
-
+  //read config
+
+  if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
+  {
+    if (GNUNET_SYSERR ==
+        GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
+                                               "TESTMODE", &(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)
+    {
+      libgnunet_plugin_transport_wlan_done (api);
+      return NULL;
+    }
+  }
+
+  //start the 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;
 }
 
+
+
+
 /* end of plugin_transport_wlan.c */