-makefile for new test_stream_local (commented)
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
index b96414a71dfc5e78e697d89871fd5858b16372fa..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
-#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
+/**
+ * time out of a mac endpoint
+ */
+#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
 
-#define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
+/**
+ * scaling factor for hello beacon
+ */
+#define HELLO_BEACON_SCALING_FACTOR 30
 
-#define MESSAGES_IN_QUEUE_SIZE 10
-#define MESSAGES_IN_QUEUE_PER_SESSION 1
+/**
+ * scaling factor for restarting the helper
+ */
+#define HELPER_RESTART_SCALING_FACTOR 2
 
-#define HALLO_BEACON_SCALING_FACTOR 900
+/**
+ * max size of fragment queue
+ */
+#define FRAGMENT_QUEUE_SIZE 10
+/**
+ * max messages in fragment queue per session/client
+ */
+#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
 
-#define DEBUG_wlan GNUNET_YES
+/**
+ * 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.
@@ -97,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;
 
@@ -169,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
@@ -192,148 +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;
 
   /**
-   * Messages in the in Queue, head
+   * time of the next "hello-beacon"
    */
-
-  struct Receive_Message_Queue * receive_messages_head;
+  struct GNUNET_TIME_Absolute beacon_time;
 
   /**
-   * Messages in the in Queue, tail
+   * queue to send acks for received fragments (head)
    */
-
-  struct Receive_Message_Queue * receive_messages_teil;
+  struct AckSendQueue *ack_send_queue_head;
 
   /**
-   * number of messages in the in queue
+   * queue to send acks for received fragments (tail)
    */
-
-  unsigned int pending_receive_messages;
+  struct AckSendQueue *ack_send_queue_tail;
 
   /**
-   * time of the next "hello-beacon"
+   * Tracker for bandwidth limit
    */
-
-  struct GNUNET_TIME_Absolute beacon_time;
+  struct GNUNET_BANDWIDTH_Tracker tracker;
 
   /**
-   * queue to send acks for received fragments (head)
+   * saves the current state of the helper process
    */
+  int helper_is_running;
+};
 
-  struct AckSendQueue * ack_send_queue_head;
+/**
+ * Struct to store data if file write did not accept the whole packet
+ */
+struct Finish_send
+{
+  /**
+   * pointer to the global plugin struct
+   */
+  struct Plugin *plugin;
 
   /**
-   * queue to send acks for received fragments (tail)
+   * head of the next part to send to the helper
    */
+  const char *head_of_next_write;
 
-  struct AckSendQueue * ack_send_queue_tail;
+  /**
+   * Start of the message to send, needed for free
+   */
+  struct GNUNET_MessageHeader *msgstart;
 
+  /**
+   * rest size to send
+   */
+  ssize_t size;
 };
 
 /**
- * Struct to store data if file write did not accept the whole packet
+ * Queue of sessions, for the general session queue and the pending session queue
  */
-struct Finish_send
+//TODO DOXYGEN
+struct Sessionqueue
 {
-  struct Plugin * plugin;
-  char * msgheader;
-  struct GNUNET_MessageHeader * msgstart;
-  ssize_t size;
+  struct Sessionqueue *next;
+  struct Sessionqueue *prev;
+  struct Session *content;
+#if !HAVE_UNALIGNED_64_ACCESS
+  void *dummy;                  /* for alignment, see #1909 */
+#endif
 };
 
+
 /**
- * Queue of sessions, for the general session queue and the pending session queue
+ * Queue of fragmented messages, for the sending queue of the plugin
  */
-
-struct Sessionqueue
+//TODO DOXYGEN
+struct FragmentMessage_queue
 {
-  struct Sessionqueue * next;
-  struct Sessionqueue * prev;
-  struct Session * content;
+  struct FragmentMessage_queue *next;
+  struct FragmentMessage_queue *prev;
+  struct FragmentMessage *content;
 };
 
+
 /**
  * Queue for the fragments received
  */
-
+//TODO DOXYGEN
 struct Receive_Fragment_Queue
 {
-  struct Receive_Fragment_Queue * next;
-  struct Receive_Fragment_Queue * prev;
+  struct Receive_Fragment_Queue *next;
+  struct Receive_Fragment_Queue *prev;
+
   uint16_t num;
-  const char * msg;
-  uint16_t size;
+  // const char *msg;
+  //   uint16_t size;
+  struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rx_msg;
 };
 
-/**
- * Queue for the fragments received
- */
 
-struct Receive_Message_Queue
+//TODO DOXYGEN
+struct MacEndpoint_id_fragment_triple
 {
-  struct Receive_Message_Queue * next;
+  struct MacEndpoint *endpoint;
+  uint32_t message_id;
+  struct FragmentMessage *fm;
+};
 
-  struct Receive_Message_Queue * prev;
+//TODO DOXYGEN
+struct Plugin_Session_pair
+{
+  struct Plugin *plugin;
+  struct Session *session;
+};
 
-  /**
-   * current number for message incoming, to distinguish between the messages
-   */
-  uint32_t message_id_in;
 
-  /**
-   * size of the message received,
-   * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
-   * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
-   */
+GNUNET_NETWORK_STRUCT_BEGIN
 
-  int rec_size;
+/**
+ * Header for messages which need fragmentation
+ */
+struct WlanHeader
+{
 
   /**
-   * Sorted queue with the fragments received; head
+   * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA.
    */
-
-  struct Receive_Fragment_Queue * frag_head;
+  struct GNUNET_MessageHeader header;
 
   /**
-   * Sorted queue with the fragments received; tail
+   * checksum/error correction
    */
-
-  struct Receive_Fragment_Queue * frag_tail;
+  uint32_t crc GNUNET_PACKED;
 
   /**
-   * Session this fragment belongs to
+   * To whom are we talking to (set to our identity
+   * if we are still waiting for the welcome message)
    */
-
-  struct Session * session;
+  struct GNUNET_PeerIdentity target;
 
   /**
-   * Timeout value for the pending message.
+   *  Where the packet came from
    */
-  struct GNUNET_TIME_Absolute timeout;
+  struct GNUNET_PeerIdentity source;
 
-  /**
-   * Bitfield of received fragments
-   */
+// followed by payload
 
-  uint64_t received_fragments;
 };
+GNUNET_NETWORK_STRUCT_END
 
 /**
  * Information kept for each message that is yet to
@@ -341,11 +381,20 @@ struct Receive_Message_Queue
  */
 struct PendingMessage
 {
+  /**
+   * dll next
+   */
+  struct PendingMessage *next;
+
+  /**
+   * dll prev
+   */
+  struct PendingMessage *prev;
 
   /**
    * The pending message
    */
-  char *msg;
+  struct WlanHeader *msg;
 
   /**
    * Size of the message
@@ -362,7 +411,7 @@ struct PendingMessage
   /**
    * Cls for transmit_cont
    */
-  void * transmit_cont_cls;
+  void *transmit_cont_cls;
 
   /**
    * Timeout value for the pending message.
@@ -371,45 +420,40 @@ struct PendingMessage
 
 };
 
+
 /**
  * Queue for acks to send for fragments recived
  */
-//TODO comments
 struct AckSendQueue
 {
 
-  struct AckSendQueue * next;
-  struct AckSendQueue * prev;
-
-  struct Session * session;
   /**
-   * ID of message, to distinguish between the messages, picked randomly.
+   * next ack in the ack send queue
    */
-  uint32_t message_id;
+  struct AckSendQueue *next;
 
   /**
-   * Bit field for received fragments
+   * previous ack in the ack send queue
    */
-  uint64_t fragments_field;
-
-};
+  struct AckSendQueue *prev;
 
-/**
- * Session infos gathered from a messages
- */
+  /**
+   * pointer to the session this ack belongs to
+   */
+  struct MacEndpoint *endpoint;
 
-struct Session_light
-{
   /**
-   * the session this message belongs to
+   * ID of message, to distinguish between the messages, picked randomly.
    */
-  struct Session * session;
+  uint32_t message_id;
+
   /**
-   * peer mac address
+   * pointer to the radiotap header with the ACK Message.
    */
-  uint8_t addr[6];
+  const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
 };
 
+
 /**
  * Session handle for connections.
  */
@@ -421,22 +465,17 @@ struct Session
    */
   struct SessionHeader header;
 
-  /**
-   * Pointer to the global plugin struct.
-   */
-  struct Plugin *plugin;
-
   /**
    * Message currently pending for transmission
-   * to this peer, if any.
+   * to this peer, if any. head
    */
-  struct PendingMessage *pending_message;
+  struct PendingMessage *pending_message_head;
 
   /**
    * Message currently pending for transmission
-   * to this peer, if any.
+   * to this peer, if any. tail
    */
-  struct PendingMessage *pending_message2;
+  struct PendingMessage *pending_message_tail;
 
   /**
    * To whom are we talking to (set to our identity
@@ -444,11 +483,6 @@ struct Session
    */
   struct GNUNET_PeerIdentity target;
 
-  /**
-   * peer mac address
-   */
-  char addr[6];
-
   /**
    * Address of the other peer (either based on our 'connect'
    * call or on our 'accept' call).
@@ -457,646 +491,674 @@ struct Session
 
   /**
    * Last activity on this connection.  Used to select preferred
-   * connection.
+   * connection and timeout
    */
   struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   * count of messages in the fragment out queue for this session
+   * Timeout task.
    */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
-  int fragment_messages_out_count;
+  /**
+   * peer connection
+   */
+  struct MacEndpoint *mac;
 
   /**
-   * count of messages in the fragment in queue for this session
+   * count of messages in the fragment out queue for this session
    */
 
-  int fragment_messages_in_count;
+  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;
 
   /**
-   * bitfield with all acks received for this message
+   * dll prev
    */
-  uint64_t ack_bitfield;
+  struct MacEndpoint *prev;
 
   /**
-   * Size of the message
+   * peer mac address
    */
-  size_t message_size;
+  struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
 
   /**
-   * pos / next fragment number in the message, for fragmentation/segmentation,
-   * some acks can be missing but there is still time
+   * Defrag context for this mac endpoint
    */
-  uint32_t message_pos;
+  struct GNUNET_DEFRAGMENT_Context *defrag;
 
   /**
-   * current number for message outgoing, to distinguish between the messages
+   * count of messages in the fragment out queue for this mac endpoint
    */
-  uint32_t message_id_out;
-};
+  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;
-
   /**
-   * ID of message, to distinguish between the messages, picked randomly.
+   * Session this message belongs to
    */
-  uint32_t message_id GNUNET_PACKED;
+  struct Session *session;
 
   /**
-   * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
+   * This is a doubly-linked list.
    */
-  uint16_t fragment_off_or_num GNUNET_PACKED;
+  struct FragmentMessage *next;
 
   /**
-   * CRC of fragment (for error checking)
+   * This is a doubly-linked list.
    */
-  uint16_t message_crc GNUNET_PACKED;
-
-// followed by payload
-
-};
-
-/**
- * Header for messages which need fragmentation
- */
-struct FragmentationAckHeader
-{
+  struct FragmentMessage *prev;
 
-  struct GNUNET_MessageHeader header;
+  /**
+   * Fragmentation context
+   */
+  struct GNUNET_FRAGMENT_Context *fragcontext;
 
   /**
-   * ID of message, to distinguish between the messages, picked randomly.
+   * Timeout value for the message.
    */
-  uint32_t message_id GNUNET_PACKED;
+  struct GNUNET_TIME_Absolute timeout;
 
   /**
-   * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
+   * Timeout task.
    */
-  uint64_t fragment_field GNUNET_PACKED;
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
+  /**
+   * pointer to the radiotap header
+   */
+  struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
 };
 
-int
-getRadiotapHeader(struct RadiotapHeader * Header);
-
-int
-getWlanHeader(struct IeeeHeader * Header, const char * to_mac_addr,
-    struct Plugin * plugin);
 
-static int
-wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
+static void
+do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
-uint16_t
-getcrc16(const char *msgbuf, size_t msgbuf_size);
 
 static void
-do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+free_session (struct Plugin *plugin, struct Sessionqueue *queue,
+              int do_free_macendpoint);
 
-static void
-check_fragment_queue(struct Plugin * plugin);
 
-uint32_t
-getcrc32(const char *msgbuf, size_t msgbuf_size);
+static struct MacEndpoint *
+create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr);
+
 
 static void
-free_receive_message(struct Plugin* plugin,
-    struct Receive_Message_Queue * rec_message);
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
-struct Receive_Message_Queue *
-get_receive_message_from_session(struct Plugin * plugin,
-    struct Session * session);
 
+/**
+ * Generates a nice hexdump of a memory area.
+ *
+ * \param  mem     pointer to memory to dump
+ * \param  length  how many bytes to dump
+ */
 static void
-wlan_data_helper(void *cls, struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr);
+hexdump (const void *mem, unsigned length)
+{
+  char line[80];
+  char *src = (char *) mem;
 
-static void
-wlan_process_helper(void *cls, void *client,
-    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
-finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+  for (i = 0; i < length; i += 16, src += 16)
+  {
+    char *t = line;
 
-static void
-wlan_data_massage_handler(struct Plugin * plugin,
-    struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr);
+    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 const char *
-wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen);
+      t += sprintf (t, (j % 2) ? " " : "-");
+    }
 
-struct Receive_Message_Queue *
-get_receive_message(struct Plugin * plugin, struct Session * session,
-    uint32_t message_id);
+    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, " ");
+      }
+    }
 
-static uint64_t
-htonll(uint64_t input)
-{
-  return input;
+    t += sprintf (t, "\r\n");
+    printf ("%s", line);
+  }
 }
 
-static uint64_t
-ntohll(uint64_t input)
-{
-  return input;
-}
 
 /**
- * Sets a bit active in the bitArray. Increment bit-specific
- * usage counter on disk only if below 4bit max (==15).
- *
- * @param bitArray memory area to set the bit in
- * @param bitIdx which bit to set
+ * Function to find a MacEndpoint with a specific mac addr
+ * @param plugin pointer to the plugin struct
+ * @param addr pointer to the mac address
+ * @param create_new GNUNET_YES if a new end point should be created
+ * @return
  */
-static void
-setBit(char *bitArray, unsigned int bitIdx)
+static struct MacEndpoint *
+get_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
+                 int create_new)
 {
-  size_t arraySlot;
-  unsigned int targetBit;
+  struct MacEndpoint *queue = plugin->mac_head;
 
-  arraySlot = bitIdx / 8;
-  targetBit = (1L << (bitIdx % 8));
-  bitArray[arraySlot] |= targetBit;
+  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;
+  }
 }
 
+
 /**
- * Clears a bit from bitArray. Bit is cleared from the array
- * only if the respective usage counter on the disk hits/is zero.
+ * search for a session with the macendpoint and peer id
  *
- * @param bitArray memory area to set the bit in
- * @param bitIdx which bit to unset
+ * @param plugin pointer to the plugin struct
+ * @param endpoint pointer to the mac endpoint of the peer
+ * @param peer pointer to the peerid
+ * @return returns the session
  */
-/*static void
-clearBit(char *bitArray, unsigned int bitIdx)
+static struct Session *
+search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
+                const struct GNUNET_PeerIdentity *peer)
 {
-  size_t slot;
-  unsigned int targetBit;
+  GNUNET_assert (endpoint != NULL);
+  struct Sessionqueue *queue = endpoint->sessions_head;
 
-  slot = bitIdx / 8;
-  targetBit = (1L << (bitIdx % 8));
-  bitArray[slot] = bitArray[slot] & (~targetBit);
-}*/
-
-/**
- * Checks if a bit is active in the bitArray
- *
- * @param bitArray memory area to set the bit in
- * @param bitIdx which bit to test
- * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
- */
-static int
-testBit(char *bitArray, unsigned int bitIdx)
-{
-  size_t slot;
-  unsigned int targetBit;
-
-  slot = bitIdx / 8;
-  targetBit = (1L << (bitIdx % 8));
-  if (bitArray[slot] & targetBit)
-    return GNUNET_YES;
-  else
-    return GNUNET_NO;
+  while (queue != NULL)
+  {
+    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;
 }
 
 /**
- * get the next message number, at the moment just a random one
- * @return returns the next valid message-number for sending packets
+ * 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
  */
-uint32_t
-get_next_message_id()
+static const char *
+wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
 {
-  return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
-}
+  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]);
 
-/**
- * start next message number generator
- * (not necessary at the moment)
- */
-void
-start_next_message_id()
-{
-  //GNUNET_CRYPTO_random_init;
+  return ret;
 }
 
 /**
- * search for a session with the addr
- *
- * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac address of the peer
- * @return returns the session
+ * Function for the scheduler if a session times out
+ * @param cls pointer to the Sessionqueue
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
  */
-
-static struct Session *
-search_session(struct Plugin *plugin, const uint8_t * addr)
+static void
+session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct Sessionqueue * queue = plugin->sessions;
-  struct Sessionqueue * lastitem = NULL;
+  struct Sessionqueue *queue = cls;
 
-  //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;
-    }
-  return NULL;
+  GNUNET_assert (queue != NULL);
+  GNUNET_assert (queue->content != NULL);
+  queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  {
+    return;
+  }
+  if (GNUNET_TIME_absolute_get_remaining
+      (GNUNET_TIME_absolute_add
+       (queue->content->last_activity, SESSION_TIMEOUT)).rel_value == 0)
+  {
+
+    GNUNET_assert (queue->content->mac != NULL);
+    GNUNET_assert (queue->content->mac->plugin != NULL);
+    GNUNET_STATISTICS_update (queue->content->mac->plugin->env->stats,
+                              _("# wlan session timeouts"), 1, GNUNET_NO);
+    free_session (queue->content->mac->plugin, queue, GNUNET_YES);
+  }
+  else
+  {
+    queue->content->timeout_task =
+        GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
+  }
 }
 
 /**
  * create a new session
  *
  * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac address of the peer
+ * @param endpoint pointer to the mac endpoint of the peer
+ * @param peer peer identity to use for this session
  * @return returns the session
  */
-
 static struct Session *
-create_session(struct Plugin *plugin, const uint8_t * addr)
-{
-  struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
-
-  GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
-
-  queue->content = GNUNET_malloc (sizeof (struct Session));
-  queue->content->plugin = plugin;
-  memcpy(queue->content->addr, addr, 6);
-  queue->content->fragment_messages_out_count = 0;
-  queue->content->fragment_messages_in_count = 0;
-
-  plugin->session_count++;
-
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
-      queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
-#endif
-
+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
+    // Session is not in the queue
 
-  queue = GNUNET_malloc (sizeof (struct Sessionqueue));
-  queue->content = session;
+    queue = GNUNET_malloc (sizeof (struct Sessionqueue));
+    queue->content = session;
 
-  //insert at the tail
-  GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
-      plugin->pending_Sessions_tail,
-      plugin->pending_Sessions_tail, queue);
-  plugin->pendingsessions++;
+    //insert at the tail
+    GNUNET_CONTAINER_DLL_insert_tail (plugin->pending_Sessions_head,
+                                      plugin->pending_Sessions_tail, queue);
+    plugin->pendingsessions++;
+    GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
+                           plugin->pendingsessions, GNUNET_NO);
+  }
 
 }
 
-//TODO doxigen
 /**
  * Function to schedule the write task, executed after a delay
+ * @param cls pointer to the plugin struct
+ * @param tc GNUNET_SCHEDULER_TaskContext pointer
  */
 static void
-delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct Plugin * plugin = cls;
+  struct Plugin *plugin = cls;
+
   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
 
   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
   if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
-    {
-      plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
-          GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
-          &do_transmit, plugin);
-    }
+  {
+    plugin->server_write_task =
+        GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                         plugin->server_stdin_handle,
+                                         &do_transmit, plugin);
+  }
 }
 
-//TODO doxigen
 /**
  * Function to calculate the time of the next periodic "hello-beacon"
+ * @param plugin pointer to the plugin struct
  */
 static void
-set_next_beacon_time(struct Plugin * const plugin)
+set_next_beacon_time (struct Plugin *const plugin)
 {
   //under 10 known peers: once a second
-  if (plugin->session_count < 10)
-    {
-      plugin->beacon_time = GNUNET_TIME_absolute_add(
-          GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
-              GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
-    }
+  if (plugin->mac_count < 10)
+  {
+    plugin->beacon_time =
+        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS,
+                                   HELLO_BEACON_SCALING_FACTOR));
+  }
   //under 30 known peers: every 10 seconds
-  else if (plugin->session_count < 30)
-    {
-      plugin->beacon_time = GNUNET_TIME_absolute_add(
-          GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
-              GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
-    }
+  else if (plugin->mac_count < 30)
+  {
+    plugin->beacon_time =
+        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS,
+                                   10 * HELLO_BEACON_SCALING_FACTOR));
+  }
   //over 30 known peers: once a minute
   else
-    {
-      plugin->beacon_time = GNUNET_TIME_absolute_add(
-          GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
-              GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
-    }
+  {
+    plugin->beacon_time =
+        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MINUTES,
+                                   HELLO_BEACON_SCALING_FACTOR));
+  }
 }
 
-//TODO doxigen
-struct GNUNET_TIME_Relative
-get_next_frag_timeout(struct FragmentMessage * fm)
-{
-  return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
-      fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
-}
-
-//TODO doxigen
-/**
- * Function to get the timeout value for acks for this session
- */
-
-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;
-      if (pm == NULL){
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-          "pending message is empty, should not happen. session %p\n", session);
-#endif
-      }
-      GNUNET_assert(pm != NULL);
-
-      //check for message timeout
-      if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
-        {
-          //check if session has no message in the fragment queue
-          if (session->fragment_messages_out_count
-              < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
-            {
-              plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-                  plugin->pending_Sessions_tail, sessionqueue);
-              GNUNET_free(sessionqueue);
-
-              return session;
-            }
-          else
-            {
-              sessionqueue = sessionqueue->next;
-            }
-        }
-      else
-        {
-
-          session->pending_message = session->pending_message2;
-          session->pending_message2 = NULL;
+  struct Session *session;
+  struct Sessionqueue *sessionqueue;
+  struct Sessionqueue *sessionqueue_alt;
+  struct PendingMessage *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);
+  sessionqueue = plugin->pending_Sessions_head;
 
-          if (session->pending_message == NULL)
-            {
-              sessionqueue_alt = sessionqueue;
-              sessionqueue = sessionqueue->next;
-              plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-                  plugin->pending_Sessions_tail, sessionqueue_alt);
+  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;
 }
 
 /**
@@ -1105,732 +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)
-{
-  if (fm != NULL)
+free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
+{
+  struct Session *session = fm->session;
+  struct MacEndpoint *endpoint = session->mac;
+  struct FragmentMessage_queue *fmq;
+  struct FragmentMessage_queue *fmq_next;
+
+  fmq = plugin->sending_messages_head;
+  while (fmq != NULL)
+  {
+    fmq_next = fmq->next;
+    if (fmq->content == fm)
     {
-      (fm->session->fragment_messages_out_count)--;
-      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--;
-
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "free pending fragment messages, pending messages remaining %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 int
+getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
+                   struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
+                  uint16_t size)
+{
+  header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
+  header->header.size = ntohs (size);
+  if (endpoint != NULL)
+  {
+    header->rate = endpoint->rate;
+    header->tx_power = endpoint->tx_power;
+    header->antenna = endpoint->antenna;
+  }
+  else
+  {
+    header->rate = 255;
+    header->tx_power = 0;
+    header->antenna = 0;
+  }
 
-static void
-check_fragment_queue(struct Plugin * plugin)
-{
-  struct Session * session;
-  struct FragmentMessage * fm;
-  struct GNUNET_PeerIdentity pid;
-
-  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->fragment_messages_out_count++;
-          GNUNET_assert(pm != NULL);
-
-          fm = GNUNET_malloc(sizeof(struct FragmentMessage));
-          fm->message_size = pm->message_size;
-          fm->msg = pm->msg;
-          fm->session = session;
-          fm->timeout.abs_value = pm->timeout.abs_value;
-          fm->message_pos = 0;
-          fm->next_ack = GNUNET_TIME_absolute_get();
-          fm->message_id_out = get_next_message_id();
-          fm->ack_bitfield = 0;
-
-          sort_fragment_into_queue(plugin, fm);
-          plugin->pending_fragment_messages++;
-
-          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);
-
-          if (session->pending_message2 != NULL){
-            session->pending_message = session->pending_message2;
-            session->pending_message2 = NULL;
-            //requeue session
-            queue_Session(plugin, session);
-          }
 
-          //check if timeout changed
-          check_next_fragment_timeout(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
+ * @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;
 }
 
+
 /**
- * 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
+ * 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
-check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
+add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
 {
-  //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
-  unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
-      - sizeof(struct FragmentationHeader)));
-  uint64_t tmpfield = 0xFFFFFFFFFFFFFFFF;
-  tmpfield = tmpfield >> maxack;
-
-  //#if DEBUG_wlan
-  if (maxack != 63)
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-        "Test bitfields %X and %X, maxack is %u, fm size %u\n",
-        fm->ack_bitfield, tmpfield, maxack, fm->message_size);
-  //#endif
-
-  if (fm->ack_bitfield == tmpfield)
-    {
-
-      free_fragment_message(plugin, fm);
-
-#if DEBUG_wlan
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-          "Finished sending and got all acks for a fragmented message\n");
-#endif
-
-      check_next_fragment_timeout(plugin);
-      check_fragment_queue(plugin);
+  struct FragmentMessage *fm = cls;
+  struct FragmentMessage_queue *fmqueue;
+  struct MacEndpoint *endpoint;
+  struct Plugin *plugin;
+  uint16_t size;
 
-    }
+  GNUNET_assert (cls != NULL);
+  endpoint = fm->session->mac;
+  plugin = endpoint->plugin;
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
+                   fm, fm->session, endpoint, hdr->type);
+  size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + ntohs (hdr->size);
+  fm->radioHeader = GNUNET_malloc (size);
+  getRadiotapHeader (plugin, fm->session->mac, fm->radioHeader, size);
+  getWlanHeader (&fm->radioHeader->frame, &(fm->session->mac->addr), plugin,
+                size);
+  memcpy (&fm->radioHeader[1], hdr, ntohs (hdr->size));
+  // FIXME: yucky allocation structure!
+  fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue));
+  fmqueue->content = fm;
+  GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head,
+                                    plugin->sending_messages_tail, fmqueue);
+  set_next_send (plugin);
 }
 
+
 /**
- * Function to set the next fragment number
- * @param fm use this FragmentMessage
+ * 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
  */
-
-void
-set_next_message_fragment_pos(struct FragmentMessage * fm)
+static void
+wlan_plugin_helper_read (void *cls,
+                         const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct Plugin *plugin = cls;
 
-  //check if retransmit is needed
-  if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
-    {
-
-      // be positive and try again later :-D
-      fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
-      // find first missing fragment
+  plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
 
-      fm->message_pos = 0;
-    }
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
 
-  //test if ack 0 (or X) was already received
-  while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
-    {
-      fm->message_pos++;
-    }
+  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);
 }
 
-void
-send_hello_beacon(struct Plugin * plugin)
+/**
+ * Start 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_start_wlan_helper (struct Plugin *plugin)
 {
+  const char *filenamehw = "gnunet-helper-transport-wlan";
+  const char *filenameloopback = "gnunet-helper-transport-wlan-dummy";
+  char *absolute_filename = NULL;
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
-#endif
+  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;
+  }
 
-  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;
+  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;
 
-  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));
+  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];
 
-  msgheader = GNUNET_malloc(size);
-  msgheader->size = htons(size);
-  msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+      GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
 
-  radioHeader = (struct RadiotapHeader*) &msgheader[1];
-  getRadiotapHeader(radioHeader);
-  ieeewlanheader = (struct IeeeHeader*) &radioHeader[1];
-  getWlanHeader(ieeewlanheader, bc_all_mac, plugin);
+      GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
+                       filenameloopback);
 
-  msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
-  msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
-      + sizeof(struct GNUNET_MessageHeader));
+      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);
+      }
+    }
+  }
 
-  msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
-  memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
-      *(plugin->env->our_hello)));
+  /* Start the server process */
 
-  bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
+  if (plugin->testmode == 0)
+  {
 
-  if (bytes == GNUNET_SYSERR)
+    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)
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-          _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
-          errno, strerror(errno));
-
+      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);
     }
-  GNUNET_assert(bytes != GNUNET_SYSERR);
-  GNUNET_assert(bytes == size);
-  GNUNET_free(msgheader);
-
-  set_next_beacon_time(plugin);
-  check_next_fragment_timeout(plugin);
-}
 
-static void
-send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
-{
+  }
+  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;
+  }
 
-  uint16_t size = 0;
-  ssize_t bytes;
-  struct GNUNET_MessageHeader * msgheader = NULL;
-  struct IeeeHeader * ieeewlanheader = NULL;
-  struct RadiotapHeader * radioHeader = NULL;
-  struct FragmentationAckHeader * msgheader2 = NULL;
 
-  GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "Sending ack for message_id %u with fragment field %u\n",
-      ack->message_id, ack->fragments_field);
-#endif
+  /* Close the write end of the read pipe */
+  GNUNET_DISK_pipe_close_end (plugin->server_stdout,
+                              GNUNET_DISK_PIPE_END_WRITE);
 
-  size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct RadiotapHeader)
-      + sizeof(struct IeeeHeader) + sizeof(struct FragmentationAckHeader);
-  msgheader = GNUNET_malloc(size);
-  msgheader->size = htons(size);
-  msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+  /* Close the read end of the write pipe */
+  GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
 
-  radioHeader = (struct RadiotapHeader*) &msgheader[1];
-  getRadiotapHeader(radioHeader);
-  ieeewlanheader = (struct IeeeHeader*) &radioHeader[1];
-  getWlanHeader(ieeewlanheader, ack->session->addr, plugin);
+  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);
 
-  msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
-  msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
-  msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
-  msgheader2->message_id = htonl(ack->message_id);
-  msgheader2->fragment_field = htonll(ack->fragments_field);
+  GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
 
-  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_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);
 
-    }
-  GNUNET_assert(bytes != GNUNET_SYSERR);
-  GNUNET_assert(bytes == size);
-  GNUNET_free(msgheader);
-  check_next_fragment_timeout(plugin);
+  plugin->helper_is_running = GNUNET_YES;
+  return GNUNET_YES;
 }
 
 /**
- * Function called when wlan helper is ready to get some data
+ * Stops the gnunet-helper-transport-wlan process.
  *
- * @param cls closure
- * @param tc GNUNET_SCHEDULER_TaskContext
+ * @param plugin the transport plugin
+ * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
  */
-
-static void
-do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+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");
 
-  struct Plugin * plugin = cls;
-  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  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;
+  }
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
-    return;
+  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;
 
-  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;
+  return GNUNET_YES;
+}
 
-  if (plugin->ack_send_queue_head != NULL)
-    {
-      ack = plugin->ack_send_queue_head;
-      GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
-          plugin->ack_send_queue_tail, ack);
-      send_ack(plugin, ack);
-      GNUNET_free(ack);
-      return;
-    }
-
-  //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);
+/**
+ * function for delayed restart of the helper process
+ * @param cls Finish_send struct if message should be finished
+ * @param tc TaskContext
+ */
+static void
+delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
 
-      return;
+  plugin = finish->plugin;
 
-    }
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+  {
+    GNUNET_free_non_null (finish->msgstart);
+    GNUNET_free (finish);
+    return;
+  }
 
-  fm = plugin->pending_Fragment_Messages_head;
-  if (fm != NULL)
-    {
-      session = fm->session;
-      GNUNET_assert(session != NULL);
+  wlan_transport_start_wlan_helper (plugin);
 
-      // 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
+  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);
+  }
 
-          check_fragment_queue(plugin);
-          free_fragment_message(plugin, fm);
+}
 
-        }
-      else
-        {
+/**
+ * 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);
 
-          //if (fm->message_size > WLAN_MTU)
-          // {
-          size += sizeof(struct FragmentationHeader);
+  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);
 
-          set_next_message_fragment_pos(fm);
+}
 
-          copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
-              * fm->message_pos;
+/**
+ * function to finish a sending if not all could have been writen befor
+ * @param cls pointer to the Finish_send struct
+ * @param tc TaskContext
+ */
+static void
+finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct Finish_send *finish = cls;
+  struct Plugin *plugin;
+  ssize_t bytes;
 
-#if DEBUG_wlan
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_DEBUG,
-              "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
-              fm->message_id_out, fm->message_pos, copysize
-                  + sizeof(struct FragmentationHeader), copyoffset,
-              GNUNET_TIME_absolute_get_remaining(fm->timeout));
-#endif
+  plugin = finish->plugin;
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
 
-          fragheader.fragment_off_or_num = htons(fm->message_pos);
-          fragheader.message_id = htonl(fm->message_id_out);
-          copystart = fm->msg + copyoffset;
-          copysize = GNUNET_MIN(fm->message_size - copyoffset,
-              WLAN_MTU - sizeof(struct FragmentationHeader));
-
-          if (copyoffset >= fm->message_size)
-            {
-              GNUNET_log(
-                  GNUNET_ERROR_TYPE_ERROR,
-                  "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
-                  copyoffset, fm->message_size, WLAN_MTU
-                      - sizeof(struct FragmentationHeader), copysize,
-                  fm->message_pos);
-            }
-          GNUNET_assert(copyoffset < fm->message_size);
-          //FIXME remove later
-          GNUNET_assert(copystart < fm->msg + fm->message_size);
-
-          fragheader.header.size = htons(copysize
-              + sizeof(struct FragmentationHeader));
-          fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
-
-          /* }
-           else
-           {
-           // there is no need to split
-           copystart = fm->msg;
-           copysize = fm->message_size;
-           }*/
-
-          size += copysize;
-          size += sizeof(struct 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);
+  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);
 
-              GNUNET_free(msgheader);
-              check_next_fragment_timeout(plugin);
-            }
+  if (bytes != finish->size)
+  {
+    if (bytes != GNUNET_SYSERR)
+    {
+      finish->head_of_next_write += bytes;
+      finish->size -= bytes;
+      plugin->server_write_task =
+          GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                           plugin->server_stdin_handle,
+                                           &finish_sending, finish);
+    }
+    else
+    {
+      restart_helper (plugin, finish);
+    }
+  }
+  else
+  {
+    GNUNET_free (finish->msgstart);
+    GNUNET_free (finish);
+    set_next_send (plugin);
+  }
+}
 
-          //check if this was the last fragment of this message, if true then queue at the end of the list
-          if (copysize + copyoffset >= fm->message_size)
-            {
-              GNUNET_assert(copysize + copyoffset == fm->message_size);
 
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
-                  plugin->pending_Fragment_Messages_tail, fm);
+/**
+ * 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_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 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;
 
-        }
-      return;
-    }
-  GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-      "do_transmit did nothing, should not happen!\n");
+  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);
 }
 
+
+/**
+ * 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
-finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+fragmentmessage_timeout (void *cls,
+                         const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct Finish_send * finish;
-  struct Plugin * plugin;
-  ssize_t bytes;
+  struct FragmentMessage *fm = cls;
 
-  finish = cls;
-  plugin = finish->plugin;
+  GNUNET_assert (fm != NULL);
+  fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))  
+    return;  
+  free_fragment_message (fm->session->mac->plugin, fm);
+}
 
-  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+/**
+ * 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
+check_fragment_queue (struct Plugin *plugin)
+{
+  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->mac3, mac_bssid, sizeof(mac_bssid));
-  memcpy(&Header->mac2, 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
- *
- * @param msgbuf pointer tor the data
- * @param msgbuf_size size of the data
+ * Creates a new outbound session the transport service will use to send data to the
+ * peer
  *
- * @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;
-
-  //check if msglen > 0
-  GNUNET_assert(msgbuf_size > 0);
-
-  //get session if needed
-  if (session == NULL)
-    {
-      if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
-        {
-          session = get_Session(plugin, addr);
-        }
-      else
-        {
-          GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-              _("Wlan Address len %d is wrong\n"), addrlen);
-          return -1;
-        }
-    }
-
-  //TODO target "problem" not solved
-  //if (session->target != NULL){
-  //  GNUNET_assert(session->target == *target);
-  //} else {
-    session->target = *target;
-  //}
+  struct Plugin *plugin = cls;
+  struct PendingMessage *newmsg;
+  struct WlanHeader *wlanheader;
 
+  GNUNET_assert (plugin != NULL);
+  GNUNET_assert (session != NULL);
+  GNUNET_assert (msgbuf_size > 0);
 
   //queue message:
 
   //queue message in session
   //test if there is no other message in the "queue"
   //FIXME: to many send requests
-  //GNUNET_assert (session->pending_message == NULL);
-  if (session->pending_message != NULL)
-    {
-      newmsg = session->pending_message;
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_ERROR,
-          "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages %u\n",
-          GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
-          session->fragment_messages_out_count);
-      if (session->pending_message2 != NULL)
-        {
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_ERROR,
-              "wlan_plugin_send: two pending messages are already in the queue for this client\n");
-          return -1;
-        }
-    }
-
-  newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
-  (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
-  wlanheader = (struct WlanHeader *) newmsg->msg;
+  if (session->pending_message_head != NULL)
+  {
+    newmsg = session->pending_message_head;
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                     "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages for this mac connection %u\n",
+                     GNUNET_TIME_absolute_get_remaining (newmsg->
+                                                         timeout).rel_value,
+                     session->mac->fragment_messages_out_count);
+  }
+
+  newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
+  newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
+  wlanheader = newmsg->msg;
   //copy msg to buffer, not fragmented / segmented yet, but with message header
-  wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
-  wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
-  memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
-  wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
-  memcpy(&wlanheader[1], msgbuf, msgbuf_size);
+  wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
+  wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
+  memcpy (&(wlanheader->target), &session->target, sizeof (struct GNUNET_PeerIdentity));
+  memcpy (&(wlanheader->source), plugin->env->my_identity,
+          sizeof (struct GNUNET_PeerIdentity));
+  wlanheader->crc = 0;
+  memcpy (&wlanheader[1], msgbuf, msgbuf_size);
+  wlanheader->crc =
+      htonl (GNUNET_CRYPTO_crc32_n
+             ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
+
   newmsg->transmit_cont = cont;
   newmsg->transmit_cont_cls = cont_cls;
-  newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
+  newmsg->timeout = GNUNET_TIME_relative_to_absolute (to);
 
   newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
 
-  newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
+  newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
 
-  if (session->pending_message == NULL)
-    {
-      session->pending_message = newmsg;
-    }
-  else
-    {
-      session->pending_message2 = newmsg;
-    }
+  GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
+                                    session->pending_message_tail, newmsg);
 
-#if DEBUG_wlan
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "New message for %p with size (incl wlan header) %u added\n", session,
-      newmsg->message_size);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "New message for %p with size (incl wlan header) %u added\n",
+                   session, newmsg->message_size);
+#if DEBUG_WLAN > 1
+  hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
 #endif
-
-
   //queue session
-  queue_Session(plugin, session);
+  queue_session (plugin, session);
 
-  check_fragment_queue(plugin);
+  check_fragment_queue (plugin);
   //FIXME not the correct size
   return msgbuf_size;
-
 }
 
+
 /**
- * function to get the first message in the fragement queue (out) of a session
- * @param session pointer to the session
- * @return pointer to the struct FragmentMessage
+ * function to free a mac endpoint
+ * @param plugin pointer to the plugin struct
+ * @param endpoint pointer to the MacEndpoint to free
  */
-static struct FragmentMessage *
-get_fragment_message_from_session(struct Session * session)
+static void
+free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
 {
-  struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
-  while (fm != NULL)
-    {
-      if (fm->session == session)
-        {
-          return fm;
-        }
-      fm = fm->next;
-    }
-  return NULL;
+  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);
+
 }
 
 /**
- * function to get the message in the fragement queue (out) of a session with a specific id
- * @param session pointer to the session
- * @param message_id id of the message
- * @return pointer to the struct FragmentMessage
+ * 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 struct FragmentMessage *
-get_fragment_message_from_session_and_id(struct Session * session,
-    uint32_t message_id)
-{
-  struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
-  while (fm != NULL)
+static void
+free_session (struct Plugin *plugin, struct Sessionqueue *queue,
+              int do_free_macendpoint)
+{
+  struct Sessionqueue *pendingsession;
+  struct Sessionqueue *pendingsession_tmp;
+  struct PendingMessage *pm;
+  struct MacEndpoint *endpoint;
+  struct FragmentMessage *fm;
+  struct FragmentMessage *fmnext;
+  int check = 0;
+
+  GNUNET_assert (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) && (fm->message_id_out == message_id))
-        {
-          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);
 }
 
 /**
@@ -1842,75 +2285,35 @@ get_fragment_message_from_session_and_id(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 Receive_Message_Queue * receive_queue;
+  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);
-          while (fm != NULL)
-            {
-              free_fragment_message(plugin, fm);
-              fm = get_fragment_message_from_session(queue->content);
-            }
-          check_next_fragment_timeout(plugin);
-
-          //dispose all received fragments
-          receive_queue = get_receive_message_from_session(plugin,
-              queue->content);
-          while (receive_queue != NULL)
-            {
-              free_receive_message(plugin, receive_queue);
-              receive_queue = get_receive_message_from_session(plugin,
-                  queue->content);
-            }
-
-          // 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;
+  }
 }
 
 /**
@@ -1928,764 +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)
+  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))
     {
-      /* TODO check for bad addresses like multicast, broadcast, etc */
-      return GNUNET_OK;
+      //packet not big enought
+      return;
     }
-  else
+
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan whole messages received"), 1,
+                              GNUNET_NO);
+    wlanheader = (struct WlanHeader *) hdr;
+
+    session = search_session (plugin, endpoint, &wlanheader->source);
+
+    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)
     {
-      return GNUNET_SYSERR;
+      //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;
     }
 
-  return GNUNET_SYSERR;
-}
+    //if not in session list
+    if (session == NULL)
+    {
+      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)
+        {
+          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;
+          }
 
-/**
- * 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;
-
-  //GNUNET_assert(cls !=NULL);
-  if (addrlen != 6)
-    {
-      /* invalid address (MAC addresses have 6 bytes) */
-      GNUNET_break (0);
-      return NULL;
-    }
-  input = (const unsigned char*) addr;
-  GNUNET_snprintf(ret, sizeof(ret),
-      "%s Mac-Address %02X:%02X:%02X:%02X:%02X:%02X", PROTOCOL_PREFIX,
-      input[0], input[1], input[2], input[3], input[4], input[5]);
-  return ret;
-}
-
-/**
- * function to check if bitfield is representation of fragments of the message
- * @param rec_message message to check
- */
-
-void
-check_message_fragment_bitfield(struct Receive_Message_Queue * rec_message)
-{
-  uint64_t checkfragments = 0;
-  struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
-
-  while (rec_queue != NULL)
-    {
-      setBit((char*) &checkfragments, rec_queue->num);
-      rec_queue = rec_queue->next;
-
-    }
-  GNUNET_assert(checkfragments == rec_message->received_fragments);
-}
-
-/**
- * Function to test if fragment number already exists in the fragments received
- *
- * @param rec_message message this fragment belongs to
- * @param fh Fragmentheader of the fragment
- * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
- */
-
-static const int
-is_double_msg(struct Receive_Message_Queue * rec_message,
-    struct FragmentationHeader * fh)
-{
-  //test if bitfield is okay
-#if DEBUG_wlan
-  check_message_fragment_bitfield(rec_message);
-#endif
-
-  return testBit((char *) &rec_message->received_fragments, ntohs(
-      fh->fragment_off_or_num));
-
-}
-
-/**
- * Function to insert a fragment in a queue of a message
- * @param session session the fragment belongs to
- * @param rec_queue fragment to add
- */
-
-static void
-insert_fragment_in_queue(struct Receive_Message_Queue * rec_message,
-    struct Receive_Fragment_Queue * rec_queue)
-{
-  struct Receive_Fragment_Queue * rec_queue2 = rec_message->frag_head;
-  struct WlanHeader * wlanheader = NULL;
-
-  GNUNET_assert(rec_message != NULL);
-  GNUNET_assert(rec_queue != NULL);
-
-  //this is the first fragment of the message (fragment id 0)
-  if (rec_queue->num == 0)
-    {
-      wlanheader = (struct WlanHeader *) rec_queue->msg;
-      rec_message->rec_size = ntohs(wlanheader->header.size);
-    }
-
-  //sort into list
-  while (rec_queue2 != NULL)
-    {
-      if (rec_queue2->num > rec_queue->num)
+        }
+        else
         {
-          //next element number is grater than the current num
-          GNUNET_CONTAINER_DLL_insert_before(rec_message->frag_head, rec_message->frag_tail, rec_queue2, rec_queue);
-          setBit((char *) &rec_message->received_fragments, rec_queue->num);
+          GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                           "WLAN client not in session list and not a hello message\n");
           return;
         }
-      rec_queue = rec_queue->next;
+      }
+      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;
+      }
     }
-  //no element has a grater number
-  GNUNET_CONTAINER_DLL_insert_tail(rec_message->frag_head, rec_message->frag_tail, rec_queue);
-
-  setBit((char *) &rec_message->received_fragments, rec_queue->num);
-}
-
-/**
- * Function to dispose the fragments received for a message and the message
- * @param plugin pointer to the plugin struct
- * @param rec_message pointer to the struct holding the message which should be freed
- */
 
-static void
-free_receive_message(struct Plugin* plugin,
-    struct Receive_Message_Queue * rec_message)
-{
-  GNUNET_assert(rec_message !=NULL);
-  struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
-  struct Receive_Fragment_Queue * rec_queue2;
+    //"receive" the message
 
-  while (rec_queue != NULL)
+    if (memcmp
+        (&wlanheader->source, &session->target,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
-      rec_queue2 = rec_queue;
-      rec_queue = rec_queue->next;
-      GNUNET_free(rec_queue2);
+      //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;
     }
 
-  GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rec_message);
-
-  GNUNET_assert(plugin->pending_receive_messages > 0);
-  GNUNET_assert(rec_message->session->fragment_messages_in_count > 0);
-
-  plugin->pending_receive_messages--;
-  rec_message->session->fragment_messages_in_count--;
-  GNUNET_free(rec_message);
-}
-
-/**
- * Function to check if all fragments of a message have been received
- * @param plugin the plugin handle
- * @param session_light information of the message sender
- * @param session session the message belongs to
- * @param rec_message pointer to the message that should be checked
- */
-
-static void
-check_rec_finished_msg(struct Plugin* plugin,
-    struct Session_light * session_light, struct Session * session,
-    struct Receive_Message_Queue * rec_message)
-{
-  struct Receive_Fragment_Queue * rec_queue = rec_message->frag_head;
-  int packetsize = rec_message->rec_size;
-  int sum = 0;
-  int aktnum = 0;
-  uint64_t bitfield = 0;
-  char * msg;
-
-  GNUNET_assert(rec_message !=NULL);
-  //check if first fragment is present
-  if (packetsize == MESSAGE_LENGHT_UNKNOWN)
+    if (memcmp
+        (&wlanheader->target, plugin->env->my_identity,
+         sizeof (struct GNUNET_PeerIdentity)) != 0)
     {
+      //wrong peer id
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                       "WLAN peer target id doesn't match our peer id: session %p\n",
+                       session);
       return;
     }
-#if DEBUG_wlan
-  check_message_fragment_bitfield(rec_message);
-#endif
 
-  bitfield = ~bitfield;
-  bitfield = bitfield >> (63 - rec_message->frag_tail->num);
-  if (rec_message->received_fragments == bitfield)
-    {
-
-      while (rec_queue != NULL)
-        {
-          sum += rec_queue->size;
-          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
+    GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
+                               (const char *) temp_hdr,
+                               ntohs (hdr->size) - sizeof (struct WlanHeader),
+                               GNUNET_YES, GNUNET_NO);
 
-          //TODO use mst
-          //copy fragments together
-          msg = GNUNET_malloc(packetsize);
-          rec_queue = rec_message->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_receive_message(plugin, rec_message);
-          //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);
-        }
-    }
+    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 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
-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));
+process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
+{
+
+  GNUNET_assert (client != NULL);
+  GNUNET_assert (cls != NULL);
+  struct Session *session = (struct Session *) client;
+  struct Plugin *plugin = (struct Plugin *) cls;
+  struct GNUNET_ATS_Information ats[2];
+
+  ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
+  ats[0].value = htonl (1);
+  ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
+  ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
+                   "Calling plugin->env->receive for session %p; %s; size: %u\n",
+                   session, wlan_plugin_address_to_string (NULL,
+                                                           session->mac->
+                                                           addr.mac, 6),
+                   htons (hdr->size));
+  plugin->env->receive (plugin->env->cls, &(session->target), hdr,
+                        (const struct GNUNET_ATS_Information *) &ats, 2,
+                        session, (const char *) &session->mac->addr,
+                        sizeof (session->mac->addr));
 }
 
 /**
- * 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);
-
-      return;
+      {
+        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
+    else
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-          "wlan_data_massage_handler got wrong message type\n");
+      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
+                       "WLAN client not in session list and HELLO message is not okay\n");
       return;
     }
-}
-
-/**
- * function to add an ack to send it for a received fragment
- * @param plugin pointer to the global plugin structure
- * @param session pointer to the session this ack belongs to
- * @param bitfield bitfield to send
- * @param fh pointer to the fragmentation header which we would like to acknolage
- */
-
-void
-add_ack_for_send(struct Plugin * plugin, struct Session * session,
-    uint64_t bitfield, struct FragmentationHeader * fh)
-{
-  struct AckSendQueue * ack;
-
-  GNUNET_assert(plugin != NULL);
-  GNUNET_assert(session != NULL);
-  GNUNET_assert(fh != NULL);
-
-  ack = GNUNET_malloc(sizeof(struct AckSendQueue));
-  ack->fragments_field = bitfield;
-  ack->message_id = ntohl(fh->message_id);
-  ack->session = session;
-
-  GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
-      plugin->ack_send_queue_tail, ack);
-
-}
-
-/**
- * function to get the receive message from the message id and the session
- * @param plugin pointer to the plugin struct
- * @param session session this fragment belongs to
- * @param message_id id of the message
- */
-
-struct Receive_Message_Queue *
-get_receive_message(struct Plugin * plugin, struct Session * session,
-    uint32_t message_id)
-{
-  struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
-  while (rec_message != NULL)
-    {
-      if ((rec_message->message_id_in == message_id) && (rec_message->session
-          == session))
-        {
-          return rec_message;
-        }
-      rec_message = rec_message->next;
-    }
-  return NULL;
-}
-
-/**
- * function to get the receive message of a session
- * @param plugin pointer to the plugin struct
- * @param session session this fragment belongs to
- */
-
-struct Receive_Message_Queue *
-get_receive_message_from_session(struct Plugin * plugin,
-    struct Session * session)
-{
-  struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
-  while (rec_message != NULL)
+    break;
+  case GNUNET_MESSAGE_TYPE_FRAGMENT:
+    macendpoint = get_macendpoint (plugin, &rxinfo->frame.addr2, GNUNET_YES);
+    GNUNET_STATISTICS_update (plugin->env->stats,
+                              _("# wlan fragments received"), 1, GNUNET_NO);
+    int ret =
+        GNUNET_DEFRAGMENT_process_fragment (macendpoint->defrag,
+                                            hdr);
+
+    if (ret == GNUNET_NO)
     {
-      if (rec_message->session == session)
-        {
-          return rec_message;
-        }
-      rec_message = rec_message->next;
+      macendpoint->dups++;
     }
-  return NULL;
-}
-
-/**
- * function to insert a received fragment into the right fragment queue of the right message
- * @param plugin pointer to the plugin struct
- * @param session_light pointer to the session_light struct of this message
- * @param session session this fragment belongs to
- * @param fh pointer to the header of the fragment
- * @return new fragment bitfield for the message
- */
-
-uint64_t
-insert_fragment_in_in_message_queue(struct Plugin * plugin,
-    struct Session_light * session_light, struct Session * session,
-    struct FragmentationHeader * fh)
-{
-  struct Receive_Fragment_Queue * rec_queue = NULL;
-  struct Receive_Message_Queue * rec_message;
-  const char * tempmsg = (char*) &fh[1];
-  uint64_t retval = 0;
-
-  //TODO fragments do not timeout
-  //check if message_id is right or it is a new msg
-  GNUNET_assert(fh != NULL);
-
-  rec_message = get_receive_message(plugin, session, ntohs(fh->message_id));
-
-  if (rec_message == NULL)
+    else if (ret == GNUNET_OK)
     {
-      if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
-        {
-
-          //new message incoming
-          rec_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
-          rec_message->message_id_in = ntohs(fh->message_id);
-          rec_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
-          rec_message->session = session;
-          rec_message->timeout = GNUNET_TIME_absolute_add(
-              GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
-          rec_message->received_fragments = 0;
-
-          GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rec_message);
-
-          session->fragment_messages_in_count++;
-          plugin->pending_receive_messages++;
-
-#if DEBUG_wlan
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_DEBUG,
-              "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
-              rec_message->message_id_in, session->fragment_messages_in_count,
-              plugin->pending_receive_messages);
-#endif
-        }
-      else
-        {
-
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_INFO,
-              "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached\n");
-          setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
-          return retval;
-        }
+      macendpoint->fragc++;
     }
-
-  if (is_double_msg(rec_message, fh) != GNUNET_YES)
+    set_next_send (plugin);
+    break;
+  case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
+    if (NULL == macendpoint)
     {
-
-      //report size
-      rec_queue = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
-          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(rec_message, rec_queue);
-      //save bitfield
-      retval = rec_message->received_fragments;
-
-#if DEBUG_wlan
-      GNUNET_log(
-          GNUNET_ERROR_TYPE_DEBUG,
-          "New fragment:  size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
-          rec_message->rec_size, rec_queue->size,
-          rec_message->received_fragments, rec_message->message_id_in, session);
-#endif
-
-      check_rec_finished_msg(plugin, session_light, session, rec_message);
+      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;
     }
-  else
+    fm = macendpoint->sending_messages_head;
+    while (fm != NULL)
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
-      retval = rec_message->received_fragments;
-
+      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;
     }
-  return retval;
-
+    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 used for to process the data received from the wlan interface
+ * Function to print mac addresses nicely.
  *
- * @param cls the plugin handle
- * @param session_light FIXME: document
- * @param hdr hdr of the GNUNET_MessageHeader
+ * @param mac the mac address
+ * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function
  */
-static void
-wlan_data_helper(void *cls, struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr)
+static const char *
+macprinter (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
 {
-  struct Plugin *plugin = cls;
-  struct Session * session = NULL;
-
-  struct FragmentationHeader * fh = NULL;
-  struct FragmentationAckHeader * fah = NULL;
-  struct FragmentMessage * fm = NULL;
-
-  const char * tempmsg = NULL;
-
-  uint64_t fragment_bitfield = 0;
-
-  //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;
-        }
-
-      //if in the session list
-      if (session != NULL)
-        {
-          fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
-              session_light, session, fh);
-        }
-      else
-        {
-          // new session
-          GNUNET_log(
-              GNUNET_ERROR_TYPE_INFO,
-              "WLAN client not in session list, fragment num %u, message id %u\n",
-              ntohs(fh->fragment_off_or_num), ntohs(fh->message_id));
-          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;
-            }
-          setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
-        }
-
-      add_ack_for_send(plugin, session, fragment_bitfield, 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
+  static char macstr[20];
 
-      GNUNET_assert(session_light != NULL);
-      if (session_light->session == NULL)
-        {
-          session_light->session = search_session(plugin, session_light->addr);
-          GNUNET_assert(session_light->session != NULL);
-        }
-      session = session_light->session;
-      fah = (struct FragmentationAckHeader *) hdr;
-      fm = get_fragment_message_from_session_and_id(session, ntohl(
-          fah->message_id));
-      if (fm != NULL)
-        {
+  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;
+}
 
-          fm->ack_bitfield = fm->ack_bitfield | ntohll(fah->fragment_field);
-          check_finished_fragment(plugin, fm);
-        }
-      else
-        {
-          GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
-              "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
-                  fh->message_id));
-          return;
-        }
+/**
+ * Function for the scheduler if a mac endpoint times out
+ * @param cls pointer to the MacEndpoint
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ */
+static void
+macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct MacEndpoint *endpoint = cls;
 
-    }
+  GNUNET_assert (endpoint != NULL);
+  endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  {
+    return;
+  }
+  if (GNUNET_TIME_absolute_get_remaining
+      (GNUNET_TIME_absolute_add
+       (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
+  {
+    GNUNET_assert (endpoint->plugin != NULL);
+    GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
+                              _("# wlan mac endpoints timeouts"), 1, GNUNET_NO);
+    free_macendpoint (endpoint->plugin, endpoint);
+  }
   else
-    {
-      // 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);
+  }
 }
 
-char *
-macprinter(struct MacAddress macx)
-{
-  static char macstr[20];
-  char * mac = macx.mac;
-  sprintf(macstr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac[0], mac[1], mac[2],
-      mac[3], mac[4], mac[5]);
-  return macstr;
+/**
+ * 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;
 }
 
 /**
@@ -2695,276 +2757,178 @@ macprinter(struct MacAddress macx)
  * @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->mac3), mac_bssid, 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->mac2),
-                  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", macprinter(
-                      wlanIeeeHeader->mac1));
-#endif
-            }
-        }
-      else
-        {
-#if DEBUG_wlan
-          GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-              "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
-                  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.mac, 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",
-              macprinter(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.
  *
@@ -2972,67 +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);
-
-  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;
-    }
+  plugin->suid_tokenizer =
+      GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
 
-  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 */