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