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