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