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