wip
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
index f8178f101cd4c6b8f6c8f2bc68787e705b02c5b5..4df111eec41c27d1a5fd02f83eae67e6a0bf2c33 100644 (file)
@@ -60,7 +60,7 @@
 
 #define HALLO_BEACON_SCALING_FACTOR 900
 
-#define DEBUG_wlan GNUNET_YES
+#define DEBUG_wlan GNUNET_NO
 #define DEBUG_wlan_retransmission GNUNET_NO
 
 #define MESSAGE_LENGHT_UNKNOWN -1
@@ -121,9 +121,13 @@ struct Plugin
   struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
 
   /**
-   * encapsulation of packets received
+   * encapsulation of packets received from the wlan helper
    */
   struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
+  /**
+   * encapsulation of packets received
+   */
+  struct GNUNET_SERVER_MessageStreamTokenizer * fragment_tokenizer;
 
   /**
    * stdout pipe handle for the gnunet-wlan-helper process
@@ -179,7 +183,7 @@ struct Plugin
    * Sessions currently pending for transmission
    * to this peer, if any.
    */
-  struct Sessionqueue * pending_Sessions;
+  struct Sessionqueue * pending_Sessions_head;
 
   /**
    * Sessions currently pending for transmission
@@ -244,7 +248,7 @@ struct Finish_send
 /**
  * Queue of sessions, for the general session queue and the pending session queue
  */
-
+//TODO DOXIGEN
 struct Sessionqueue
 {
   struct Sessionqueue * next;
@@ -255,6 +259,7 @@ struct Sessionqueue
 /**
  * Queue for the fragments received
  */
+//TODO DOXIGEN
 struct Receive_Fragment_Queue
 {
   struct Receive_Fragment_Queue * next;
@@ -265,12 +270,15 @@ struct Receive_Fragment_Queue
   struct Radiotap_rx rxinfo;
 };
 
-struct Session_id_pair
+//TODO DOXIGEN
+struct Session_id_fragment_triple
 {
   struct Session * session;
   uint32_t message_id;
+  struct FragmentMessage * fm;
 };
 
+//TODO DOXIGEN
 struct Plugin_Session_pair
 {
   struct Plugin * plugin;
@@ -367,13 +375,20 @@ struct PendingMessage
 /**
  * Queue for acks to send for fragments recived
  */
-//TODO comments
 struct AckSendQueue
 {
 
+  /**
+   * next ack in the ack send queue
+   */
   struct AckSendQueue * next;
+  /**
+   * previous ack in the ack send queue
+   */
   struct AckSendQueue * prev;
-
+  /**
+   * pointer to the session this ack belongs to
+   */
   struct Session * session;
   /**
    * ID of message, to distinguish between the messages, picked randomly.
@@ -565,8 +580,6 @@ struct FragmentationAckHeader
 
 };
 
-static struct FragmentMessage * return_val;
-
 static void
 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
@@ -726,8 +739,7 @@ get_session(struct Plugin *plugin, const struct MacAddress *addr)
 static void
 queue_session(struct Plugin *plugin, struct Session * session)
 {
-  struct Sessionqueue * queue = plugin->pending_Sessions;
-  struct Sessionqueue * lastitem = NULL;
+  struct Sessionqueue * queue = plugin->pending_Sessions_head;
 
   if (session->pending_message != NULL)
     {
@@ -741,7 +753,6 @@ queue_session(struct Plugin *plugin, struct Session * session)
               return;
             }
           // try next
-          lastitem = queue;
           queue = queue->next;
         }
 
@@ -751,16 +762,17 @@ queue_session(struct Plugin *plugin, struct Session * session)
       queue->content = session;
 
       //insert at the tail
-      GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions,
+      GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions_head,
           plugin->pending_Sessions_tail, queue);
       plugin->pendingsessions++;
     }
 
 }
 
-//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)
@@ -768,7 +780,7 @@ delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   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
@@ -780,10 +792,11 @@ delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     }
 }
 
-//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)
 {
@@ -810,21 +823,11 @@ set_next_beacon_time(struct Plugin * const plugin)
     }
 }
 
-//TODO doxigen
-/*
- static struct GNUNET_TIME_Relative
- get_next_frag_timeout(struct FragmentMessage * fm)
- {
- return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
- fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
- }
- */
-
-//TODO doxigen
 /**
  * Function to get the timeout value for acks for this session
+ * @param fm pointer to the FragmentMessage to get the next timeout
+ * @return time until the next ack should be received, in GNUNET_TIME_Relative
  */
-
 static struct GNUNET_TIME_Relative
 get_ack_timeout(struct FragmentMessage * fm)
 {
@@ -879,9 +882,21 @@ set_next_send(struct Plugin * const plugin)
 
 #endif
 
-  plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
-      &delay_fragment_task, plugin);
-
+  if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
+    {
+      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);
+        }
+    }
+  else
+    {
+      plugin->server_write_delay_task 
+       = GNUNET_SCHEDULER_add_delayed(next_send,
+                                      &delay_fragment_task, plugin);
+    }
 }
 
 /**
@@ -896,7 +911,7 @@ get_next_queue_session(struct Plugin * plugin)
   struct Sessionqueue * sessionqueue;
   struct Sessionqueue * sessionqueue_alt;
   struct PendingMessage * pm;
-  sessionqueue = plugin->pending_Sessions;
+  sessionqueue = plugin->pending_Sessions_head;
 
   while (sessionqueue != NULL)
     {
@@ -905,6 +920,7 @@ get_next_queue_session(struct Plugin * plugin)
       GNUNET_assert(session != NULL);
       pm = session->pending_message;
 
+
 #if DEBUG_wlan
       if (pm == NULL)
         {
@@ -924,7 +940,7 @@ get_next_queue_session(struct Plugin * plugin)
               < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
             {
               plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
+              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
                   plugin->pending_Sessions_tail, sessionqueue);
               GNUNET_free(sessionqueue);
 
@@ -953,7 +969,7 @@ get_next_queue_session(struct Plugin * plugin)
               sessionqueue_alt = sessionqueue;
               sessionqueue = sessionqueue->next;
               plugin->pendingsessions--;
-              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
+              GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
                   plugin->pending_Sessions_tail, sessionqueue_alt);
 
               GNUNET_free(sessionqueue_alt);
@@ -1082,9 +1098,9 @@ check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
 
 #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);
+  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)
@@ -1143,6 +1159,7 @@ set_next_message_fragment_pos(struct Plugin * plugin,
 
 }
 
+//TODO DOXIGEN
 static int
 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
     struct Radiotap_Send * header)
@@ -1223,6 +1240,7 @@ getcrc16(const char *msgbuf, size_t msgbuf_size)
   return 0;
 }
 
+//TODO DOXIGEN
 static void
 send_hello_beacon(struct Plugin * plugin)
 {
@@ -1278,6 +1296,7 @@ send_hello_beacon(struct Plugin * plugin)
   set_next_send(plugin);
 }
 
+//TODO DOXIGEN
 static void
 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
 {
@@ -1298,7 +1317,7 @@ send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
       "Sending ack for message_id %u with fragment field %u, size %u\n",
       ack->message_id, ack->fragments_field, size
-          - sizeof(struct Radiotap_Send));
+      - sizeof(struct Radiotap_Send));
 #endif
 
   msgheader = GNUNET_malloc(size);
@@ -1330,40 +1349,44 @@ send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
   set_next_send(plugin);
 }
 
+//TODO DOXIGEN
 static void
-finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+finish_sending(void *cls, 
+              const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct Finish_send * finish;
+  struct Finish_send * finish = cls;
   struct Plugin * plugin;
   ssize_t bytes;
 
-  finish = cls;
   plugin = finish->plugin;
-
   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
 
-  bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
-      finish->msgheader, finish->size);
-  GNUNET_assert(bytes != GNUNET_SYSERR);
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    {
+      GNUNET_free (finish->msgstart);
+      GNUNET_free (finish);
+      return;
+    }
+  bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle,
+                                 finish->msgheader, 
+                                 finish->size);
+  GNUNET_assert (bytes != GNUNET_SYSERR);
 
   if (bytes != finish->size)
     {
-
       finish->msgheader = finish->msgheader + bytes;
       finish->size = finish->size - bytes;
-      plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
-          GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
-          &finish_sending, finish);
+      plugin->server_write_task 
+       = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL,
+                                         plugin->server_stdin_handle,
+                                         &finish_sending, finish);
     }
   else
     {
       GNUNET_free(finish->msgstart);
       GNUNET_free(finish);
-
       set_next_send(plugin);
-
     }
-
 }
 
 /**
@@ -1375,11 +1398,10 @@ finish_sending(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 static void
 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-
   struct Plugin * plugin = cls;
-  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
 
   struct Session * session;
@@ -1387,7 +1409,6 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct ieee80211_frame * ieeewlanheader;
   struct Radiotap_Send * radioHeader;
   struct GNUNET_MessageHeader * msgheader;
-
   struct FragmentationHeader fragheader;
   struct FragmentationHeader * fragheaderptr;
   struct Finish_send * finish;
@@ -1413,9 +1434,7 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
     {
       send_hello_beacon(plugin);
-
       return;
-
     }
 
   fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
@@ -1459,7 +1478,7 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
               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,
+              + sizeof(struct FragmentationHeader), copyoffset,
               GNUNET_TIME_absolute_get_remaining(fm->timeout));
 #endif
 
@@ -1473,21 +1492,11 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                   fm->message_pos);
             }
           GNUNET_assert(copyoffset < fm->message_size);
-          //FIXME remove later
-          GNUNET_assert(copystart < fm->msg + fm->message_size);
 
           fragheader.header.size = htons(copysize
               + sizeof(struct FragmentationHeader));
           fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
 
-          /* }
-           else
-           {
-           // there is no need to split
-           copystart = fm->msg;
-           copysize = fm->message_size;
-           }*/
-
           size += copysize;
           size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
               + sizeof(struct GNUNET_MessageHeader);
@@ -1503,18 +1512,11 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
           //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);
@@ -1581,6 +1583,7 @@ do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
         }
       return;
     }
+
   GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
       "do_transmit did nothing, should not happen!\n");
 }
@@ -1786,13 +1789,14 @@ search_fragment_message_from_session_and_id(void *cls,
     struct GNUNET_CONTAINER_HeapNode *node, void *element,
     GNUNET_CONTAINER_HeapCostType cost)
 {
-  struct Session_id_pair * pair = (struct Session_id_pair *) cls;
+  struct Session_id_fragment_triple * triple =
+      (struct Session_id_fragment_triple *) cls;
   struct FragmentMessage * fm = (struct FragmentMessage*) element;
 
-  if ((fm->session == pair->session)
-      && (fm->message_id_out == pair->message_id))
+  if ((fm->session == triple->session) && (fm->message_id_out
+      == triple->message_id))
     {
-      return_val = fm;
+      triple->fm = fm;
       return GNUNET_NO;
     }
   return GNUNET_YES;
@@ -1809,12 +1813,12 @@ static struct FragmentMessage *
 get_fragment_message_from_session_and_id(struct Plugin * plugin,
     struct Session * session, uint32_t message_id)
 {
-  struct Session_id_pair pair;
-  pair.session = session;
-  pair.message_id = message_id;
+  struct Session_id_fragment_triple triple;
+  triple.session = session;
+  triple.message_id = message_id;
   GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
-      &search_fragment_message_from_session_and_id, &pair);
-  return return_val;
+      &search_fragment_message_from_session_and_id, &triple);
+  return triple.fm;
 }
 
 /**
@@ -1822,7 +1826,7 @@ get_fragment_message_from_session_and_id(struct Plugin * plugin,
  * @param plugin pointer to the plugin struct
  * @param session session this fragment belongs to
  */
-struct Receive_Message_Queue *
+static struct Receive_Message_Queue *
 get_receive_message_from_session(struct Plugin * plugin,
     struct Session * session)
 {
@@ -1868,37 +1872,59 @@ free_receive_message(struct Plugin* plugin,
   GNUNET_free(rx_message);
 }
 
+/**
+ * function to get the receive message of a session
+ * @param plugin pointer to the plugin struct
+ * @param session session this fragment belongs to
+ */
+static void
+check_receive_message_timeouts(struct Plugin * plugin, struct Session * session)
+{
+  struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
+  while (rec_message != NULL)
+    {
+      if (GNUNET_TIME_absolute_get_remaining(rec_message->timeout).rel_value
+          == 0)
+        {
+          free_receive_message(plugin, rec_message);
+        }
+      rec_message = rec_message->next;
+    }
+
+}
+
+//TODO DOXIGEN
 static void
 free_session(struct Plugin * plugin, struct Sessionqueue * queue)
 {
-  struct Sessionqueue * pendingsession = plugin->pending_Sessions;
+  struct Sessionqueue * pendingsession;
+  struct Sessionqueue * pendingsession_tmp;
   struct PendingMessage * pm;
   struct Receive_Message_Queue * receive_queue;
   struct Plugin_Session_pair pair;
   int check = 0;
 
   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->next;
       if (pendingsession->content == queue->content)
         {
           plugin->pendingsessions--;
-          GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
-              plugin->pending_Sessions_tail, pendingsession);
+          GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
+                                      plugin->pending_Sessions_tail, 
+                                      pendingsession);
           GNUNET_free(pendingsession);
 
-          if (check == 1)
-            {
-              GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-                  "Session is more then once in pending session\n");
-            }
-
+          GNUNET_assert (check == 0);
           check = 1;
         }
-      pendingsession = pendingsession->next;
+      pendingsession = pendingsession_tmp;
     }
 
   //is something of this session in the fragment queue?
@@ -1931,13 +1957,13 @@ free_session(struct Plugin * plugin, struct Sessionqueue * queue)
       GNUNET_free(pm);
     }
 
-  GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
+  GNUNET_CONTAINER_DLL_remove(plugin->sessions, 
+                             plugin->sessions_tail, 
+                             queue);
   GNUNET_free(queue->content);
   GNUNET_free(queue);
   plugin->session_count--;
-
   check_fragment_queue(plugin);
-
 }
 
 /**
@@ -2008,25 +2034,6 @@ wlan_plugin_address_pretty_printer(void *cls, const char *type,
   asc(asc_cls, 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 * rx_msg)
-{
-  uint64_t checkfragments = 0;
-  struct Receive_Fragment_Queue * rx_frag = rx_msg->frag_head;
-
-  while (rx_frag != NULL)
-    {
-      setBit((char*) &checkfragments, rx_frag->num);
-      rx_frag = rx_frag->next;
-
-    }
-  GNUNET_assert(checkfragments == rx_msg->received_fragments);
-}
 
 /**
  * Function to test if fragment number already exists in the fragments received
@@ -2035,8 +2042,7 @@ check_message_fragment_bitfield(struct Receive_Message_Queue * rx_msg)
  * @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
+static int
 is_double_msg(struct Receive_Message_Queue * rx_msg,
     struct FragmentationHeader * fh)
 {
@@ -2055,7 +2061,6 @@ is_double_msg(struct Receive_Message_Queue * rx_msg,
  * @param session session the fragment belongs to
  * @param rec_queue fragment to add
  */
-
 static void
 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
     struct Receive_Fragment_Queue * rx_frag)
@@ -2099,10 +2104,11 @@ insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
  * @param hdr pointer to the data
  */
 static void
-wlan_data_message_handler(struct Plugin * plugin,
-    struct Session_light * session_light,
-    const struct GNUNET_MessageHeader * hdr)
+wlan_data_message_handler(void *cls, void *client,
+    const struct GNUNET_MessageHeader *hdr)
 {
+  struct Plugin * plugin = (struct Plugin*) cls;
+  struct Session_light * session_light = (struct Session_light *) client;
   struct WlanHeader * wlanheader;
   struct Session * session;
   const char * tempmsg;
@@ -2232,9 +2238,10 @@ check_rx_finished_msg(struct Plugin* plugin,
   struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
   int packetsize = rx_message->rec_size;
   int sum;
-  int aktnum;
+  //TODO CLEANUP
+  //int aktnum;
   uint64_t bitfield = 0;
-  char * msg;
+  //char * msg;
 
   //check if first fragment is present
   if (packetsize == MESSAGE_LENGHT_UNKNOWN)
@@ -2279,31 +2286,50 @@ check_rx_finished_msg(struct Plugin* plugin,
               "check_rec_finished_msg: A message for %p is complete\n", session);
 #endif
 
-          //TODO use mst
+          //TODO cleanup
+
           //copy fragments together
-          msg = GNUNET_malloc(packetsize);
+          //msg = GNUNET_malloc(packetsize);
           rx_frag = rx_message->frag_head;
-          aktnum = 0;
+          //aktnum = 0;
+          /*while (rx_frag != NULL)
+           {
+           //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
+           memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
+           aktnum += rx_frag->size;
+           rx_frag = rx_frag->next;
+           }*/
+
           while (rx_frag != NULL)
             {
-              //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
-              memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
-              aktnum += rx_frag->size;
+              if (rx_frag->next != NULL)
+                {
+                  GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
+                      session_light, rx_frag->msg, rx_frag->size, GNUNET_NO,
+                      GNUNET_NO);
+                }
+              else
+                {
+                  //if it is the last fragment just kill all leftover
+                  GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
+                      session_light, rx_frag->msg, rx_frag->size, GNUNET_YES,
+                      GNUNET_NO);
+                }
               rx_frag = rx_frag->next;
             }
-
           free_receive_message(plugin, rx_message);
           //call wlan_process_helper to process the message
-          wlan_data_message_handler(plugin, session_light,
-              (struct GNUNET_MessageHeader*) msg);
+          //wlan_data_message_handler(plugin, session_light,
+          //   (struct GNUNET_MessageHeader*) msg);
           //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
 
-          GNUNET_free(msg);
+          //GNUNET_free(msg);
         }
     }
   //    }
 }
 
+//TODO DOXIGEN
 static void
 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
 {
@@ -2410,6 +2436,11 @@ insert_fragment_in_in_message_queue(struct Plugin * plugin,
 
   if (rx_message == NULL)
     {
+      if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
+        {
+          check_receive_message_timeouts(plugin, session);
+        }
+
       if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
         {
 
@@ -2418,8 +2449,6 @@ insert_fragment_in_in_message_queue(struct Plugin * plugin,
           rx_message->message_id_in = ntohl(fh->message_id);
           rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
           rx_message->session = session;
-          rx_message->timeout = GNUNET_TIME_absolute_add(
-              GNUNET_TIME_absolute_get(), MESSAGE_IN_TIMEOUT);
           rx_message->received_fragments = 0;
 
           GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
@@ -2447,6 +2476,11 @@ insert_fragment_in_in_message_queue(struct Plugin * plugin,
         }
     }
 
+  //reset timeout
+  rx_message->timeout = GNUNET_TIME_absolute_add(
+  GNUNET_TIME_absolute_get(),
+      MESSAGE_IN_TIMEOUT);
+
   if (is_double_msg(rx_message, fh) != GNUNET_YES)
     {
 
@@ -2576,8 +2610,12 @@ wlan_data_helper(void *cls, struct Session_light * session_light,
               GNUNET_ERROR_TYPE_INFO,
               "WLAN client not in session list, fragment num %u, message id %u\n",
               ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
-          wlan_data_message_handler(plugin, session_light,
-              (struct GNUNET_MessageHeader *) tempmsg);
+
+          GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer, session_light,
+              tempmsg, ntohs(hdr->size) - sizeof(struct FragmentationHeader),
+              GNUNET_YES, GNUNET_NO);
+          //wlan_data_message_handler(plugin, session_light,
+          //    (struct GNUNET_MessageHeader *) tempmsg);
           session = session_light->session;
           //test if a session was created
           if (session == NULL)
@@ -2658,6 +2696,7 @@ wlan_data_helper(void *cls, struct Session_light * session_light,
 
 }
 
+//TODO DOXIGEN
 const char *
 macprinter(const u_int8_t * mac)
 {
@@ -2706,7 +2745,7 @@ wlan_process_helper(void *cls, void *client,
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
             "Size of packet is too small; size: %u min size: %u\n", ntohs(
                 hdr->size), sizeof(struct ieee80211_frame)
-                + sizeof(struct GNUNET_MessageHeader));
+            + sizeof(struct GNUNET_MessageHeader));
 #endif
         //GNUNET_break (0);
         /* FIXME: restart SUID process */
@@ -2812,13 +2851,7 @@ wlan_plugin_helper_read(void *cls,
   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)
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
 
   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
@@ -2927,7 +2960,36 @@ libgnunet_plugin_transport_wlan_done(void *cls)
       "libgnunet_plugin_transport_wlan_done started\n");
 #endif
 
-  GNUNET_assert(cls !=NULL);
+
+  GNUNET_OS_process_close(plugin->server_proc);
+  GNUNET_DISK_pipe_close(plugin->server_stdout);
+  GNUNET_DISK_pipe_close(plugin->server_stdin);
+
+  GNUNET_assert (cls !=NULL);
+  //free sessions
+  while (queue != NULL)
+    {
+      queue_next = queue->next;
+      free_session(plugin, queue);
+      queue = queue_next;
+
+    }
+  if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
+      plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel(plugin->server_write_task);
+      plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel(plugin->server_read_task);
+      plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+
 
   if (plugin->suid_tokenizer != NULL)
     GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
@@ -2935,6 +2997,9 @@ libgnunet_plugin_transport_wlan_done(void *cls)
   if (plugin->data_tokenizer != NULL)
     GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
 
+  if (plugin->fragment_tokenizer != NULL)
+    GNUNET_SERVER_mst_destroy(plugin->fragment_tokenizer);
+
   fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
       plugin->pending_Fragment_Messages);
 
@@ -2945,15 +3010,6 @@ libgnunet_plugin_transport_wlan_done(void *cls)
           plugin->pending_Fragment_Messages);
     }
 
-  //free sessions
-  while (queue != NULL)
-    {
-      queue_next = queue->next;
-      free_session(plugin, queue);
-      queue = queue_next;
-
-    }
-
   GNUNET_free_non_null(plugin->interface);
   GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
   GNUNET_free (plugin);
@@ -2992,9 +3048,11 @@ libgnunet_plugin_transport_wlan_init(void *cls)
       plugin);
 
   plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
+  plugin->fragment_tokenizer = GNUNET_SERVER_mst_create(
+      &wlan_data_message_handler, 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;