fbaf7aa233432bd9128465a0cf629fc07a3f1b44
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
1 /*
2  This file is part of GNUnet
3  (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
4
5  GNUnet is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published
7  by the Free Software Foundation; either version 3, or (at your
8  option) any later version.
9
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  General Public License for more details.
14
15  You should have received a copy of the GNU General Public License
16  along with GNUnet; see the file COPYING.  If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file transport/plugin_transport_wlan.c
23  * @brief transport plugin for wlan
24  * @author David Brodski
25  */
26
27 #include "platform.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_transport_plugin.h"
34 #include "plugin_transport_wlan.h"
35 #include "gnunet_common.h"
36 #include "gnunet_crypto_lib.h"
37 #include "wlan/ieee80211.h"
38
39 #include <string.h>
40
41 #define PROTOCOL_PREFIX "wlan"
42
43 /**
44  * Max size of packet from helper
45  */
46 #define WLAN_MTU 3000
47
48 /**
49  * Time until retransmission of a fragment in ms
50  */
51 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
52
53 #define FRAGMENT_QUEUE_SIZE 10
54 #define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
55
56 #define MESSAGE_IN_TIMEOUT GNUNET_TIME_UNIT_SECONDS
57
58 #define MESSAGES_IN_QUEUE_SIZE 10
59 #define MESSAGES_IN_QUEUE_PER_SESSION 1
60
61 #define HALLO_BEACON_SCALING_FACTOR 900
62
63 #define DEBUG_wlan GNUNET_NO
64 #define DEBUG_wlan_retransmission GNUNET_NO
65
66 #define MESSAGE_LENGHT_UNKNOWN -1
67 //#define NO_MESSAGE_OR_MESSAGE_FINISHED -2
68
69 /**
70  * After how long do we expire an address that we
71  * learned from another peer if it is not reconfirmed
72  * by anyone?
73  */
74 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
75
76 /**
77  * Initial handshake message for a session.
78  */
79 struct WelcomeMessage
80 {
81   /**
82    * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
83    */
84   struct GNUNET_MessageHeader header;
85
86   /**
87    * Identit*mac_y of the node connecting (TCP client)
88    */
89   struct GNUNET_PeerIdentity clientIdentity;
90
91 };
92
93 /**
94  * Encapsulation of all of the state of the plugin.
95  */
96 struct Plugin
97 {
98   /**
99    * Our environment.
100    */
101   struct GNUNET_TRANSPORT_PluginEnvironment *env;
102
103   /**
104    * List of open sessions. head
105    */
106   struct Sessionqueue *sessions;
107
108   /**
109    * List of open sessions. tail
110    */
111   struct Sessionqueue *sessions_tail;
112
113   /**
114    * Number of sessions
115    */
116   unsigned int session_count;
117
118   /**
119    * encapsulation of data from the local wlan helper program
120    */
121   struct GNUNET_SERVER_MessageStreamTokenizer * suid_tokenizer;
122
123   /**
124    * encapsulation of packets received from the wlan helper
125    */
126   struct GNUNET_SERVER_MessageStreamTokenizer * data_tokenizer;
127   /**
128    * encapsulation of packets received
129    */
130   struct GNUNET_SERVER_MessageStreamTokenizer * fragment_tokenizer;
131
132   /**
133    * stdout pipe handle for the gnunet-wlan-helper process
134    */
135   struct GNUNET_DISK_PipeHandle *server_stdout;
136
137   /**
138    * stdout file handle for the gnunet-wlan-helper process
139    */
140   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
141
142   /**
143    * stdin pipe handle for the gnunet-wlan-helper process
144    */
145   struct GNUNET_DISK_PipeHandle *server_stdin;
146
147   /**
148    * stdin file handle for the gnunet-wlan-helper process
149    */
150   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
151
152   /**
153    * ID of the gnunet-wlan-server std read task
154    */
155   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
156
157   /**
158    * ID of the gnunet-wlan-server std read task
159    */
160   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
161
162   /**
163    * ID of the delay task for writing
164    */
165   GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
166
167   /**
168    * The process id of the wlan process
169    */
170   struct GNUNET_OS_Process *server_proc;
171
172   /**
173    * The interface of the wlan card given to us by the user.
174    */
175   char *interface;
176
177   /**
178    * The mac_address of the wlan card given to us by the helper.
179    */
180   struct MacAddress mac_address;
181
182   /**
183    * Sessions currently pending for transmission
184    * to this peer, if any.
185    */
186   struct Sessionqueue * pending_Sessions_head;
187
188   /**
189    * Sessions currently pending for transmission
190    * to this peer (tail), if any.
191    */
192   struct Sessionqueue * pending_Sessions_tail;
193
194   /**
195    * number of pending sessions
196    */
197   unsigned int pendingsessions;
198
199   /**
200    * Messages in the fragmentation queue, head
201    */
202   struct GNUNET_CONTAINER_Heap * pending_Fragment_Messages;
203
204   /**
205    * Messages in the in Queue, head
206    */
207   struct Receive_Message_Queue * receive_messages_head;
208
209   /**
210    * Messages in the in Queue, tail
211    */
212   struct Receive_Message_Queue * receive_messages_teil;
213
214   /**
215    * number of messages in the in queue
216    */
217   unsigned int pending_receive_messages;
218
219   /**
220    * time of the next "hello-beacon"
221    */
222   struct GNUNET_TIME_Absolute beacon_time;
223
224   /**
225    * queue to send acks for received fragments (head)
226    */
227   struct AckSendQueue * ack_send_queue_head;
228
229   /**
230    * queue to send acks for received fragments (tail)
231    */
232   struct AckSendQueue * ack_send_queue_tail;
233
234 };
235
236 /**
237  * Struct to store data if file write did not accept the whole packet
238  */
239 struct Finish_send
240 {
241   struct Plugin * plugin;
242   char * msgheader;
243   struct GNUNET_MessageHeader * msgstart;
244   ssize_t size;
245   struct GNUNET_TIME_Absolute next_send;
246 };
247
248 /**
249  * Queue of sessions, for the general session queue and the pending session queue
250  */
251 //TODO DOXIGEN
252 struct Sessionqueue
253 {
254   struct Sessionqueue * next;
255   struct Sessionqueue * prev;
256   struct Session * content;
257 };
258
259 /**
260  * Queue for the fragments received
261  */
262 //TODO DOXIGEN
263 struct Receive_Fragment_Queue
264 {
265   struct Receive_Fragment_Queue * next;
266   struct Receive_Fragment_Queue * prev;
267   uint16_t num;
268   const char * msg;
269   uint16_t size;
270   struct Radiotap_rx rxinfo;
271 };
272
273 //TODO DOXIGEN
274 struct Session_id_fragment_triple
275 {
276   struct Session * session;
277   uint32_t message_id;
278   struct FragmentMessage * fm;
279 };
280
281 //TODO DOXIGEN
282 struct Plugin_Session_pair
283 {
284   struct Plugin * plugin;
285   struct Session * session;
286 };
287
288 /**
289  * Queue for the fragments received
290  */
291 struct Receive_Message_Queue
292 {
293   struct Receive_Message_Queue * next;
294
295   struct Receive_Message_Queue * prev;
296
297   /**
298    * current number for message incoming, to distinguish between the messages
299    */
300   uint32_t message_id_in;
301
302   /**
303    * size of the message received,
304    * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
305    * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
306    */
307   int rec_size;
308
309   /**
310    * Sorted queue with the fragments received; head
311    */
312
313   struct Receive_Fragment_Queue * frag_head;
314
315   /**
316    * Sorted queue with the fragments received; tail
317    */
318
319   struct Receive_Fragment_Queue * frag_tail;
320
321   /**
322    * Session this fragment belongs to
323    */
324
325   struct Session * session;
326
327   /**
328    * Timeout value for the pending message.
329    */
330   struct GNUNET_TIME_Absolute timeout;
331
332   /**
333    * Bitfield of received fragments
334    */
335
336   uint64_t received_fragments;
337 };
338
339 /**
340  * Information kept for each message that is yet to
341  * be transmitted.
342  */
343 struct PendingMessage
344 {
345
346   /**
347    * The pending message
348    */
349   char *msg;
350
351   /**
352    * Size of the message
353    */
354   size_t message_size;
355
356   /**
357    * Continuation function to call once the message
358    * has been sent.  Can be NULL if there is no
359    * continuation to call.
360    */
361   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
362
363   /**
364    * Cls for transmit_cont
365    */
366   void * transmit_cont_cls;
367
368   /**
369    * Timeout value for the pending message.
370    */
371   struct GNUNET_TIME_Absolute timeout;
372
373 };
374
375 /**
376  * Queue for acks to send for fragments recived
377  */
378 struct AckSendQueue
379 {
380
381   /**
382    * next ack in the ack send queue
383    */
384   struct AckSendQueue * next;
385   /**
386    * previous ack in the ack send queue
387    */
388   struct AckSendQueue * prev;
389   /**
390    * pointer to the session this ack belongs to
391    */
392   struct Session * session;
393   /**
394    * ID of message, to distinguish between the messages, picked randomly.
395    */
396   uint32_t message_id;
397
398   /**
399    * Bit field for received fragments
400    */
401   uint64_t fragments_field;
402
403 };
404
405 /**
406  * Session infos gathered from a messages
407  */
408
409 struct Session_light
410 {
411   /**
412    * the session this message belongs to
413    */
414   struct Session * session;
415   /**
416    * peer mac address
417    */
418   struct MacAddress addr;
419 };
420
421 /**
422  * Session handle for connections.
423  */
424 struct Session
425 {
426
427   /**
428    * API requirement.
429    */
430   struct SessionHeader header;
431
432   /**
433    * Pointer to the global plugin struct.
434    */
435   struct Plugin *plugin;
436
437   /**
438    * Message currently pending for transmission
439    * to this peer, if any.
440    */
441   struct PendingMessage *pending_message;
442
443   /**
444    * Message currently pending for transmission
445    * to this peer, if any.
446    */
447   struct PendingMessage *pending_message2;
448
449   /**
450    * To whom are we talking to (set to our identity
451    * if we are still waiting for the welcome message)
452    */
453   struct GNUNET_PeerIdentity target;
454
455   /**
456    * peer mac address
457    */
458   struct MacAddress addr;
459
460   /**
461    * Address of the other peer (either based on our 'connect'
462    * call or on our 'accept' call).
463    */
464   void *connect_addr;
465
466   /**
467    * Last activity on this connection.  Used to select preferred
468    * connection.
469    */
470   struct GNUNET_TIME_Absolute last_activity;
471
472   /**
473    * count of messages in the fragment out queue for this session
474    */
475
476   int fragment_messages_out_count;
477
478   /**
479    * count of messages in the fragment in queue for this session
480    */
481
482   int fragment_messages_in_count;
483
484   //TODO DOXIGEN
485   uint8_t rate;
486   uint16_t tx_power;
487   uint8_t antenna;
488
489 };
490
491 /**
492  * Struct for Messages in the fragment queue
493  */
494
495 struct FragmentMessage
496 {
497   /**
498    * heap pointer of this message
499    */
500   struct GNUNET_CONTAINER_HeapNode * node;
501
502   /**
503    * Session this message belongs to
504    */
505
506   struct Session *session;
507
508   /**
509    * This is a doubly-linked list.
510    */
511   struct FragmentMessage *next;
512
513   /**
514    * This is a doubly-linked list.
515    */
516   struct FragmentMessage *prev;
517
518   /**
519    * The pending message
520    */
521   char *msg;
522
523   /**
524    * 0 if not in ack queue
525    * 1 if in ack queue
526    */
527
528   char in_ack_queue;
529
530   /**
531    * Timeout value for the pending message.
532    */
533   struct GNUNET_TIME_Absolute timeout;
534
535   /**
536    * Timeout value for the pending fragments.
537    * Stores the time when the next msg fragment ack has to be received
538    */
539   struct GNUNET_TIME_Absolute next_ack;
540
541   /**
542    * bitfield with all acks received for this message
543    */
544   uint64_t ack_bitfield;
545
546   /**
547    * Size of the message
548    */
549   size_t message_size;
550
551   /**
552    * pos / next fragment number in the message, for fragmentation/segmentation,
553    * some acks can be missing but there is still time
554    */
555   uint32_t message_pos;
556
557   /**
558    * current number for message outgoing, to distinguish between the messages
559    */
560   uint32_t message_id_out;
561 };
562
563 /**
564  * Header for messages which need fragmentation
565  */
566 struct FragmentationAckHeader
567 {
568
569   struct GNUNET_MessageHeader header;
570
571   /**
572    * ID of message, to distinguish between the messages, picked randomly.
573    */
574   uint32_t message_id GNUNET_PACKED;
575
576   /**
577    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
578    */
579   uint64_t fragment_field GNUNET_PACKED;
580
581 };
582
583 static void
584 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
585
586 /**
587  * Sets a bit active in the bitArray. Increment bit-specific
588  * usage counter on disk only if below 4bit max (==15).
589  *
590  * @param bitArray memory area to set the bit in
591  * @param bitIdx which bit to set
592  */
593 static void
594 setBit(char *bitArray, unsigned int bitIdx)
595 {
596   size_t arraySlot;
597   unsigned int targetBit;
598
599   arraySlot = bitIdx / 8;
600   targetBit = (1L << (bitIdx % 8));
601   bitArray[arraySlot] |= targetBit;
602 }
603
604 /**
605  * Checks if a bit is active in the bitArray
606  *
607  * @param bitArray memory area to set the bit in
608  * @param bitIdx which bit to test
609  * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
610  */
611 static int
612 testBit(char *bitArray, unsigned int bitIdx)
613 {
614   size_t slot;
615   unsigned int targetBit;
616
617   slot = bitIdx / 8;
618   targetBit = (1L << (bitIdx % 8));
619   if (bitArray[slot] & targetBit)
620     return GNUNET_YES;
621   return GNUNET_NO;
622 }
623
624 /**
625  * get the next message number, at the moment just a random one
626  * @return returns the next valid message-number for sending packets
627  */
628 static uint32_t
629 get_next_message_id()
630 {
631   return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
632 }
633
634 /**
635  * search for a session with the addr
636  *
637  * @param plugin pointer to the plugin struct
638  * @param addr pointer to the mac address of the peer
639  * @return returns the session
640  */
641 static struct Session *
642 search_session(struct Plugin *plugin, const struct MacAddress *addr)
643 {
644   struct Sessionqueue * queue = plugin->sessions;
645
646   while (queue != NULL)
647     {
648       GNUNET_assert (queue->content != NULL);
649       if (memcmp(addr, &queue->content->addr, sizeof(struct MacAddress)) == 0)
650         return queue->content; /* session found */
651       queue = queue->next;
652     }
653   return NULL;
654 }
655
656 /**
657  * Function called for a quick conversion of the binary address to
658  * a numeric address.  Note that the caller must not free the
659  * address and that the next call to this function is allowed
660  * to override the address again.
661  *
662  * @param cls closure
663  * @param addr binary address
664  * @param addrlen length of the address
665  * @return string representing the same address
666  */
667 static const char*
668 wlan_plugin_address_to_string(void *cls, const void *addr, size_t addrlen)
669 {
670   static char ret[40];
671   const struct MacAddress *mac;
672
673   if (addrlen != sizeof(struct MacAddress))
674     {
675       GNUNET_break (0);
676       return NULL;
677     }
678   mac = addr;
679   GNUNET_snprintf(ret, sizeof(ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
680       PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3],
681       mac->mac[4], mac->mac[5]);
682   return ret;
683 }
684
685 /**
686  * create a new session
687  *
688  * @param plugin pointer to the plugin struct
689  * @param addr pointer to the mac address of the peer
690  * @return returns the session
691  */
692
693 static struct Session *
694 create_session(struct Plugin *plugin, const struct MacAddress * addr)
695 {
696   struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
697
698   GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
699
700   queue->content = GNUNET_malloc (sizeof (struct Session));
701   queue->content->plugin = plugin;
702   queue->content->addr = *addr;
703   queue->content->fragment_messages_out_count = 0;
704   queue->content->fragment_messages_in_count = 0;
705
706   plugin->session_count++;
707
708 #if DEBUG_wlan
709   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New session %p with %s\n",
710       queue->content, wlan_plugin_address_to_string(NULL, addr, 6));
711 #endif
712
713   return queue->content;
714 }
715
716 /**
717  * Get session from address, create if no session exists
718  *
719  * @param plugin pointer to the plugin struct
720  * @param addr pointer to the mac address of the peer
721  * @return returns the session
722  */
723 static struct Session *
724 get_session(struct Plugin *plugin, const struct MacAddress *addr)
725 {
726   struct Session * session = search_session(plugin, addr);
727   if (session != NULL)
728     return session;
729   return create_session(plugin, addr);
730 }
731
732 /**
733  * Queue the session to send data
734  * checks if there is a message pending
735  * checks if this session is not allready in the queue
736  * @param plugin pointer to the plugin
737  * @param session pointer to the session to add
738  */
739 static void
740 queue_session(struct Plugin *plugin, struct Session * session)
741 {
742   struct Sessionqueue * queue = plugin->pending_Sessions_head;
743
744   if (session->pending_message != NULL)
745     {
746       while (queue != NULL)
747         {
748           // content is never NULL
749           GNUNET_assert (queue->content != NULL);
750           // is session already in queue?
751           if (session == queue->content)
752             {
753               return;
754             }
755           // try next
756           queue = queue->next;
757         }
758
759       // Session is not in the queue
760
761       queue = GNUNET_malloc (sizeof (struct Sessionqueue));
762       queue->content = session;
763
764       //insert at the tail
765       GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions_head,
766           plugin->pending_Sessions_tail, queue);
767       plugin->pendingsessions++;
768     }
769
770 }
771
772 /**
773  * Function to schedule the write task, executed after a delay
774  * @param cls pointer to the plugin struct
775  * @param tc GNUNET_SCHEDULER_TaskContext pointer
776  */
777 static void
778 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
779 {
780   struct Plugin * plugin = cls;
781   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
782
783   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
784     return;
785
786   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
787   if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
788     {
789       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
790           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
791           &do_transmit, plugin);
792     }
793 }
794
795 /**
796  * Function to calculate the time of the next periodic "hello-beacon"
797  * @param plugin pointer to the plugin struct
798  */
799
800 static void
801 set_next_beacon_time(struct Plugin * const plugin)
802 {
803   //under 10 known peers: once a second
804   if (plugin->session_count < 10)
805     {
806       plugin->beacon_time = GNUNET_TIME_absolute_add(
807           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
808               GNUNET_TIME_UNIT_SECONDS, HALLO_BEACON_SCALING_FACTOR));
809     }
810   //under 30 known peers: every 10 seconds
811   else if (plugin->session_count < 30)
812     {
813       plugin->beacon_time = GNUNET_TIME_absolute_add(
814           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
815               GNUNET_TIME_UNIT_SECONDS, 10 * HALLO_BEACON_SCALING_FACTOR));
816     }
817   //over 30 known peers: once a minute
818   else
819     {
820       plugin->beacon_time = GNUNET_TIME_absolute_add(
821           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
822               GNUNET_TIME_UNIT_MINUTES, HALLO_BEACON_SCALING_FACTOR));
823     }
824 }
825
826 /**
827  * Function to get the timeout value for acks for this session
828  * @param fm pointer to the FragmentMessage to get the next timeout
829  * @return time until the next ack should be received, in GNUNET_TIME_Relative
830  */
831 static struct GNUNET_TIME_Relative
832 get_ack_timeout(struct FragmentMessage * fm)
833 {
834   return FRAGMENT_TIMEOUT;
835 }
836
837 /**
838  * Function to set the timer for the next timeout of the fragment queue
839  * @param plugin the handle to the plugin struct
840  */
841
842 static void
843 set_next_send(struct Plugin * const plugin)
844 {
845   struct FragmentMessage * fm;
846   struct GNUNET_TIME_Relative next_send;
847   struct GNUNET_TIME_Absolute next_send_tmp;
848
849   //cancel old task
850   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
851     {
852       GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
853       plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
854     }
855
856   fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
857
858   //check if some acks are in the queue
859   if (plugin->ack_send_queue_head != NULL)
860     {
861       next_send = GNUNET_TIME_UNIT_ZERO;
862     }
863
864   //check if there are some fragments in the queue
865   else
866     {
867       next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
868       if (fm != NULL)
869         {
870           next_send_tmp.abs_value = GNUNET_CONTAINER_heap_node_get_cost(
871               fm->node);
872           next_send = GNUNET_TIME_relative_min(next_send,
873               GNUNET_TIME_absolute_get_remaining(next_send_tmp));
874
875         }
876     }
877
878 #if DEBUG_wlan
879
880   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Next packet is send in: %u\n",
881       next_send.rel_value);
882
883 #endif
884
885   if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
886     {
887       if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
888         {
889           plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
890               GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
891               &do_transmit, plugin);
892         }
893     }
894   else
895     {
896       plugin->server_write_delay_task 
897         = GNUNET_SCHEDULER_add_delayed(next_send,
898                                        &delay_fragment_task, plugin);
899     }
900 }
901
902 /**
903  * Function to get the next queued Session, removes the session from the queue
904  * @param plugin pointer to the plugin struct
905  * @return pointer to the session found, returns NULL if there is now session in the queue
906  */
907 static struct Session *
908 get_next_queue_session(struct Plugin * plugin)
909 {
910   struct Session * session;
911   struct Sessionqueue * sessionqueue;
912   struct Sessionqueue * sessionqueue_alt;
913   struct PendingMessage * pm;
914   sessionqueue = plugin->pending_Sessions_head;
915
916   while (sessionqueue != NULL)
917     {
918       session = sessionqueue->content;
919
920       GNUNET_assert(session != NULL);
921       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
922           "Found session %p from pending session queue\n", session
923           );
924       pm = session->pending_message;
925
926
927 #if DEBUG_wlan
928       if (pm == NULL)
929         {
930           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
931               "pending message is empty, should not happen. session %p\n",
932               session);
933         }
934 #endif
935
936       GNUNET_assert(pm != NULL);
937
938       //check for message timeout
939       if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0)
940         {
941           //check if session has no message in the fragment queue
942           if (session->fragment_messages_out_count
943               < FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION)
944             {
945               plugin->pendingsessions--;
946               GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
947                   plugin->pending_Sessions_tail, sessionqueue);
948               GNUNET_free(sessionqueue);
949
950               return session;
951             }
952           else
953             {
954               sessionqueue = sessionqueue->next;
955             }
956         }
957       else
958         {
959
960           session->pending_message = session->pending_message2;
961           session->pending_message2 = NULL;
962
963           //call the cont func that it did not work
964           if (pm->transmit_cont != NULL)
965             pm->transmit_cont(pm->transmit_cont_cls, &(session->target),
966                 GNUNET_SYSERR);
967           GNUNET_free(pm->msg);
968           GNUNET_free(pm);
969
970           if (session->pending_message == NULL)
971             {
972               sessionqueue_alt = sessionqueue;
973               sessionqueue = sessionqueue->next;
974               plugin->pendingsessions--;
975               GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
976                   plugin->pending_Sessions_tail, sessionqueue_alt);
977
978               GNUNET_free(sessionqueue_alt);
979             }
980
981         }
982
983     }
984   return NULL;
985 }
986
987 /**
988  * frees the space of a message in the fragment queue (send queue)
989  * @param plugin the plugin struct
990  * @param fm message to free
991  */
992 static void
993 free_fragment_message(struct Plugin * plugin, struct FragmentMessage * fm)
994 {
995   struct Session * session = fm->session;
996
997   if (fm != NULL)
998     {
999       (session->fragment_messages_out_count)--;
1000       GNUNET_free_non_null(fm->msg);
1001       GNUNET_CONTAINER_heap_remove_node(fm->node);
1002       GNUNET_free(fm);
1003
1004       queue_session(plugin, session);
1005 #if DEBUG_wlan
1006       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1007           "free pending fragment messages, pending messages remaining %u\n",
1008           GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages));
1009 #endif
1010     }
1011 }
1012
1013 /**
1014  * Function to check if there is some space in the fragment queue
1015  * inserts a message if space is available
1016  * @param plugin the plugin struct
1017  */
1018
1019 static void
1020 check_fragment_queue(struct Plugin * plugin)
1021 {
1022   struct Session * session;
1023   struct FragmentMessage * fm;
1024   struct GNUNET_PeerIdentity pid;
1025
1026   struct PendingMessage * pm;
1027
1028   if (GNUNET_CONTAINER_heap_get_size(plugin->pending_Fragment_Messages)
1029       < FRAGMENT_QUEUE_SIZE)
1030     {
1031       session = get_next_queue_session(plugin);
1032       if (session != NULL)
1033         {
1034           pm = session->pending_message;
1035           session->pending_message = NULL;
1036           session->fragment_messages_out_count++;
1037           GNUNET_assert(pm != NULL);
1038
1039           fm = GNUNET_malloc(sizeof(struct FragmentMessage));
1040           fm->message_size = pm->message_size;
1041           fm->msg = pm->msg;
1042           fm->session = session;
1043           fm->timeout.abs_value = pm->timeout.abs_value;
1044           fm->message_pos = 0;
1045           fm->next_ack = GNUNET_TIME_absolute_get();
1046           fm->message_id_out = get_next_message_id();
1047           fm->ack_bitfield = 0;
1048           fm->node = GNUNET_CONTAINER_heap_insert(
1049               plugin->pending_Fragment_Messages, fm,
1050               GNUNET_TIME_absolute_get().abs_value);
1051
1052           GNUNET_assert(session !=NULL);
1053
1054           if (pm->transmit_cont != NULL)
1055             {
1056               pid = session->target;
1057               pm->transmit_cont(pm->transmit_cont_cls, &pid, GNUNET_OK);
1058 #if DEBUG_wlan
1059               GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1060                   "called pm->transmit_cont for %p\n", session);
1061 #endif
1062             }
1063           else
1064             {
1065 #if DEBUG_wlan
1066               GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1067                   "no pm->transmit_cont for %p\n", session);
1068 #endif
1069             }
1070           GNUNET_free(pm);
1071
1072           if (session->pending_message2 != NULL)
1073             {
1074               session->pending_message = session->pending_message2;
1075               session->pending_message2 = NULL;
1076               //requeue session
1077               queue_session(plugin, session);
1078             }
1079
1080         }
1081     }
1082
1083   //check if timeout changed
1084   set_next_send(plugin);
1085 }
1086
1087 /**
1088  * Funktion to check if all fragments where send and the acks received
1089  * frees the space if finished
1090  * @param plugin the plugin struct
1091  * @param fm the message to check
1092  */
1093 static void
1094 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm)
1095 {
1096   //maxack = size of message / max packet size, eg 12 / 5 = 2 start at 0 so ack numbers are 0,1,2
1097   unsigned int maxack = 63 - ((fm->message_size - 1) / (WLAN_MTU
1098       - sizeof(struct FragmentationHeader)));
1099   uint64_t tmpfield = UINT64_MAX;
1100   tmpfield = tmpfield >> maxack;
1101
1102 #if DEBUG_wlan
1103   if (maxack != 63)
1104   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1105       "Test bitfields %X and %X, maxack is %u, fm size %u\n",
1106       fm->ack_bitfield, tmpfield, maxack, fm->message_size);
1107 #endif
1108
1109   if (fm->ack_bitfield == tmpfield)
1110     {
1111
1112 #if DEBUG_wlan_retransmission
1113       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1114           "Finished sending and got all acks; message_id %u\n",
1115           fm->message_id_out);
1116 #endif
1117
1118       free_fragment_message(plugin, fm);
1119
1120       check_fragment_queue(plugin);
1121
1122     }
1123 }
1124
1125 /**
1126  * Function to set the next fragment number
1127  * @param fm use this FragmentMessage
1128  */
1129
1130 static void
1131 set_next_message_fragment_pos(struct Plugin * plugin,
1132     struct FragmentMessage * fm)
1133 {
1134
1135   fm->message_pos++;
1136
1137   //check if retransmit is needed
1138   if (GNUNET_TIME_absolute_get_remaining(fm->next_ack).rel_value == 0)
1139     {
1140
1141       // be positive and try again later :-D
1142       fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1143       // find first missing fragment
1144
1145       fm->message_pos = 0;
1146
1147       GNUNET_CONTAINER_heap_update_cost(plugin->pending_Fragment_Messages,
1148           fm->node, 0);
1149
1150 #if DEBUG_wlan_retransmission
1151       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1152           "Retransmit; message_id %u; fragment number %i, size: %u\n",
1153           fm->message_id_out, fm->message_pos, fm->message_size);
1154 #endif
1155     }
1156
1157   //test if ack 0 (or X) was already received
1158   while (testBit((char*) &fm->ack_bitfield, fm->message_pos) == GNUNET_YES)
1159     {
1160       fm->message_pos++;
1161     }
1162
1163 }
1164
1165 //TODO DOXIGEN
1166 static int
1167 getRadiotapHeader(struct Plugin * plugin, struct Session * session,
1168     struct Radiotap_Send * header)
1169 {
1170
1171   if (session != NULL)
1172     {
1173       header->rate = session->rate;
1174       header->tx_power = session->tx_power;
1175       header->antenna = session->antenna;
1176     }
1177   else
1178     {
1179       header->rate = 255;
1180       header->tx_power = 0;
1181       header->antenna = 0;
1182     }
1183
1184   return GNUNET_YES;
1185 }
1186
1187 /**
1188  * function to generate the wlan hardware header for one packet
1189  * @param Header address to write the header to
1190  * @param to_mac_addr address of the recipient
1191  * @param plugin pointer to the plugin struct
1192  * @return GNUNET_YES if there was no error
1193  */
1194 static int
1195 getWlanHeader(struct ieee80211_frame * Header,
1196     const struct MacAddress * to_mac_addr, struct Plugin * plugin,
1197     unsigned int size)
1198 {
1199   uint16_t * tmp16;
1200   const int rate = 11000000;
1201
1202   Header->i_fc[0] = 0x08;
1203   Header->i_fc[1] = 0x00;
1204   memcpy(&Header->i_addr3, &mac_bssid, sizeof(mac_bssid));
1205   memcpy(&Header->i_addr2, plugin->mac_address.mac, sizeof(plugin->mac_address));
1206   memcpy(&Header->i_addr1, to_mac_addr, sizeof(struct MacAddress));
1207
1208   tmp16 = (uint16_t*) Header->i_dur;
1209   *tmp16 = (uint16_t) htole16((size * 1000000) / rate + 290);
1210
1211   return GNUNET_YES;
1212 }
1213
1214 /**
1215  * 32bit CRC
1216  *
1217  * @param msgbuf pointer tor the data
1218  * @param msgbuf_size size of the data
1219  *
1220  * @return 32bit crc value
1221  */
1222
1223 uint32_t
1224 getcrc32(const char *msgbuf, size_t msgbuf_size)
1225 {
1226   //TODO calc some crc
1227   return 0;
1228 }
1229
1230 /**
1231  * 16bit CRC
1232  *
1233  * @param msgbuf pointer tor the data
1234  * @param msgbuf_size size of the data
1235  *
1236  * @return 16bit crc value
1237  */
1238
1239 uint16_t
1240 getcrc16(const char *msgbuf, size_t msgbuf_size)
1241 {
1242   //TODO calc some crc
1243   return 0;
1244 }
1245
1246 //TODO DOXIGEN
1247 static void
1248 send_hello_beacon(struct Plugin * plugin)
1249 {
1250
1251 #if DEBUG_wlan
1252   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending hello beacon\n");
1253 #endif
1254
1255   uint16_t size;
1256   ssize_t bytes;
1257   uint16_t hallo_size;
1258   struct GNUNET_MessageHeader * msgheader;
1259   struct ieee80211_frame * ieeewlanheader;
1260   struct Radiotap_Send * radioHeader;
1261   struct GNUNET_MessageHeader * msgheader2;
1262
1263   hallo_size = GNUNET_HELLO_size(*(plugin->env->our_hello));
1264   GNUNET_assert(sizeof(struct WlanHeader) + hallo_size <= WLAN_MTU);
1265   size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1266       + sizeof(struct ieee80211_frame) + sizeof(struct GNUNET_MessageHeader)
1267       + hallo_size;
1268
1269   msgheader = GNUNET_malloc(size);
1270   msgheader->size = htons(size);
1271   msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1272
1273   radioHeader = (struct Radiotap_Send*) &msgheader[1];
1274   getRadiotapHeader(plugin, NULL, radioHeader);
1275   ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1276   getWlanHeader(ieeewlanheader, &bc_all_mac, plugin, size);
1277
1278   msgheader2 = (struct GNUNET_MessageHeader*) &ieeewlanheader[1];
1279   msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello))
1280       + sizeof(struct GNUNET_MessageHeader));
1281
1282   msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1283   memcpy(&msgheader2[1], *plugin->env->our_hello, hallo_size);
1284
1285   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1286
1287   if (bytes == GNUNET_SYSERR)
1288     {
1289       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1290           _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1291           errno, strerror(errno));
1292
1293     }
1294   GNUNET_assert(bytes != GNUNET_SYSERR);
1295   GNUNET_assert(bytes == size);
1296   GNUNET_free(msgheader);
1297
1298   set_next_beacon_time(plugin);
1299   set_next_send(plugin);
1300 }
1301
1302 //TODO DOXIGEN
1303 static void
1304 send_ack(struct Plugin * plugin, struct AckSendQueue * ack)
1305 {
1306
1307   uint16_t size;
1308   ssize_t bytes;
1309   struct GNUNET_MessageHeader * msgheader;
1310   struct ieee80211_frame * ieeewlanheader;
1311   struct Radiotap_Send * radioHeader;
1312   struct FragmentationAckHeader * msgheader2;
1313
1314   GNUNET_assert(sizeof(struct FragmentationAckHeader) <= WLAN_MTU);
1315
1316   size = sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_Send)
1317       + sizeof(struct ieee80211_frame) + sizeof(struct FragmentationAckHeader);
1318
1319 #if DEBUG_wlan
1320   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1321       "Sending ack for message_id %u with fragment field %u, size %u\n",
1322       ack->message_id, ack->fragments_field, size
1323       - sizeof(struct Radiotap_Send));
1324 #endif
1325
1326   msgheader = GNUNET_malloc(size);
1327   msgheader->size = htons(size);
1328   msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1329
1330   radioHeader = (struct Radiotap_Send*) &msgheader[1];
1331   getRadiotapHeader(plugin, ack->session, radioHeader);
1332   ieeewlanheader = (struct ieee80211_frame*) &radioHeader[1];
1333   getWlanHeader(ieeewlanheader, &ack->session->addr, plugin, size);
1334
1335   msgheader2 = (struct FragmentationAckHeader*) &ieeewlanheader[1];
1336   msgheader2->header.size = htons(sizeof(struct FragmentationAckHeader));
1337   msgheader2->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK);
1338   msgheader2->message_id = htonl(ack->message_id);
1339   msgheader2->fragment_field = GNUNET_htonll(ack->fragments_field);
1340
1341   bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1342   if (bytes == GNUNET_SYSERR)
1343     {
1344       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1345           _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1346           errno, strerror(errno));
1347
1348     }
1349   GNUNET_assert(bytes != GNUNET_SYSERR);
1350   GNUNET_assert(bytes == size);
1351   GNUNET_free(msgheader);
1352   set_next_send(plugin);
1353 }
1354
1355 //TODO DOXIGEN
1356 static void
1357 finish_sending(void *cls, 
1358                const struct GNUNET_SCHEDULER_TaskContext *tc)
1359 {
1360   struct Finish_send * finish = cls;
1361   struct Plugin * plugin;
1362   ssize_t bytes;
1363
1364   plugin = finish->plugin;
1365   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1366
1367   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1368     {
1369       GNUNET_free (finish->msgstart);
1370       GNUNET_free (finish);
1371       return;
1372     }
1373   bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle,
1374                                   finish->msgheader, 
1375                                   finish->size);
1376   GNUNET_assert (bytes != GNUNET_SYSERR);
1377
1378   if (bytes != finish->size)
1379     {
1380       finish->msgheader = finish->msgheader + bytes;
1381       finish->size = finish->size - bytes;
1382       plugin->server_write_task 
1383         = GNUNET_SCHEDULER_add_write_file(GNUNET_TIME_UNIT_FOREVER_REL,
1384                                           plugin->server_stdin_handle,
1385                                           &finish_sending, finish);
1386     }
1387   else
1388     {
1389       GNUNET_free(finish->msgstart);
1390       GNUNET_free(finish);
1391       set_next_send(plugin);
1392     }
1393 }
1394
1395 /**
1396  * Function called when wlan helper is ready to get some data
1397  *
1398  * @param cls closure
1399  * @param tc GNUNET_SCHEDULER_TaskContext
1400  */
1401 static void
1402 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1403 {
1404   struct Plugin * plugin = cls;
1405
1406   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1407   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1408     return;
1409
1410   struct Session * session;
1411   struct FragmentMessage * fm;
1412   struct ieee80211_frame * ieeewlanheader;
1413   struct Radiotap_Send * radioHeader;
1414   struct GNUNET_MessageHeader * msgheader;
1415   struct FragmentationHeader fragheader;
1416   struct FragmentationHeader * fragheaderptr;
1417   struct Finish_send * finish;
1418   struct AckSendQueue * ack;
1419   uint16_t size;
1420   ssize_t bytes;
1421   const char * copystart;
1422   uint16_t copysize;
1423   uint copyoffset;
1424   struct GNUNET_TIME_Absolute next_send;
1425
1426   if (plugin->ack_send_queue_head != NULL)
1427     {
1428       ack = plugin->ack_send_queue_head;
1429       GNUNET_CONTAINER_DLL_remove(plugin->ack_send_queue_head,
1430           plugin->ack_send_queue_tail, ack);
1431       send_ack(plugin, ack);
1432       GNUNET_free(ack);
1433       return;
1434     }
1435
1436   //test if a "hello-beacon" has to be send
1437   if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1438     {
1439       send_hello_beacon(plugin);
1440       return;
1441     }
1442
1443   fm = GNUNET_CONTAINER_heap_peek(plugin->pending_Fragment_Messages);
1444
1445   if (fm != NULL)
1446     {
1447       session = fm->session;
1448       GNUNET_assert(session != NULL);
1449
1450       // test if message timed out
1451       if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0)
1452         {
1453 #if DEBUG_wlan
1454           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "message timeout\n");
1455 #endif
1456
1457           free_fragment_message(plugin, fm);
1458           check_fragment_queue(plugin);
1459
1460         }
1461       else
1462         {
1463
1464           //if (fm->message_size > WLAN_MTU)
1465           // {
1466           size = sizeof(struct FragmentationHeader);
1467
1468           set_next_message_fragment_pos(plugin, fm);
1469
1470           copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader))
1471               * fm->message_pos;
1472
1473           fragheader.fragment_off_or_num = htons(fm->message_pos);
1474           fragheader.message_id = htonl(fm->message_id_out);
1475           copystart = fm->msg + copyoffset;
1476           copysize = GNUNET_MIN(fm->message_size - copyoffset,
1477               WLAN_MTU - sizeof(struct FragmentationHeader));
1478
1479 #if DEBUG_wlan
1480           GNUNET_log(
1481               GNUNET_ERROR_TYPE_DEBUG,
1482               "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u, offset %u, time until timeout %u\n",
1483               fm->message_id_out, fm->message_pos, copysize
1484               + sizeof(struct FragmentationHeader), copyoffset,
1485               GNUNET_TIME_absolute_get_remaining(fm->timeout));
1486 #endif
1487
1488           if (copyoffset >= fm->message_size)
1489             {
1490               GNUNET_log(
1491                   GNUNET_ERROR_TYPE_ERROR,
1492                   "offset in message for fragment too large, offset %u, size %u, max size %u, copysize %u, message_pos %u,\n",
1493                   copyoffset, fm->message_size, WLAN_MTU
1494                       - sizeof(struct FragmentationHeader), copysize,
1495                   fm->message_pos);
1496             }
1497           GNUNET_assert(copyoffset < fm->message_size);
1498
1499           fragheader.header.size = htons(copysize
1500               + sizeof(struct FragmentationHeader));
1501           fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1502
1503           size += copysize;
1504           size += sizeof(struct Radiotap_Send) + sizeof(struct ieee80211_frame)
1505               + sizeof(struct GNUNET_MessageHeader);
1506           msgheader = GNUNET_malloc(size);
1507           msgheader->size = htons(size);
1508           msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1509
1510           radioHeader = (struct Radiotap_Send*) &msgheader[1];
1511           getRadiotapHeader(plugin, session, radioHeader);
1512
1513           ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1514           getWlanHeader(ieeewlanheader, &(fm->session->addr), plugin, size);
1515
1516           //could be faster if content is just send and not copyed before
1517           //fragmentheader is needed
1518           fragheader.message_crc = htons(getcrc16(copystart, copysize));
1519           memcpy(&ieeewlanheader[1], &fragheader,
1520               sizeof(struct FragmentationHeader));
1521           fragheaderptr = (struct FragmentationHeader *) &ieeewlanheader[1];
1522           memcpy(&fragheaderptr[1], copystart, copysize);
1523
1524           bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle,
1525               msgheader, size);
1526           if (bytes == GNUNET_SYSERR)
1527             {
1528               GNUNET_log(
1529                   GNUNET_ERROR_TYPE_ERROR,
1530                   _("Error writing to wlan healper. errno == %d, ERROR: %s\n"),
1531                   errno, strerror(errno));
1532
1533             }
1534           GNUNET_assert(bytes != GNUNET_SYSERR);
1535
1536           //check if this was the last fragment of this message, if true then queue at the end of the list
1537           if (copysize + copyoffset >= fm->message_size)
1538             {
1539               GNUNET_assert(copysize + copyoffset == fm->message_size);
1540
1541               GNUNET_CONTAINER_heap_update_cost(
1542                   plugin->pending_Fragment_Messages, fm->node, MIN(
1543                       fm->timeout.abs_value, fm->next_ack.abs_value));
1544               // if fragments have opimized timeouts
1545               //sort_fragment_into_queue(plugin,fm);
1546
1547
1548 #if DEBUG_wlan_retransmission
1549               GNUNET_log(
1550                   GNUNET_ERROR_TYPE_DEBUG,
1551                   "Finished sending all fragments waiting for acks; message_id %u; message_id %u; fragment number %i, size: %u, time until timeout %u\n",
1552                   fm->message_id_out, fm->message_id_out, fm->message_pos,
1553                   fm->message_size, GNUNET_TIME_absolute_get_remaining(
1554                       fm->timeout));
1555 #endif
1556             }
1557           else
1558             {
1559               GNUNET_CONTAINER_heap_update_cost(
1560                   plugin->pending_Fragment_Messages, fm->node,
1561                   GNUNET_TIME_absolute_get().abs_value);
1562             }
1563
1564           if (bytes != size)
1565             {
1566               finish = GNUNET_malloc(sizeof( struct Finish_send));
1567               finish->plugin = plugin;
1568               finish->msgheader = (char *) msgheader + bytes;
1569               finish->size = size - bytes;
1570               finish->msgstart = msgheader;
1571               finish ->next_send = next_send;
1572
1573               GNUNET_assert(plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
1574
1575               plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
1576                   GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
1577                   &finish_sending, finish);
1578
1579             }
1580           else
1581             {
1582               GNUNET_free(msgheader);
1583               set_next_send(plugin);
1584             }
1585
1586         }
1587       return;
1588     }
1589
1590   GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1591       "do_transmit did nothing, should not happen!\n");
1592 }
1593
1594 /**
1595  * Another peer has suggested an address for this
1596  * peer and transport plugin.  Check that this could be a valid
1597  * address.  If so, consider adding it to the list
1598  * of addresses.
1599  *
1600  * @param cls closure
1601  * @param addr pointer to the address
1602  * @param addrlen length of addr
1603  * @return GNUNET_OK if this is a plausible address for this peer
1604  *         and transport
1605  */
1606 static int
1607 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen)
1608 {
1609   //struct Plugin *plugin = cls;
1610
1611   /* check if the address is plausible; if so,
1612    add it to our list! */
1613
1614   GNUNET_assert(cls !=NULL);
1615   //FIXME mitm is not checked
1616   //Mac Address has 6 bytes
1617   if (addrlen == 6)
1618     {
1619       /* TODO check for bad addresses like multicast, broadcast, etc */
1620       return GNUNET_OK;
1621     }
1622
1623   return GNUNET_SYSERR;
1624 }
1625
1626 /**
1627  * Function that can be used by the transport service to transmit
1628  * a message using the plugin.
1629  *
1630  * @param cls closure
1631  * @param target who should receive this message
1632  * @param priority how important is the message
1633  * @param msgbuf the message to transmit
1634  * @param msgbuf_size number of bytes in 'msgbuf'
1635  * @param timeout when should we time out
1636  * @param session which session must be used (or NULL for "any")
1637  * @param addr the address to use (can be NULL if the plugin
1638  *                is "on its own" (i.e. re-use existing TCP connection))
1639  * @param addrlen length of the address in bytes
1640  * @param force_address GNUNET_YES if the plugin MUST use the given address,
1641  *                otherwise the plugin may use other addresses or
1642  *                existing connections (if available)
1643  * @param cont continuation to call once the message has
1644  *        been transmitted (or if the transport is ready
1645  *        for the next transmission call; or if the
1646  *        peer disconnected...)
1647  * @param cont_cls closure for cont
1648  * @return number of bytes used (on the physical network, with overheads);
1649  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1650  *         and does NOT mean that the message was not transmitted (DV)
1651  */
1652 static ssize_t
1653 wlan_plugin_send(void *cls, const struct GNUNET_PeerIdentity * target,
1654     const char *msgbuf, size_t msgbuf_size, unsigned int priority,
1655     struct GNUNET_TIME_Relative timeout, struct Session *session,
1656     const void *addr, size_t addrlen, int force_address,
1657     GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
1658 {
1659   struct Plugin * plugin = cls;
1660   struct PendingMessage * newmsg;
1661   struct WlanHeader * wlanheader;
1662
1663   //check if msglen > 0
1664   GNUNET_assert(msgbuf_size > 0);
1665
1666   //get session if needed
1667   if (session == NULL)
1668     {
1669       if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1670         {
1671           session = get_session(plugin, addr);
1672         }
1673       else
1674         {
1675           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1676               _("Wlan Address len %d is wrong\n"), addrlen);
1677           return -1;
1678         }
1679     }
1680
1681   //TODO target "problem" not solved
1682   //if (session->target != NULL){
1683   //  GNUNET_assert(session->target == *target);
1684   //} else {
1685   session->target = *target;
1686   //}
1687
1688
1689   //queue message:
1690
1691   //queue message in session
1692   //test if there is no other message in the "queue"
1693   //FIXME: to many send requests
1694   //GNUNET_assert (session->pending_message == NULL);
1695   if (session->pending_message != NULL)
1696     {
1697       newmsg = session->pending_message;
1698       GNUNET_log(
1699           GNUNET_ERROR_TYPE_ERROR,
1700           "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",
1701           GNUNET_TIME_absolute_get_remaining(newmsg->timeout).rel_value,
1702           session->fragment_messages_out_count);
1703       if (session->pending_message2 != NULL)
1704         {
1705           GNUNET_log(
1706               GNUNET_ERROR_TYPE_ERROR,
1707               "wlan_plugin_send: two pending messages are already in the queue for this client\n");
1708           return -1;
1709         }
1710     }
1711
1712   newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1713   (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1714   wlanheader = (struct WlanHeader *) newmsg->msg;
1715   //copy msg to buffer, not fragmented / segmented yet, but with message header
1716   wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1717   wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1718   memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1719   wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1720   memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1721   newmsg->transmit_cont = cont;
1722   newmsg->transmit_cont_cls = cont_cls;
1723   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1724
1725   newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
1726
1727   newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1728
1729   if (session->pending_message == NULL)
1730     {
1731       session->pending_message = newmsg;
1732     }
1733   else
1734     {
1735       session->pending_message2 = newmsg;
1736     }
1737
1738 #if DEBUG_wlan
1739   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1740       "New message for %p with size (incl wlan header) %u added\n", session,
1741       newmsg->message_size);
1742 #endif
1743
1744   //queue session
1745   queue_session(plugin, session);
1746
1747   check_fragment_queue(plugin);
1748   //FIXME not the correct size
1749   return msgbuf_size;
1750
1751 }
1752
1753 /**
1754  * Iterate over the fragment messages of the given session.
1755  *
1756  * @param cls argument to give to iterator
1757  * @param node node to iterate over
1758  * @param element value stored at the node
1759  * @param cost cost associated with the node
1760  * @return GNUNET_YES if we should continue to iterate,
1761  *         GNUNET_NO if not.
1762  */
1763 static int
1764 free_fragment_message_from_session(void *cls,
1765     struct GNUNET_CONTAINER_HeapNode *node, void *element,
1766     GNUNET_CONTAINER_HeapCostType cost)
1767 {
1768   struct Plugin_Session_pair * pair = (struct Plugin_Session_pair *) cls;
1769   struct FragmentMessage * fm = (struct FragmentMessage*) element;
1770
1771   if (fm->session == pair->session)
1772     {
1773
1774       free_fragment_message(pair->plugin, fm);
1775     }
1776   return GNUNET_YES;
1777
1778 }
1779
1780 /**
1781  * Search for fragment message with given id and session
1782  *
1783  * @param cls argument to give to iterator
1784  * @param node node to iterate over
1785  * @param element value stored at the node
1786  * @param cost cost associated with the node
1787  * @return GNUNET_YES if we should continue to iterate,
1788  *         GNUNET_NO if not.
1789  */
1790 static int
1791 search_fragment_message_from_session_and_id(void *cls,
1792     struct GNUNET_CONTAINER_HeapNode *node, void *element,
1793     GNUNET_CONTAINER_HeapCostType cost)
1794 {
1795   struct Session_id_fragment_triple * triple =
1796       (struct Session_id_fragment_triple *) cls;
1797   struct FragmentMessage * fm = (struct FragmentMessage*) element;
1798
1799   if ((fm->session == triple->session) && (fm->message_id_out
1800       == triple->message_id))
1801     {
1802       triple->fm = fm;
1803       return GNUNET_NO;
1804     }
1805   return GNUNET_YES;
1806
1807 }
1808
1809 /**
1810  * function to get the message in the fragement queue (out) of a session with a specific id
1811  * @param session pointer to the session
1812  * @param message_id id of the message
1813  * @return pointer to the struct FragmentMessage
1814  */
1815 static struct FragmentMessage *
1816 get_fragment_message_from_session_and_id(struct Plugin * plugin,
1817     struct Session * session, uint32_t message_id)
1818 {
1819   struct Session_id_fragment_triple triple;
1820   triple.session = session;
1821   triple.message_id = message_id;
1822   GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1823       &search_fragment_message_from_session_and_id, &triple);
1824   return triple.fm;
1825 }
1826
1827 /**
1828  * function to get the receive message of a session
1829  * @param plugin pointer to the plugin struct
1830  * @param session session this fragment belongs to
1831  */
1832 static struct Receive_Message_Queue *
1833 get_receive_message_from_session(struct Plugin * plugin,
1834     struct Session * session)
1835 {
1836   struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1837   while (rec_message != NULL)
1838     {
1839       if (rec_message->session == session)
1840         {
1841           return rec_message;
1842         }
1843       rec_message = rec_message->next;
1844     }
1845   return NULL;
1846 }
1847
1848 /**
1849  * Function to dispose the fragments received for a message and the message
1850  * @param plugin pointer to the plugin struct
1851  * @param rec_message pointer to the struct holding the message which should be freed
1852  */
1853 static void
1854 free_receive_message(struct Plugin* plugin,
1855     struct Receive_Message_Queue * rx_message)
1856 {
1857   GNUNET_assert(rx_message !=NULL);
1858   struct Receive_Fragment_Queue * rec_queue = rx_message->frag_head;
1859   struct Receive_Fragment_Queue * rec_queue2;
1860
1861   while (rec_queue != NULL)
1862     {
1863       rec_queue2 = rec_queue;
1864       rec_queue = rec_queue->next;
1865       GNUNET_free(rec_queue2);
1866     }
1867
1868   GNUNET_CONTAINER_DLL_remove(plugin->receive_messages_head,plugin->receive_messages_teil, rx_message);
1869
1870   GNUNET_assert(plugin->pending_receive_messages > 0);
1871   GNUNET_assert(rx_message->session->fragment_messages_in_count > 0);
1872
1873   plugin->pending_receive_messages--;
1874   rx_message->session->fragment_messages_in_count--;
1875   GNUNET_free(rx_message);
1876 }
1877
1878 /**
1879  * function to get the receive message of a session
1880  * @param plugin pointer to the plugin struct
1881  * @param session session this fragment belongs to
1882  */
1883 static void
1884 check_receive_message_timeouts(struct Plugin * plugin, struct Session * session)
1885 {
1886   struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
1887   while (rec_message != NULL)
1888     {
1889       if (GNUNET_TIME_absolute_get_remaining(rec_message->timeout).rel_value
1890           == 0)
1891         {
1892           free_receive_message(plugin, rec_message);
1893         }
1894       rec_message = rec_message->next;
1895     }
1896
1897 }
1898
1899 //TODO DOXIGEN
1900 static void
1901 free_session(struct Plugin * plugin, struct Sessionqueue * queue)
1902 {
1903   struct Sessionqueue * pendingsession;
1904   struct Sessionqueue * pendingsession_tmp;
1905   struct PendingMessage * pm;
1906   struct Receive_Message_Queue * receive_queue;
1907   struct Plugin_Session_pair pair;
1908   int check = 0;
1909
1910   GNUNET_assert(queue != NULL);
1911   GNUNET_assert(queue->content != NULL);
1912
1913   //session found
1914   //is this session pending for send
1915   pendingsession = plugin->pending_Sessions_head;
1916   while (pendingsession != NULL)
1917     {
1918       pendingsession_tmp = pendingsession->next;
1919       if (pendingsession->content == queue->content)
1920         {
1921           plugin->pendingsessions--;
1922           GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1923                                        plugin->pending_Sessions_tail, 
1924                                        pendingsession);
1925           GNUNET_free(pendingsession);
1926
1927           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1928                      "Remove session %p from pending session queue\n", 
1929                      queue->content);
1930           GNUNET_assert (check == 0);
1931           check = 1;
1932         }
1933       pendingsession = pendingsession_tmp;
1934     }
1935
1936   //is something of this session in the fragment queue?
1937   pair.plugin = plugin;
1938   pair.session = queue->content;
1939   GNUNET_CONTAINER_heap_iterate(plugin->pending_Fragment_Messages,
1940       &free_fragment_message_from_session, &pair);
1941
1942   //dispose all received fragments
1943   receive_queue = get_receive_message_from_session(plugin, queue->content);
1944   while (receive_queue != NULL)
1945     {
1946       free_receive_message(plugin, receive_queue);
1947       receive_queue = get_receive_message_from_session(plugin, queue->content);
1948     }
1949
1950   // remove PendingMessage
1951   pm = queue->content->pending_message;
1952   if (pm != NULL)
1953     {
1954       GNUNET_free_non_null(pm->msg);
1955       GNUNET_free(pm);
1956     }
1957
1958   // remove PendingMessage
1959   pm = queue->content->pending_message2;
1960   if (pm != NULL)
1961     {
1962       GNUNET_free_non_null(pm->msg);
1963       GNUNET_free(pm);
1964     }
1965
1966   GNUNET_CONTAINER_DLL_remove(plugin->sessions, 
1967                               plugin->sessions_tail, 
1968                               queue);
1969   GNUNET_free(queue->content);
1970   GNUNET_free(queue);
1971   plugin->session_count--;
1972   check_fragment_queue(plugin);
1973 }
1974
1975 /**
1976  * Function that can be used to force the plugin to disconnect
1977  * from the given peer and cancel all previous transmissions
1978  * (and their continuation).
1979  *
1980  * @param cls closure
1981  * @param target peer from which to disconnect
1982  */
1983 static void
1984 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1985 {
1986   struct Plugin *plugin = cls;
1987   struct Sessionqueue * queue = plugin->sessions;
1988
1989   // just look at all the session for the needed one
1990   while (queue != NULL)
1991     {
1992       // content is never NULL
1993       GNUNET_assert (queue->content != NULL);
1994       if (memcmp(target, &(queue->content->target),
1995           sizeof(struct GNUNET_PeerIdentity)) == 0)
1996         {
1997           free_session(plugin, queue);
1998           return;
1999         }
2000       // try next
2001       queue = queue->next;
2002     }
2003 }
2004
2005 /**
2006  * Convert the transports address to a nice, human-readable
2007  * format.
2008  *
2009  * @param cls closure
2010  * @param type name of the transport that generated the address
2011  * @param addr one of the addresses of the host, NULL for the last address
2012  *        the specific address format depends on the transport
2013  * @param addrlen length of the address
2014  * @param numeric should (IP) addresses be displayed in numeric form?
2015  * @param timeout after how long should we give up?
2016  * @param asc function to call on each string
2017  * @param asc_cls closure for asc
2018  */
2019 static void
2020 wlan_plugin_address_pretty_printer(void *cls, const char *type,
2021     const void *addr, size_t addrlen, int numeric,
2022     struct GNUNET_TIME_Relative timeout,
2023     GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
2024 {
2025   char ret[92];
2026   const unsigned char * input;
2027
2028   //GNUNET_assert(cls !=NULL);
2029   if (addrlen != 6)
2030     {
2031       /* invalid address (MAC addresses have 6 bytes) */
2032       GNUNET_break (0);
2033       asc(asc_cls, NULL);
2034       return;
2035     }
2036   input = (const unsigned char*) addr;
2037   GNUNET_snprintf(ret, sizeof(ret),
2038       "%s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X", PROTOCOL_PREFIX,
2039       input[0], input[1], input[2], input[3], input[4], input[5]);
2040   asc(asc_cls, ret);
2041 }
2042
2043
2044 /**
2045  * Function to test if fragment number already exists in the fragments received
2046  *
2047  * @param rec_message message this fragment belongs to
2048  * @param fh Fragmentheader of the fragment
2049  * @return GNUNET_YES if fragment exists already, GNUNET_NO if it does not exists in the queue of the session
2050  */
2051 static int
2052 is_double_msg(struct Receive_Message_Queue * rx_msg,
2053     struct FragmentationHeader * fh)
2054 {
2055   //test if bitfield is okay
2056 #if DEBUG_wlan
2057   check_message_fragment_bitfield(rx_msg);
2058 #endif
2059
2060   return testBit((char *) &rx_msg->received_fragments, ntohs(
2061       fh->fragment_off_or_num));
2062
2063 }
2064
2065 /**
2066  * Function to insert a fragment in a queue of a message
2067  * @param session session the fragment belongs to
2068  * @param rec_queue fragment to add
2069  */
2070 static void
2071 insert_fragment_in_queue(struct Receive_Message_Queue * rx_message,
2072     struct Receive_Fragment_Queue * rx_frag)
2073 {
2074   GNUNET_assert(rx_message != NULL);
2075   GNUNET_assert(rx_frag != NULL);
2076
2077   struct Receive_Fragment_Queue * rx_frag2 = rx_message->frag_head;
2078   struct WlanHeader * wlanheader;
2079
2080   //this is the first fragment of the message (fragment id 0)
2081   if (rx_frag->num == 0)
2082     {
2083       wlanheader = (struct WlanHeader *) rx_frag->msg;
2084       rx_message->rec_size = ntohs(wlanheader->header.size);
2085     }
2086
2087   //sort into list
2088   while (rx_frag2 != NULL)
2089     {
2090       if (rx_frag2->num > rx_frag->num)
2091         {
2092           //next element number is grater than the current num
2093           GNUNET_CONTAINER_DLL_insert_before(rx_message->frag_head, rx_message->frag_tail, rx_frag2, rx_frag);
2094           setBit((char *) &rx_message->received_fragments, rx_frag->num);
2095           return;
2096         }
2097       rx_frag2 = rx_frag2->next;
2098     }
2099
2100   //no element has a grater number
2101   GNUNET_CONTAINER_DLL_insert_tail(rx_message->frag_head, rx_message->frag_tail, rx_frag);
2102
2103   setBit((char *) &rx_message->received_fragments, rx_frag->num);
2104 }
2105
2106 /**
2107  * handels the data after all fragments are put together
2108  * @param plugin
2109  * @param session_light
2110  * @param hdr pointer to the data
2111  */
2112 static void
2113 wlan_data_message_handler(void *cls, void *client,
2114     const struct GNUNET_MessageHeader *hdr)
2115 {
2116   struct Plugin * plugin = (struct Plugin*) cls;
2117   struct Session_light * session_light = (struct Session_light *) client;
2118   struct WlanHeader * wlanheader;
2119   struct Session * session;
2120   const char * tempmsg;
2121   const struct GNUNET_MessageHeader * temp_hdr;
2122   struct GNUNET_PeerIdentity tmptarget;
2123
2124   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2125     {
2126
2127 #if DEBUG_wlan
2128       GNUNET_log(
2129           GNUNET_ERROR_TYPE_DEBUG,
2130           "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2131           ntohs(hdr->size));
2132 #endif
2133
2134       if (ntohs(hdr->size) < sizeof(struct WlanHeader)
2135           + sizeof(struct GNUNET_MessageHeader))
2136         {
2137           //packet not big enought
2138           return;
2139         }
2140
2141       GNUNET_assert(session_light != NULL);
2142       if (session_light->session == NULL)
2143         {
2144           session_light->session = search_session(plugin, &session_light->addr);
2145         }
2146       session = session_light->session;
2147       wlanheader = (struct WlanHeader *) hdr;
2148
2149       tempmsg = (char*) &wlanheader[1];
2150       temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2151
2152       if (getcrc32(tempmsg, ntohs(wlanheader->header.size)) != ntohl(
2153           wlanheader->crc))
2154         {
2155           //wrong crc, dispose message
2156           GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2157               "Wlan message Header crc was wrong\n");
2158           return;
2159         }
2160
2161       //if not in session list
2162       if (session == NULL)
2163         {
2164 #if DEBUG_wlan
2165           GNUNET_log(
2166               GNUNET_ERROR_TYPE_DEBUG,
2167               "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2168               ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2169               sizeof(struct WlanHeader));
2170 #endif
2171           //try if it is a hello message
2172           if (ntohs(wlanheader->header.size) >= ntohs(temp_hdr->size)
2173               + sizeof(struct WlanHeader))
2174             {
2175               if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2176                 {
2177                   if (GNUNET_HELLO_get_id(
2178                       (const struct GNUNET_HELLO_Message *) temp_hdr,
2179                       &tmptarget) == GNUNET_OK)
2180                     {
2181                       session = create_session(plugin, &session_light->addr);
2182                       session_light->session = session;
2183                       memcpy(&session->target, &tmptarget,
2184                           sizeof(struct GNUNET_PeerIdentity));
2185                     }
2186                   else
2187                     {
2188                       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2189                           "WLAN client not in session list and hello message not okay\n");
2190                       return;
2191                     }
2192
2193                 }
2194               else
2195                 {
2196                   GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2197                       "WLAN client not in session list and not a hello message\n");
2198                   return;
2199                 }
2200             }
2201           else
2202             {
2203               GNUNET_log(
2204                   GNUNET_ERROR_TYPE_WARNING,
2205                   "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2206                   ntohs(wlanheader->header.size), ntohs(temp_hdr->size),
2207                   sizeof(struct WlanHeader));
2208               return;
2209             }
2210         }
2211
2212       //"receive" the message
2213
2214
2215       GNUNET_SERVER_mst_receive(plugin->data_tokenizer, session,
2216           (const char *) temp_hdr,
2217           ntohs(hdr->size) - sizeof(struct WlanHeader), GNUNET_YES, GNUNET_NO);
2218
2219       return;
2220     }
2221   else
2222     {
2223       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2224           "wlan_data_message_handler got wrong message type\n");
2225       return;
2226     }
2227 }
2228
2229 /**
2230  * Function to check if all fragments of a message have been received
2231  * @param plugin the plugin handle
2232  * @param session_light information of the message sender
2233  * @param session session the message belongs to
2234  * @param rec_message pointer to the message that should be checked
2235  */
2236
2237 static void
2238 check_rx_finished_msg(struct Plugin* plugin,
2239     struct Session_light * session_light, struct Session * session,
2240     struct Receive_Message_Queue * rx_message)
2241 {
2242   GNUNET_assert(rx_message !=NULL);
2243
2244   struct Receive_Fragment_Queue * rx_frag = rx_message->frag_head;
2245   int packetsize = rx_message->rec_size;
2246   int sum;
2247   //TODO CLEANUP
2248   //int aktnum;
2249   uint64_t bitfield = 0;
2250   //char * msg;
2251
2252   //check if first fragment is present
2253   if (packetsize == MESSAGE_LENGHT_UNKNOWN)
2254     {
2255       return;
2256     }
2257   // test if message has at least the size of the WlanHeader and a GNUNET_MessageHeader
2258
2259   else if (packetsize < sizeof(struct WlanHeader)
2260       + sizeof(struct GNUNET_MessageHeader))
2261     {
2262 #if DEBUG_wlan
2263       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Message not big enough\n");
2264 #endif
2265       free_receive_message(plugin, rx_message);
2266       return;
2267     }
2268
2269 #if DEBUG_wlan
2270   check_message_fragment_bitfield(rx_message);
2271 #endif
2272
2273   //  if (rx_message->frag_tail->num == ffsl(rx_message->received_fragments))
2274   //    {
2275   bitfield = ~bitfield;
2276   bitfield = bitfield >> (63 - rx_message->frag_tail->num);
2277   if (rx_message->received_fragments == bitfield)
2278     {
2279       sum = 0;
2280       while (rx_frag != NULL)
2281         {
2282           sum += rx_frag->size;
2283           rx_frag = rx_frag->next;
2284         }
2285       //sum should always be smaller or equal of
2286       GNUNET_assert(sum <= packetsize);
2287       if (sum == packetsize)
2288         {
2289
2290 #if DEBUG_wlan
2291           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2292               "check_rec_finished_msg: A message for %p is complete\n", session);
2293 #endif
2294
2295           //TODO cleanup
2296
2297           //copy fragments together
2298           //msg = GNUNET_malloc(packetsize);
2299           rx_frag = rx_message->frag_head;
2300           //aktnum = 0;
2301           /*while (rx_frag != NULL)
2302            {
2303            //TODO SAVE SOME COPY OPS AND CHECK CRC WITHOUT COPY
2304            memcpy(msg + aktnum, rx_frag->msg, rx_frag->size);
2305            aktnum += rx_frag->size;
2306            rx_frag = rx_frag->next;
2307            }*/
2308
2309           while (rx_frag != NULL)
2310             {
2311               if (rx_frag->next != NULL)
2312                 {
2313                   GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2314                       session_light, rx_frag->msg, rx_frag->size, GNUNET_NO,
2315                       GNUNET_NO);
2316                 }
2317               else
2318                 {
2319                   //if it is the last fragment just kill all leftover
2320                   GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer,
2321                       session_light, rx_frag->msg, rx_frag->size, GNUNET_YES,
2322                       GNUNET_NO);
2323                 }
2324               rx_frag = rx_frag->next;
2325             }
2326           free_receive_message(plugin, rx_message);
2327           //call wlan_process_helper to process the message
2328           //wlan_data_message_handler(plugin, session_light,
2329           //   (struct GNUNET_MessageHeader*) msg);
2330           //wlan_data_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
2331
2332           //GNUNET_free(msg);
2333         }
2334     }
2335   //    }
2336 }
2337
2338 //TODO DOXIGEN
2339 static void
2340 process_data(void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2341 {
2342
2343   GNUNET_assert(client != NULL);
2344   GNUNET_assert(cls != NULL);
2345   struct Session * session = (struct Session *) client;
2346   struct Plugin * plugin = (struct Plugin *) cls;
2347
2348   struct GNUNET_TRANSPORT_ATS_Information distance[2];
2349   distance[0].type = htonl(GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
2350   distance[0].value = htonl(1);
2351   distance[1].type = htonl(GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
2352   distance[1].value = htonl(0);
2353
2354 #if DEBUG_wlan
2355   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2356       "Calling plugin->env->receive for session %p; %s; size: %u\n", session,
2357       wlan_plugin_address_to_string(NULL, session->addr.mac, 6), htons(
2358           hdr->size));
2359 #endif
2360
2361   plugin->env->receive(plugin->env->cls, &(session->target), hdr,
2362       (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2, session,
2363       (const char*) &session->addr, sizeof(session->addr));
2364 }
2365
2366 /**
2367  * function to add an ack to send it for a received fragment
2368  * @param plugin pointer to the global plugin structure
2369  * @param session pointer to the session this ack belongs to
2370  * @param bitfield bitfield to send
2371  * @param fh pointer to the fragmentation header which we would like to acknolage
2372  */
2373
2374 void
2375 add_ack_for_send(struct Plugin * plugin, struct Session * session,
2376     uint64_t bitfield, struct FragmentationHeader * fh)
2377 {
2378   struct AckSendQueue * ack;
2379
2380   GNUNET_assert(plugin != NULL);
2381   GNUNET_assert(session != NULL);
2382   GNUNET_assert(fh != NULL);
2383
2384   ack = GNUNET_malloc(sizeof(struct AckSendQueue));
2385   ack->fragments_field = bitfield;
2386   ack->message_id = ntohl(fh->message_id);
2387   ack->session = session;
2388
2389   GNUNET_CONTAINER_DLL_insert_tail(plugin->ack_send_queue_head,
2390       plugin->ack_send_queue_tail, ack);
2391
2392 }
2393
2394 /**
2395  * function to get the receive message from the message id and the session
2396  * @param plugin pointer to the plugin struct
2397  * @param session session this fragment belongs to
2398  * @param message_id id of the message
2399  */
2400
2401 struct Receive_Message_Queue *
2402 get_receive_message(struct Plugin * plugin, struct Session * session,
2403     uint32_t message_id)
2404 {
2405   struct Receive_Message_Queue * rec_message = plugin->receive_messages_head;
2406   while (rec_message != NULL)
2407     {
2408       if ((rec_message->message_id_in == message_id) && (rec_message->session
2409           == session))
2410         {
2411           return rec_message;
2412         }
2413       rec_message = rec_message->next;
2414     }
2415   return NULL;
2416 }
2417
2418 /**
2419  * function to insert a received fragment into the right fragment queue of the right message
2420  * @param plugin pointer to the plugin struct
2421  * @param session_light pointer to the session_light struct of this message
2422  * @param session session this fragment belongs to
2423  * @param fh pointer to the header of the fragment
2424  * @return new fragment bitfield for the message
2425  */
2426
2427 uint64_t
2428 insert_fragment_in_in_message_queue(struct Plugin * plugin,
2429     struct Session_light * session_light, struct Session * session,
2430     struct FragmentationHeader * fh, const struct Radiotap_rx * rxinfo)
2431 {
2432   struct Receive_Fragment_Queue * rx_frag = NULL;
2433   struct Receive_Message_Queue * rx_message;
2434   const char * tempmsg = (char*) &fh[1];
2435   uint64_t retval = 0;
2436
2437   //TODO fragments do not timeout
2438   //check if message_id is right or it is a new msg
2439   GNUNET_assert(fh != NULL);
2440
2441   rx_message = get_receive_message(plugin, session, ntohl(fh->message_id));
2442
2443   if (rx_message == NULL)
2444     {
2445       if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2446         {
2447           check_receive_message_timeouts(plugin, session);
2448         }
2449
2450       if (session->fragment_messages_in_count < MESSAGES_IN_QUEUE_PER_SESSION)
2451         {
2452
2453           //new message incoming
2454           rx_message = GNUNET_malloc(sizeof (struct Receive_Message_Queue));
2455           rx_message->message_id_in = ntohl(fh->message_id);
2456           rx_message->rec_size = MESSAGE_LENGHT_UNKNOWN;
2457           rx_message->session = session;
2458           rx_message->received_fragments = 0;
2459
2460           GNUNET_CONTAINER_DLL_insert(plugin->receive_messages_head, plugin->receive_messages_teil, rx_message);
2461
2462           session->fragment_messages_in_count++;
2463           plugin->pending_receive_messages++;
2464
2465 #if DEBUG_wlan
2466           GNUNET_log(
2467               GNUNET_ERROR_TYPE_DEBUG,
2468               "New fragmented message started: message id %u, messages in for this session %u, messages in %u\n",
2469               rx_message->message_id_in, session->fragment_messages_in_count,
2470               plugin->pending_receive_messages);
2471 #endif
2472         }
2473       else
2474         {
2475
2476           GNUNET_log(
2477               GNUNET_ERROR_TYPE_INFO,
2478               "WLAN fragment message_id and session message_id do not exist, max MESSAGES_IN_QUEUE_PER_SESSION reached, akt in message_id %u\n",
2479               get_receive_message_from_session(plugin, session)->message_id_in);
2480           setBit((char *) &retval, ntohs(fh->fragment_off_or_num));
2481           return retval;
2482         }
2483     }
2484
2485   //reset timeout
2486   rx_message->timeout = GNUNET_TIME_absolute_add(
2487   GNUNET_TIME_absolute_get(),
2488       MESSAGE_IN_TIMEOUT);
2489
2490   if (is_double_msg(rx_message, fh) != GNUNET_YES)
2491     {
2492
2493       //report size
2494       rx_frag = GNUNET_malloc(sizeof (struct Receive_Fragment_Queue) +
2495           ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
2496       rx_frag->size = ntohs(fh->header.size)
2497           - sizeof(struct FragmentationHeader);
2498       rx_frag->num = ntohs(fh->fragment_off_or_num);
2499       rx_frag->msg = (char*) &(rx_frag[1]);
2500       //copy msg to buffer
2501       memcpy((char *) rx_frag->msg, tempmsg, rx_frag->size);
2502       memcpy((char *) &(rx_frag->rxinfo), rxinfo, sizeof(rxinfo));
2503       insert_fragment_in_queue(rx_message, rx_frag);
2504       //save bitfield
2505       retval = rx_message->received_fragments;
2506
2507 #if DEBUG_wlan
2508       GNUNET_log(
2509           GNUNET_ERROR_TYPE_DEBUG,
2510           "New fragment:  size %u, fragsize %u, message id %u, bitfield %X, session %u\n",
2511           rx_message->rec_size, rx_frag->size, rx_message->message_id_in,
2512           rx_message->received_fragments, session);
2513 #endif
2514
2515       check_rx_finished_msg(plugin, session_light, session, rx_message);
2516     }
2517   else
2518     {
2519       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment is a clone\n");
2520       retval = rx_message->received_fragments;
2521
2522     }
2523   return retval;
2524
2525 }
2526
2527 /**
2528  * Function used for to process the data received from the wlan interface
2529  *
2530  * @param cls the plugin handle
2531  * @param session_light FIXME: document
2532  * @param hdr hdr of the GNUNET_MessageHeader
2533  */
2534 static void
2535 wlan_data_helper(void *cls, struct Session_light * session_light,
2536     const struct GNUNET_MessageHeader * hdr, const struct Radiotap_rx * rxinfo)
2537 {
2538   struct Plugin *plugin = cls;
2539   struct Session * session;
2540
2541   struct FragmentationHeader * fh;
2542   struct FragmentationAckHeader * fah;
2543   struct FragmentMessage * fm;
2544
2545   const char * tempmsg;
2546
2547   uint64_t fragment_bitfield = 0;
2548
2549   //ADVERTISEMENT
2550   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
2551     {
2552
2553       //TODO better DOS protection, error handling
2554       //TODO test first than create session
2555       GNUNET_assert(session_light != NULL);
2556
2557 #if DEBUG_wlan
2558       GNUNET_log(
2559           GNUNET_ERROR_TYPE_DEBUG,
2560           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT size: %u; %s\n",
2561           ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2562               session_light->addr.mac, 6));
2563 #endif
2564
2565       if (session_light->session == NULL)
2566         {
2567           session_light->session = get_session(plugin, &session_light->addr);
2568         }
2569       GNUNET_assert(GNUNET_HELLO_get_id(
2570               (const struct GNUNET_HELLO_Message *) &hdr[1],
2571               &(session_light->session->target) ) != GNUNET_SYSERR);
2572
2573     }
2574
2575   //FRAGMENT
2576
2577   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
2578     {
2579
2580       GNUNET_assert(session_light != NULL);
2581       if (session_light->session == NULL)
2582         {
2583           session_light->session = search_session(plugin, &session_light->addr);
2584         }
2585       session = session_light->session;
2586
2587       fh = (struct FragmentationHeader *) hdr;
2588       tempmsg = (char*) &fh[1];
2589
2590 #if DEBUG_wlan
2591       GNUNET_log(
2592           GNUNET_ERROR_TYPE_DEBUG,
2593           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT with message_id %u with fragment number %i, size: %u; %s\n",
2594           ntohl(fh->message_id), ntohs(fh->fragment_off_or_num), ntohs(
2595               hdr->size), wlan_plugin_address_to_string(NULL,
2596               session_light->addr.mac, 6));
2597 #endif
2598
2599       if (getcrc16(tempmsg, ntohs(fh->header.size)) != ntohs(fh->message_crc))
2600         {
2601           //wrong crc, dispose message
2602           GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN fragment crc was wrong\n");
2603           return;
2604         }
2605
2606       //if in the session list
2607       if (session != NULL)
2608         {
2609           fragment_bitfield = insert_fragment_in_in_message_queue(plugin,
2610               session_light, session, fh, rxinfo);
2611         }
2612       else
2613         {
2614           // new session
2615           GNUNET_log(
2616               GNUNET_ERROR_TYPE_INFO,
2617               "WLAN client not in session list, fragment num %u, message id %u\n",
2618               ntohs(fh->fragment_off_or_num), ntohl(fh->message_id));
2619
2620           GNUNET_SERVER_mst_receive(plugin->fragment_tokenizer, session_light,
2621               tempmsg, ntohs(hdr->size) - sizeof(struct FragmentationHeader),
2622               GNUNET_YES, GNUNET_NO);
2623           //wlan_data_message_handler(plugin, session_light,
2624           //    (struct GNUNET_MessageHeader *) tempmsg);
2625           session = session_light->session;
2626           //test if a session was created
2627           if (session == NULL)
2628             {
2629               return;
2630             }
2631           setBit((char *) &fragment_bitfield, ntohs(fh->fragment_off_or_num));
2632         }
2633
2634       add_ack_for_send(plugin, session, fragment_bitfield, fh);
2635       set_next_send(plugin);
2636
2637     }
2638
2639   //ACK
2640
2641   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
2642     {
2643
2644 #if DEBUG_wlan
2645       GNUNET_log(
2646           GNUNET_ERROR_TYPE_DEBUG,
2647           "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK size: %u; %s\n",
2648           ntohs(hdr->size), wlan_plugin_address_to_string(NULL,
2649               session_light->addr.mac, 6));
2650 #endif
2651
2652       GNUNET_assert(session_light != NULL);
2653       if (session_light->session == NULL)
2654         {
2655           session_light->session = search_session(plugin, &session_light->addr);
2656           GNUNET_assert(session_light->session != NULL);
2657         }
2658       session = session_light->session;
2659       fah = (struct FragmentationAckHeader *) hdr;
2660       fm = get_fragment_message_from_session_and_id(plugin, session, ntohl(
2661           fah->message_id));
2662
2663       if (fm != NULL)
2664         {
2665
2666           fm->ack_bitfield = fm->ack_bitfield | GNUNET_ntohll(
2667               fah->fragment_field);
2668           fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
2669
2670 #if DEBUG_wlan_retransmission
2671           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got ack for: %u; %u\n",
2672               fm->message_id_out, fm->ack_bitfield);
2673 #endif
2674           check_finished_fragment(plugin, fm);
2675           set_next_send(plugin);
2676
2677         }
2678       else
2679         {
2680           GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2681               "WLAN fragment not in fragment list with id %u of ack\n", ntohl(
2682                   fah->message_id));
2683           return;
2684         }
2685
2686     }
2687   else
2688     {
2689       // TODO Wrong data?
2690       GNUNET_log(
2691           GNUNET_ERROR_TYPE_INFO,
2692           "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2693           ntohs(hdr->type), ntohs(hdr->size));
2694       GNUNET_break(0);
2695       return;
2696     }
2697
2698 #if 0
2699   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2700       "Helper finished\n");
2701 #endif
2702
2703 }
2704
2705 //TODO DOXIGEN
2706 const char *
2707 macprinter(const u_int8_t * mac)
2708 {
2709   static char macstr[20];
2710
2711   GNUNET_snprintf(macstr, sizeof(macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2712       mac[2], mac[3], mac[4], mac[5]);
2713   return macstr;
2714 }
2715
2716 /**
2717  * Function used for to process the data from the suid process
2718  *
2719  * @param cls the plugin handle
2720  * @param client client that send the data (not used)
2721  * @param hdr header of the GNUNET_MessageHeader
2722  */
2723 static void
2724 wlan_process_helper(void *cls, void *client,
2725     const struct GNUNET_MessageHeader *hdr)
2726 {
2727   struct Plugin *plugin = cls;
2728   struct ieee80211_frame * wlanIeeeHeader = NULL;
2729   struct Session_light * session_light = NULL;
2730   struct Radiotap_rx * rxinfo;
2731   const struct GNUNET_MessageHeader * temp_hdr = NULL;
2732
2733   int datasize = 0;
2734   int pos;
2735
2736   switch (ntohs(hdr->type))
2737     {
2738   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
2739 #if DEBUG_wlan
2740     GNUNET_log(
2741         GNUNET_ERROR_TYPE_DEBUG,
2742         "Func wlan_process_helper got  GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
2743         ntohs(hdr->size));
2744 #endif
2745
2746     //call wlan_process_helper with the message inside, later with wlan: analyze signal
2747     if (ntohs(hdr->size) < sizeof(struct ieee80211_frame)
2748         + sizeof(struct GNUNET_MessageHeader) + sizeof(struct Radiotap_rx))
2749       {
2750 #if DEBUG_wlan
2751         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2752             "Size of packet is too small; size: %u min size: %u\n", ntohs(
2753                 hdr->size), sizeof(struct ieee80211_frame)
2754             + sizeof(struct GNUNET_MessageHeader));
2755 #endif
2756         //GNUNET_break (0);
2757         /* FIXME: restart SUID process */
2758         return;
2759       }
2760     rxinfo = (struct Radiotap_rx *) &hdr[1];
2761     wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
2762
2763     //process only if it is an broadcast or for this computer both with the gnunet bssid
2764
2765     //check for bssid
2766     if (memcmp(&(wlanIeeeHeader->i_addr3), &mac_bssid,
2767         sizeof(struct MacAddress)) == 0)
2768       {
2769         //check for broadcast or mac
2770         if (memcmp(&(wlanIeeeHeader->i_addr1), &bc_all_mac,
2771             sizeof(struct MacAddress) == 0) || memcmp(
2772             &(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
2773             sizeof(struct MacAddress)) == 0)
2774           {
2775
2776             // process the inner data
2777
2778
2779             datasize = ntohs(hdr->size) - sizeof(struct ieee80211_frame)
2780                 - sizeof(struct GNUNET_MessageHeader)
2781                 - sizeof(struct Radiotap_rx);
2782
2783             session_light = GNUNET_malloc(sizeof(struct Session_light));
2784             memcpy(&session_light->addr, &(wlanIeeeHeader->i_addr2),
2785                 sizeof(struct MacAddress));
2786             //session_light->session = search_session(plugin,session_light->addr);
2787
2788             pos = 0;
2789             while (pos < datasize)
2790               {
2791                 temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1]
2792                     + pos;
2793
2794                 wlan_data_helper(plugin, session_light, temp_hdr, rxinfo);
2795                 pos += ntohs(temp_hdr->size);
2796
2797               }
2798
2799             //clean up
2800             GNUNET_free(session_light);
2801           }
2802         else
2803           {
2804 #if DEBUG_wlan
2805             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2806                 "Func wlan_process_helper got wrong MAC: %s\n", macprinter(
2807                     wlanIeeeHeader->i_addr1));
2808 #endif
2809           }
2810       }
2811     else
2812       {
2813 #if DEBUG_wlan
2814         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2815             "Func wlan_process_helper got wrong BSSID: %s\n", macprinter(
2816                 wlanIeeeHeader->i_addr2));
2817 #endif
2818       }
2819     break;
2820   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
2821     //TODO more control messages
2822     //TODO use struct wlan_helper_control
2823     if (ntohs(hdr->size) != sizeof(struct Wlan_Helper_Control_Message))
2824       {
2825         GNUNET_break (0);
2826         /* FIXME: restart SUID process */
2827         return;
2828       }
2829     memcpy(&plugin->mac_address, &hdr[1], sizeof(struct MacAddress));
2830 #if DEBUG_wlan
2831     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2832         "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
2833         wlan_plugin_address_to_string(cls, &plugin->mac_address,
2834             sizeof(struct MacAddress)));
2835 #endif
2836     plugin->env->notify_address(plugin->env->cls, "wlan", &plugin->mac_address,
2837         sizeof(struct MacAddress), GNUNET_TIME_UNIT_FOREVER_REL);
2838     break;
2839   default:
2840     GNUNET_break (0);
2841     return;
2842     }
2843 }
2844
2845 /**
2846  * We have been notified that wlan-helper has written something to stdout.
2847  * Handle the output, then reschedule this function to be called again once
2848  * more is available.
2849  *
2850  * @param cls the plugin handle
2851  * @param tc the scheduling context
2852  */
2853 static void
2854 wlan_plugin_helper_read(void *cls,
2855     const struct GNUNET_SCHEDULER_TaskContext *tc)
2856 {
2857   struct Plugin *plugin = cls;
2858   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2859
2860   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2861     return;
2862
2863   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
2864   ssize_t bytes;
2865
2866   bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, mybuf,
2867       sizeof(mybuf));
2868   if (bytes <= 0)
2869     {
2870 #if DEBUG_wlan
2871       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2872           _("Finished reading from wlan-helper stdout with code: %d\n"),
2873           bytes);
2874 #endif
2875       return;
2876     }
2877   GNUNET_SERVER_mst_receive(plugin->suid_tokenizer, NULL, mybuf, bytes,
2878       GNUNET_NO, GNUNET_NO);
2879
2880   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2881   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2882       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2883       &wlan_plugin_helper_read, plugin);
2884 }
2885
2886 /**
2887  * Start the gnunet-wlan-helper process.
2888  *
2889  * @param plugin the transport plugin
2890  * @param testmode should we use the dummy driver for testing?
2891  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2892  */
2893 static int
2894 wlan_transport_start_wlan_helper(struct Plugin *plugin, int testmode)
2895 {
2896   const char * filename = "gnunet-transport-wlan-helper";
2897   plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
2898   if (plugin->server_stdout == NULL)
2899     return GNUNET_SYSERR;
2900
2901   plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
2902   if (plugin->server_stdin == NULL)
2903     return GNUNET_SYSERR;
2904
2905 #if DEBUG_wlan
2906   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2907       "Starting gnunet-wlan-helper process cmd: %s %s %i\n", filename,
2908       plugin->interface, testmode);
2909 #endif
2910   /* Start the server process */
2911
2912   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
2913       plugin->server_stdout, filename, filename, plugin->interface, ((testmode
2914           == 1) ? "1" : (testmode == 2) ? "2" : "0"), NULL);
2915   if (plugin->server_proc == NULL)
2916     {
2917 #if DEBUG_wlan
2918       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2919           "Failed to start gnunet-wlan-helper process\n");
2920 #endif
2921       return GNUNET_SYSERR;
2922     }
2923
2924   /* Close the write end of the read pipe */
2925   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
2926
2927   /* Close the read end of the write pipe */
2928   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
2929
2930   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
2931       GNUNET_DISK_PIPE_END_READ);
2932   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
2933       GNUNET_DISK_PIPE_END_WRITE);
2934
2935   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
2936
2937 #if DEBUG_wlan
2938   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2939       "Adding server_read_task for the wlan-helper\n");
2940 #endif
2941
2942   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
2943       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
2944       &wlan_plugin_helper_read, plugin);
2945
2946   return GNUNET_YES;
2947 }
2948
2949 /**
2950  * Exit point from the plugin.
2951  * @param cls pointer to the api struct
2952  */
2953
2954 //FIXME cleanup
2955 void *
2956 libgnunet_plugin_transport_wlan_done(void *cls)
2957 {
2958   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2959   struct Plugin *plugin = api->cls;
2960   struct Sessionqueue * queue = plugin->sessions;
2961   struct Sessionqueue * queue_next;
2962   struct FragmentMessage * fm;
2963
2964 #if DEBUG_wlan
2965   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2966       "libgnunet_plugin_transport_wlan_done started\n");
2967 #endif
2968
2969   GNUNET_assert (cls !=NULL);
2970   //free sessions
2971   while (queue != NULL)
2972     {
2973       queue_next = queue->next;
2974       free_session(plugin, queue);
2975       queue = queue_next;
2976
2977     }
2978   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
2979     {
2980       GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
2981       plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2982     }
2983   if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
2984     {
2985       GNUNET_SCHEDULER_cancel(plugin->server_write_task);
2986       plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2987     }
2988   if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
2989     {
2990       GNUNET_SCHEDULER_cancel(plugin->server_read_task);
2991       plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2992     }
2993
2994
2995   if (plugin->suid_tokenizer != NULL)
2996     GNUNET_SERVER_mst_destroy(plugin->suid_tokenizer);
2997
2998   if (plugin->data_tokenizer != NULL)
2999     GNUNET_SERVER_mst_destroy(plugin->data_tokenizer);
3000
3001   if (plugin->fragment_tokenizer != NULL)
3002     GNUNET_SERVER_mst_destroy(plugin->fragment_tokenizer);
3003
3004   fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3005       plugin->pending_Fragment_Messages);
3006
3007   while (fm != NULL)
3008     {
3009       free_fragment_message(plugin, fm);
3010       fm = (struct FragmentMessage *) GNUNET_CONTAINER_heap_peek(
3011           plugin->pending_Fragment_Messages);
3012     }
3013
3014   GNUNET_free_non_null(plugin->interface);
3015   GNUNET_CONTAINER_heap_destroy(plugin->pending_Fragment_Messages);
3016   GNUNET_free (plugin);
3017   GNUNET_free (api);
3018   return NULL;
3019 }
3020
3021 /**
3022  * Entry point for the plugin.
3023  *
3024  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3025  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3026  */
3027 void *
3028 libgnunet_plugin_transport_wlan_init(void *cls)
3029 {
3030   //struct GNUNET_SERVICE_Context *service;
3031   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3032   struct GNUNET_TRANSPORT_PluginFunctions *api;
3033   struct Plugin *plugin;
3034   static unsigned long long testmode = 0;
3035
3036   GNUNET_assert(cls !=NULL);
3037
3038   plugin = GNUNET_malloc (sizeof (struct Plugin));
3039   plugin->env = env;
3040   plugin->pendingsessions = 0;
3041   plugin->session_count = 0;
3042   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3043   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3044   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3045   plugin->pending_Fragment_Messages = GNUNET_CONTAINER_heap_create(
3046       GNUNET_CONTAINER_HEAP_ORDER_MIN);
3047
3048   plugin->suid_tokenizer = GNUNET_SERVER_mst_create(&wlan_process_helper,
3049       plugin);
3050
3051   plugin->data_tokenizer = GNUNET_SERVER_mst_create(&process_data, plugin);
3052   plugin->fragment_tokenizer = GNUNET_SERVER_mst_create(
3053       &wlan_data_message_handler, plugin);
3054
3055   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3056   //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3057
3058   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3059   api->cls = plugin;
3060   api->send = &wlan_plugin_send;
3061   api->disconnect = &wlan_plugin_disconnect;
3062   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3063   api->check_address = &wlan_plugin_address_suggested;
3064   api->address_to_string = &wlan_plugin_address_to_string;
3065
3066   //read config
3067
3068   if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "TESTMODE"))
3069     {
3070       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(env->cfg,
3071           "transport-wlan", "TESTMODE", &testmode))
3072         testmode = 0; //default value
3073     }
3074
3075   if (GNUNET_CONFIGURATION_have_value(env->cfg, "transport-wlan", "INTERFACE"))
3076     {
3077       if (GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-wlan",
3078           "INTERFACE", &(plugin->interface)) != GNUNET_YES)
3079         {
3080           libgnunet_plugin_transport_wlan_done(api);
3081           return NULL;
3082         }
3083     }
3084
3085   //start the plugin
3086   set_next_beacon_time(plugin);
3087
3088   wlan_transport_start_wlan_helper(plugin, testmode);
3089
3090 #if DEBUG_wlan
3091   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "wlan init finished\n");
3092 #endif
3093
3094   return api;
3095 }
3096
3097 /* end of plugin_transport_wlan.c */