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