removing fprintfs -- with bad %fmt statements giving warnings
[oweals/gnunet.git] / src / transport / plugin_transport_wlan.c
1 /*
2      This file is part of GNUnet
3      (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file transport/plugin_transport_wlan.c
23  * @brief transport plugin for wlan
24  * @author David Brodski
25  */
26
27 #include "platform.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_transport_plugin.h"
34 #include "plugin_transport_wlan.h"
35 #include "gnunet_common.h"
36 #include "gnunet_crypto_lib.h"
37
38 #define PROTOCOL_PREFIX "wlan"
39
40 /**
41  * Max size of packet from helper
42  */
43 #define WLAN_MTU 3000
44
45 /**
46  * Time until retransmission of a fragment in ms
47  */
48 #define FRAGMENT_TIMEOUT GNUNET_TIME_UNIT_SECONDS 
49
50 #define FRAGMENT_QUEUE_SIZE 10
51
52 #define DEBUG_wlan GNUNET_NO
53
54 #define MESSAGE_LENGHT_UNKNOWN -1
55 #define NO_MESSAGE_OR_MESSAGE_FINISHED -2
56
57
58 /**
59  * After how long do we expire an address that we
60  * learned from another peer if it is not reconfirmed
61  * by anyone?
62  */
63 #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
64
65 /**
66  * Initial handshake message for a session.
67  */
68 struct WelcomeMessage
69 {
70   /**
71    * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
72    */
73   struct GNUNET_MessageHeader header;
74
75   /**
76    * Identity of the node connecting (TCP client)
77    */
78   struct GNUNET_PeerIdentity clientIdentity;
79
80 };
81
82 /**
83  * Encapsulation of all of the state of the plugin.
84  */
85 struct Plugin
86 {
87   /**
88    * Our environment.
89    */
90   struct GNUNET_TRANSPORT_PluginEnvironment *env;
91
92   /**
93    * List of open sessions. head
94    */
95   struct Sessionqueue *sessions;
96
97   /**
98    * List of open sessions. tail
99    */
100   struct Sessionqueue *sessions_tail;
101
102   /**
103    * Number of sessions
104    */
105
106   int session_count;
107
108   /**
109    * encapsulation to the local wlan server prog
110    */
111
112   struct GNUNET_SERVER_MessageStreamTokenizer * consoltoken;
113
114
115   /**
116    * stdout pipe handle for the gnunet-wlan-helper process
117    */
118   struct GNUNET_DISK_PipeHandle *server_stdout;
119
120   /**
121    * stdout file handle for the gnunet-wlan-helper process
122    */
123   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
124
125   /**
126    * stdin pipe handle for the gnunet-wlan-helper process
127    */
128   struct GNUNET_DISK_PipeHandle *server_stdin;
129
130   /**
131    * stdin file handle for the gnunet-wlan-helper process
132    */
133   const struct GNUNET_DISK_FileHandle *server_stdin_handle;
134
135   /**
136    * ID of the gnunet-wlan-server std read task
137    */
138   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
139
140   /**
141    * ID of the gnunet-wlan-server std read task
142    */
143   GNUNET_SCHEDULER_TaskIdentifier server_write_task;
144
145   /**
146    * ID of the delay task for writing
147    */
148   GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
149
150   /**
151    * The process id of the wlan process
152    */
153   struct GNUNET_OS_Process *server_proc;
154
155   /**
156    * The interface of the wlan card given to us by the user.
157    */
158   char *interface;
159
160   /**
161    * The mac_address of the wlan card given to us by the helper.
162    */
163   char *mac_address;
164
165   /**
166    * Sessions currently pending for transmission
167    * to this peer, if any.
168    */
169   struct Sessionqueue * pending_Sessions;
170
171   /**
172     * Sessions currently pending for transmission
173     * to this peer (tail), if any.
174     */
175   struct Sessionqueue * pending_Sessions_tail;
176
177   /**
178    * number of pending sessions
179    */
180   unsigned int pendingsessions;
181
182   /**
183    * Messages in the fragmentation queue, head
184    */
185
186   struct FragmentMessage * pending_Fragment_Messages_head;
187
188   /**
189    * Messages in the fragmentation queue, tail
190    */
191
192   struct FragmentMessage * pending_Fragment_Messages_tail;
193
194   /**
195      * number of pending fragment message
196      */
197
198   unsigned int pending_fragment_messages;
199
200   /**
201    * time of the next "hello-beacon"
202    */
203
204   struct GNUNET_TIME_Absolute beacon_time;
205
206 };
207
208 /**
209  * Queue of sessions, for the general session queue and the pending session queue
210  */
211
212 struct Sessionqueue
213 {
214         struct Sessionqueue * next;
215         struct Sessionqueue * prev;
216         struct Session * content;
217 };
218
219 /**
220  * Queue of ack received for messages send
221  */
222
223 struct AckQueue
224 {
225         struct AckQueue * next;
226         struct AckQueue * prev;
227         int fragment_num; //TODO change it to offset if better
228 };
229
230 /**
231  * Queue for the fragments received
232  */
233
234 struct RecQueue
235 {
236         struct RecQueue * next;
237         struct RecQueue * prev;
238         uint16_t num;
239         const char * msg;
240         uint16_t size;
241 };
242
243 /**
244  * Information kept for each message that is yet to
245  * be transmitted.
246  */
247 struct PendingMessage
248 {
249
250   /**
251    * The pending message
252    */
253   char *msg;
254
255   /**
256    * Continuation function to call once the message
257    * has been sent.  Can be NULL if there is no
258    * continuation to call.
259    */
260   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
261
262   /**
263    * Cls for transmit_cont
264    */
265   void * transmit_cont_cls;
266
267   /**
268    * Timeout value for the pending message.
269    */
270   struct GNUNET_TIME_Absolute timeout;
271
272   /**
273    * Size of the message
274    */
275   size_t message_size;
276
277 };
278
279 /**
280  * Session infos gathered from a messages
281  */
282
283 struct Session_light
284 {
285   /**
286    * the session this message belongs to
287    */
288   struct Session * session;
289   /**
290    * peer mac address
291    */
292   uint8_t addr[6];
293 };
294
295 /**
296  * Session handle for connections.
297  */
298 struct Session
299 {
300
301   /**
302    * API requirement.
303    */
304   struct SessionHeader header;
305
306   /**
307    * Pointer to the global plugin struct.
308    */
309   struct Plugin *plugin;
310
311   /**
312    * Message currently pending for transmission
313    * to this peer, if any.
314    */
315   struct PendingMessage *pending_message;
316
317   /**
318    * To whom are we talking to (set to our identity
319    * if we are still waiting for the welcome message)
320    */
321   struct GNUNET_PeerIdentity target;
322
323   /**
324    * encapsulation of the receive data
325    */
326   //struct GNUNET_SERVER_MessageStreamTokenizer * receive_token;
327
328   /**
329    * offset of the next fragment for the receive_token, -1 means last message finished
330    */
331
332   //int rec_offset;
333
334   /**
335    * size of the message received,
336    * MESSAGE_LENGHT_UNKNOWN means that the size is not known,
337    * NO_MESSAGE_OR_MESSAGE_FINISHED means no message received
338    */
339
340   int rec_size;
341
342   /**
343    * Sorted queue with the fragments received; head
344    */
345
346   struct RecQueue * frag_head;
347
348   /**
349    * Sorted queue with the fragments received; tail
350    */
351
352   struct RecQueue * frag_tail;
353
354   /**
355    * peer mac address
356    */
357   char addr[6];
358
359   /**
360    * Address of the other peer (either based on our 'connect'
361    * call or on our 'accept' call).
362    */
363   void *connect_addr;
364
365   /**
366    * Last activity on this connection.  Used to select preferred
367    * connection.
368    */
369   struct GNUNET_TIME_Absolute last_activity;
370
371   /**
372    * current number for message incoming, to distinguish between the messages
373    */
374   uint32_t message_id_in;
375
376   /**
377    * current number for message outgoing, to distinguish between the messages
378    */
379   uint32_t message_id_out;
380
381   /**
382    * does this session have a message in the fragment queue
383    */
384
385   int has_fragment;
386
387 };
388
389
390
391
392 struct FragmentMessage
393 {
394         /**
395          * Session this message belongs to
396          */
397
398         struct Session *session;
399
400         /**
401         * This is a doubly-linked list.
402         */
403         struct FragmentMessage *next;
404
405         /**
406         * This is a doubly-linked list.
407         */
408         struct FragmentMessage *prev;
409
410         /**
411         * The pending message
412         */
413         char *msg;
414
415         /**
416         * Timeout value for the pending message.
417         */
418         struct GNUNET_TIME_Absolute timeout;
419
420         /**
421         * Timeout value for the pending fragments.
422         * Stores the time when the next msg fragment ack has to be received
423         */
424         struct GNUNET_TIME_Absolute next_ack;
425
426         /**
427         * Sorted queue with the acks received for fragments; head
428         */
429
430         struct AckQueue * head;
431
432         /**
433         * Sorted queue with the acks received for fragments; tail
434         */
435
436         struct AckQueue * tail;
437
438         /**
439         * Size of the message
440         */
441         size_t message_size;
442
443         /**
444         * pos / next fragment number in the message, for fragmentation/segmentation,
445         * some acks can be missing but there is still time
446         */
447         uint32_t message_pos;
448
449 };
450
451 /**
452  * Header for messages which need fragmentation
453  */
454 struct WlanHeader
455 {
456
457   struct GNUNET_MessageHeader header;
458
459   /**
460    * checksum/error correction
461    */
462   uint32_t crc GNUNET_PACKED;
463
464   /**
465    * To whom are we talking to (set to our identity
466    * if we are still waiting for the welcome message)
467    */
468   struct GNUNET_PeerIdentity target;
469
470   // followed by payload
471
472 };
473
474 /**
475  * Header for messages which need fragmentation
476  */
477 struct FragmentationHeader
478 {
479
480   struct GNUNET_MessageHeader header;
481
482   /**
483    * To whom are we talking to (set to our identity
484    * if we are still waiting for the welcome message)
485    */
486   // struct GNUNET_PeerIdentity target GNUNET_PACKED;
487
488   /**
489    * ID of message, to distinguish between the messages, picked randomly.
490    */
491   uint32_t message_id GNUNET_PACKED;
492
493   /**
494    * Offset or number of this fragment, for fragmentation/segmentation (design choice, TBD)
495    */
496   uint16_t fragment_off_or_num GNUNET_PACKED;
497
498   /**
499    * CRC of fragment (for error checking)
500    */
501   uint16_t message_crc GNUNET_PACKED;
502
503   /**
504    * Flags
505    * // 0x1 ack => Use two different message types in header.type! (FRAG_MESSAGE; FRAG_ACK)
506    * // 0x2 has data (not only ack)
507    * // 0x4 last fragment of message
508    * // 0x8 new message
509    */
510   //  uint32_t flags GNUNET_PACKED;
511
512   /**
513    * checksum/error correction
514    */
515   // uint32_t crc GNUNET_PACKED;
516
517   // followed by payload unless ACK
518
519 };
520
521 //enum { ACK_FRAGMENT = 1, DATA_FRAGMENT = 2, LAST_FRAGMENT = 4, NEW_MESSAGE = 8 };
522
523 int
524 getRadiotapHeader(struct RadiotapHeader * Header);
525
526 int
527 getWlanHeader(struct IeeeHeader * Header);
528
529 static int
530 wlan_plugin_address_suggested(void *cls, const void *addr, size_t addrlen);
531
532 uint16_t
533 getcrc16(const char *msgbuf, size_t msgbuf_size);
534
535 static void
536 do_transmit(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
537
538 static void
539 check_fragment_queue(struct Plugin * plugin);
540
541 uint32_t
542 getcrc32(const char *msgbuf, size_t msgbuf_size);
543
544 static void
545 free_rec_frag_queue(struct Session * session);
546
547 static void
548 wlan_process_helper (void *cls,
549                       void *client,
550                       const struct GNUNET_MessageHeader *hdr);
551
552 /**
553  * get the next message number, at the moment just a random one
554  *
555  */
556 //TODO doxigen
557 uint32_t
558 get_next_message_id()
559 {
560   return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
561 }
562
563 /**
564  * start next message number generator
565  */
566 //TODO doxigen
567 void
568 start_next_message_id()
569 {
570   //GNUNET_CRYPTO_random_init;
571 }
572
573 /**
574  * search for a session with the addr
575  *
576  * @param plugin pointer to the plugin struct
577  * @param addr pointer to the mac address of the peer
578  * @return returns the session
579  */
580
581 static struct Session *
582 search_session(struct Plugin *plugin, const uint8_t * addr)
583 {
584   struct Sessionqueue * queue = plugin->sessions;
585   struct Sessionqueue * lastitem = NULL;
586
587   //just look at all the session for the needed one
588   while (queue != NULL)
589     {
590       // content is never NULL
591       GNUNET_assert (queue->content == NULL);
592       char * addr2 = queue->content->addr;
593       if (memcmp(addr, addr2, 6) == 0)
594         {
595           //sesion found
596           return queue->content;
597         }
598       // try next
599       lastitem = queue;
600       queue = queue->next;
601     }
602   return NULL;
603 }
604
605 /**
606  * create a new session
607  *
608  * @param plugin pointer to the plugin struct
609  * @param addr pointer to the mac address of the peer
610  * @return returns the session
611  */
612
613 static struct Session *
614 create_session(struct Plugin *plugin,const uint8_t * addr)
615 {
616   struct Sessionqueue * queue = GNUNET_malloc (sizeof (struct Sessionqueue));
617
618   GNUNET_CONTAINER_DLL_insert_tail(plugin->sessions, plugin->sessions_tail, queue);
619
620   queue->content = GNUNET_malloc (sizeof (struct Session));
621   queue->content->plugin = plugin;
622   memcpy(queue->content->addr, addr, 6);
623   queue->content->message_id_out = get_next_message_id();
624   queue->content->has_fragment = 0;
625   queue->content->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
626
627   plugin->session_count++;
628   return queue->content;
629 }
630
631 /**
632  * get Session from address, create if no session exists
633  *
634  * @param plugin pointer to the plugin struct
635  * @param addr pointer to the mac address of the peer
636  * @return returns the session
637  */
638 //TODO add other possibilities to find the right session (are there other?)
639 static struct Session *
640 get_Session(struct Plugin *plugin, const uint8_t * addr)
641 {
642   struct Session * session = search_session(plugin, addr);
643   if (session != NULL)
644     {
645       return session;
646     }
647   // new session
648   return create_session(plugin, addr);
649
650   /* -- not needed, layer above already has it--
651    //queue welcome message for new sessions, not realy needed
652    //struct WelcomeMessage welcome;
653    struct PendingMessage *pm;
654    pm = GNUNET_malloc (sizeof (struct PendingMessage));
655    pm->msg = GNUNET_malloc(GNUNET_HELLO_size(* (plugin->env->our_hello)));
656    pm->message_size = GNUNET_HELLO_size(* (plugin->env->our_hello));
657    //welcome.header.size = htons (GNUNET_HELLO_size(* (plugin->env->our_hello)));
658    //welcome.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
659    //welcome.clientIdentity = *plugin->env->my_identity;
660    memcpy ( (pm->msg), * plugin->env->our_hello, GNUNET_HELLO_size(* (plugin->env->our_hello)));
661    pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
662    queue->content->pending_message = pm;
663    plugin->pendingsessions ++;
664    GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Sessions, plugin->pending_Sessions_tail, queue);
665
666    check_fragment_queue(plugin);
667    */
668 }
669
670 /**
671  * Queue the session to send data
672  */
673 //TODO doxigen
674 static void
675 queue_Session (struct Plugin *plugin,
676                 struct Session * session)
677 {
678         struct Sessionqueue * queue = plugin->pending_Sessions;
679         struct Sessionqueue * lastitem = NULL;
680
681         while (queue != NULL){
682                 // content is never NULL
683                 GNUNET_assert (queue->content == NULL);
684                 // is session already in queue?
685                 if (session == queue->content){
686                         return;
687                 }
688                 // try next
689                 lastitem = queue;
690                 queue = queue->next;
691         }
692
693         // Session is not in the queue
694
695         queue = GNUNET_malloc (sizeof (struct Sessionqueue));
696         queue->content = session;
697
698         //insert at the tail
699         GNUNET_CONTAINER_DLL_insert_after (plugin->pending_Sessions,
700                         plugin->pending_Sessions_tail,
701                         plugin->pending_Sessions_tail, queue);
702         plugin->pendingsessions ++;
703
704 }
705
706 //TODO doxigen
707 static void
708 free_acks (struct FragmentMessage * fm){
709         struct AckQueue * fq;
710         while (fm->head != NULL){
711                 fq = fm->head;
712                 GNUNET_CONTAINER_DLL_remove(fm->head, fm->tail, fq);
713                 GNUNET_free(fq);
714         }
715         //needed?
716         fm->head = NULL;
717         fm->tail = NULL;
718 }
719
720 //TODO doxigen
721 /**
722  * Function to schedule the write task, executed after a delay
723  */
724 static void
725 delay_fragment_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
726 {
727   struct Plugin * plugin = cls;
728   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
729
730   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
731     return;
732
733   // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
734   if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
735     {
736       plugin->server_write_task = GNUNET_SCHEDULER_add_write_file(
737           GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdin_handle,
738           &do_transmit, plugin);
739     }
740 }
741
742 //TODO doxigen
743 /**
744  * Function to calculate the time of the next periodic "hello-beacon"
745  */
746 static void
747 set_next_beacon_time(struct Plugin * const plugin)
748 {
749   //under 10 known peers: once a second
750   if (plugin->session_count < 10)
751     {
752       plugin->beacon_time = GNUNET_TIME_absolute_add(
753           GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_SECONDS);
754     }
755   //under 30 known peers: every 10 seconds
756   else if (plugin->session_count < 30)
757     {
758       plugin->beacon_time = GNUNET_TIME_absolute_add(
759           GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_multiply(
760               GNUNET_TIME_UNIT_SECONDS, 10));
761     }
762   //over 30 known peers: once a minute
763   else
764     {
765       plugin->beacon_time = GNUNET_TIME_absolute_add(
766           GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES);
767     }
768 }
769
770
771 //TODO doxigen
772 struct GNUNET_TIME_Relative
773 get_next_frag_timeout(struct FragmentMessage * fm)
774 {
775   return GNUNET_TIME_relative_min(GNUNET_TIME_absolute_get_remaining(
776       fm->next_ack), GNUNET_TIME_absolute_get_remaining(fm->timeout));
777 }
778
779 //TODO doxigen
780 /**
781  * Function to get the timeout value for acks for this session
782  */
783
784 struct GNUNET_TIME_Relative
785 get_ack_timeout (struct FragmentMessage * fm){
786         return FRAGMENT_TIMEOUT;
787 }
788
789 //TODO doxigen
790 /**
791  * Function to set the timer for the next timeout of the fragment queue
792  */
793 static void
794 check_next_fragment_timeout(struct Plugin * const plugin)
795 {
796   struct FragmentMessage * fm;
797   struct GNUNET_TIME_Relative next_send;
798
799   next_send = GNUNET_TIME_absolute_get_remaining(plugin->beacon_time);
800
801   //cancel old task
802   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
803     {
804       GNUNET_SCHEDULER_cancel(plugin->server_write_delay_task);
805     }
806   fm = plugin->pending_Fragment_Messages_head;
807
808   GNUNET_assert(plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK);
809
810   //check if there are some fragments in the queue
811   if (fm != NULL)
812     {
813       next_send
814           = GNUNET_TIME_relative_min(next_send, get_next_frag_timeout(fm));
815     }
816   plugin->server_write_delay_task = GNUNET_SCHEDULER_add_delayed(next_send,
817       &delay_fragment_task, plugin);
818 }
819
820
821
822 //TODO doxigen
823 /**
824  * Function to get the next queued Session, removes the session from the queue
825  */
826
827 static struct Session *
828 get_next_queue_Session (struct Plugin * plugin){
829         struct Session * session;
830         struct Sessionqueue * sessionqueue;
831         struct Sessionqueue * sessionqueue_alt;
832         struct PendingMessage * pm;
833         sessionqueue = plugin->pending_Sessions;
834         while (sessionqueue != NULL){
835                 session = sessionqueue->content;
836                 pm = session->pending_message;
837
838                 //check for message timeout
839                 if (GNUNET_TIME_absolute_get_remaining(pm->timeout).rel_value > 0){
840                         //check if session has no message in the fragment queue
841                         if (! session->has_fragment){
842                                 plugin->pendingsessions --;
843                                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
844                                                 plugin->pending_Sessions_tail, sessionqueue);
845                                 GNUNET_free(sessionqueue);
846
847                                 return session;
848                         } else {
849                                 sessionqueue = sessionqueue->next;
850                         }
851                 } else {
852
853                         session->pending_message = NULL;
854                         //call the cont func that it did not work
855                         if (pm->transmit_cont != NULL)
856                           pm->transmit_cont (pm->transmit_cont_cls,
857                                                 &(session->target), GNUNET_SYSERR);
858                         GNUNET_free(pm->msg);
859                         GNUNET_free(pm);
860
861                         sessionqueue_alt = sessionqueue;
862                         sessionqueue = sessionqueue->next;
863                         plugin->pendingsessions --;
864                         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
865                                         plugin->pending_Sessions_tail, sessionqueue_alt);
866
867                         GNUNET_free(sessionqueue_alt);
868
869                 }
870
871
872         }
873         return NULL;
874 }
875
876 //TODO doxigen
877 /**
878  * Function to sort the message into the message fragment queue
879  */
880 static void
881 sort_fragment_into_queue (struct Plugin * plugin, struct FragmentMessage * fm){
882         struct FragmentMessage * fm2;
883         //sort into the list at the right position
884
885         fm2 = plugin->pending_Fragment_Messages_head;
886
887         while (fm2 != NULL){
888                 if (GNUNET_TIME_absolute_get_difference(fm2->next_ack, fm->next_ack).rel_value == 0){
889                         break;
890                 } else {
891                         fm2 = fm2->next;
892                 }
893         }
894
895         GNUNET_CONTAINER_DLL_insert_after(plugin->pending_Fragment_Messages_head,
896                         plugin->pending_Fragment_Messages_tail,fm2,fm);
897 }
898
899 //TODO doxigen
900 static void
901 free_fragment_message(struct Plugin * plugin,struct FragmentMessage * fm)
902 {
903   if (fm != NULL)
904     {
905       free_acks(fm);
906       GNUNET_free_non_null(fm->msg);
907       GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
908           plugin->pending_Fragment_Messages_tail, fm);
909       GNUNET_free(fm);
910       plugin->pending_fragment_messages --;
911       check_fragment_queue(plugin);
912     }
913 }
914
915 //TODO doxigen
916 /**
917  * Function to check if there is some space in the fragment queue
918  */
919
920 static void
921 check_fragment_queue (struct Plugin * plugin){
922         struct Session * session;
923         struct FragmentMessage * fm;
924
925         struct PendingMessage * pm;
926
927         if (plugin->pending_fragment_messages < FRAGMENT_QUEUE_SIZE){
928                 session = get_next_queue_Session(plugin);
929                 if (session != NULL){
930                         pm = session->pending_message;
931                         session->pending_message = NULL;
932                         session->has_fragment = 1;
933                         GNUNET_assert(pm != NULL);
934
935                         fm = GNUNET_malloc(sizeof(struct FragmentMessage));
936                         fm->message_size = pm->message_size;
937                         fm->msg = pm->msg;
938                         fm->session = session;
939                         fm->timeout.abs_value = pm->timeout.abs_value;
940                         fm->message_pos = 0;
941                         fm->next_ack = GNUNET_TIME_absolute_get();
942
943                         if (pm->transmit_cont != NULL)
944                                   pm->transmit_cont (pm->transmit_cont_cls,
945                                                         &(session->target), GNUNET_OK);
946                         GNUNET_free(pm);
947
948                         sort_fragment_into_queue(plugin,fm);
949                         plugin->pending_fragment_messages ++;
950
951                         //generate new message id
952                         session->message_id_out = get_next_message_id();
953
954                         //check if timeout changed
955                         check_next_fragment_timeout(plugin);
956                 }
957         }
958 }
959
960 //TODO doxigen
961 static void
962 check_finished_fragment(struct Plugin * plugin, struct FragmentMessage * fm){
963   struct AckQueue * ack;
964   int counter = 0;
965
966   if (fm->message_size >= (WLAN_MTU - sizeof(struct FragmentationHeader))
967       * fm->tail->fragment_num)
968     {
969       ack = fm->head;
970       counter = 0;
971       //check if all acks are present
972       while (ack != NULL)
973         {
974           if (counter == ack->fragment_num)
975             {
976               counter ++;
977               ack = ack->next;
978             } else {
979               //ack is missing
980               return;
981             }
982         }
983       fm->session->has_fragment = 0;
984       free_fragment_message(plugin, fm);
985
986
987     }
988 }
989
990 /**
991  * Function called to when wlan helper is ready to get some data
992  *
993  * @param cls closure
994  * @param GNUNET_SCHEDULER_TaskContext
995  */
996
997 static void
998 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
999 {
1000
1001   struct Plugin * plugin = cls;
1002   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1003
1004   ssize_t bytes;
1005
1006   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1007     return;
1008
1009   struct Session * session = NULL;
1010   struct FragmentMessage * fm = NULL;
1011   struct IeeeHeader * ieeewlanheader = NULL;
1012   struct RadiotapHeader * radioHeader = NULL;
1013   struct GNUNET_MessageHeader * msgheader = NULL;
1014   struct GNUNET_MessageHeader * msgheader2 = NULL;
1015   struct FragmentationHeader fragheader;
1016   uint16_t size = 0;
1017   const char * copystart = NULL;
1018   uint16_t copysize = 0;
1019   uint copyoffset = 0;
1020   struct AckQueue * akt = NULL;
1021
1022   //test if a "hello-beacon" has to be send
1023   if (GNUNET_TIME_absolute_get_remaining(plugin->beacon_time).rel_value == 0)
1024     {
1025       //check if the message is not to big
1026       GNUNET_assert(sizeof(struct WlanHeader) + GNUNET_HELLO_size(
1027               *(plugin->env->our_hello)) <= WLAN_MTU);
1028       size = sizeof(struct GNUNET_MessageHeader)
1029           + sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1030           + sizeof(struct GNUNET_MessageHeader) + GNUNET_HELLO_size(
1031           *(plugin->env->our_hello));
1032
1033       msgheader = GNUNET_malloc(size);
1034       msgheader->size = htons(size);
1035       msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1036
1037       radioHeader = (struct RadiotapHeader *) &msgheader[1];
1038       getRadiotapHeader(radioHeader);
1039
1040       ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1041       getWlanHeader(ieeewlanheader);
1042
1043       msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1044       msgheader2->size = htons(GNUNET_HELLO_size(*(plugin->env->our_hello)) + sizeof(struct GNUNET_MessageHeader));
1045       msgheader2->type = htons(GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT);
1046
1047       memcpy(&msgheader2[1], *plugin->env->our_hello, GNUNET_HELLO_size(
1048           *(plugin->env->our_hello)));
1049
1050
1051       bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader,
1052           size);
1053       GNUNET_assert(bytes == size);
1054
1055       set_next_beacon_time(plugin);
1056       check_next_fragment_timeout(plugin);
1057       return;
1058
1059     }
1060
1061
1062   fm = plugin->pending_Fragment_Messages_head;
1063   GNUNET_assert(fm != NULL);
1064   session = fm->session;
1065   GNUNET_assert(session != NULL);
1066
1067   // test if message timed out
1068   if (GNUNET_TIME_absolute_get_remaining(fm->timeout).rel_value == 0){
1069           free_acks(fm);
1070           GNUNET_assert(plugin->pending_fragment_messages > 0);
1071           plugin->pending_fragment_messages --;
1072           GNUNET_CONTAINER_DLL_remove(plugin->pending_Fragment_Messages_head,
1073                           plugin->pending_Fragment_Messages_tail, fm);
1074
1075           GNUNET_free(fm->msg);
1076
1077           GNUNET_free(fm);
1078           check_fragment_queue(plugin);
1079   } else {
1080
1081           if (fm->message_size > WLAN_MTU) {
1082                 size += sizeof(struct FragmentationHeader);
1083                 // check/set for retransmission
1084                 if (GNUNET_TIME_absolute_get_duration(fm->next_ack).rel_value == 0) {
1085
1086                         // be positive and try again later :-D
1087                         fm->next_ack = GNUNET_TIME_relative_to_absolute(get_ack_timeout(fm));
1088                         // find first missing fragment
1089                         akt = fm->head;
1090                         fm->message_pos = 0;
1091
1092                         //test if ack 0 was already received
1093                         while (akt != NULL){
1094                                 //if fragment is present, take next
1095                                 if (akt->fragment_num == fm->message_pos) {
1096                                         fm->message_pos ++;
1097                                 }
1098                                 //next ack is bigger then the fragment number
1099                                 //in case there is something like this: (acks) 1, 2, 5, 6, ...
1100                                 //and we send 3 again, the next number should be 4
1101                                 else if (akt->fragment_num > fm->message_pos) {
1102                                         break;
1103                                 }
1104
1105                                 akt = akt->next;
1106
1107                         }
1108
1109
1110                 }
1111
1112                 copyoffset = (WLAN_MTU - sizeof(struct FragmentationHeader)) * fm->message_pos;
1113                 fragheader.fragment_off_or_num = htons(fm->message_pos);
1114                 fragheader.message_id = htonl(session->message_id_out);
1115
1116                 // start should be smaller then the packet size
1117                 GNUNET_assert(copyoffset < fm->message_size);
1118                 copystart = fm->msg + copyoffset;
1119
1120                 //size of the fragment is either the MTU - overhead
1121                 //or the missing part of the message in case this is the last fragment
1122                 copysize = GNUNET_MIN(fm->message_size - copyoffset,
1123                                 WLAN_MTU - sizeof(struct FragmentationHeader));
1124                 fragheader.header.size = htons(copysize + sizeof(struct FragmentationHeader));
1125                 fragheader.header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT);
1126
1127
1128                 //get the next missing fragment
1129                 akt = fm->head;
1130                 fm->message_pos ++;
1131
1132                 //test if ack was already received
1133                 while (akt != NULL){
1134                         //if fragment is present, take next
1135                         if (akt->fragment_num == fm->message_pos) {
1136                                 fm->message_pos ++;
1137                         }
1138                         //next ack is bigger then the fragment number
1139                         //in case there is something like this: (acks) 1, 2, 5, 6, ...
1140                         //and we send 3 again, the next number should be 4
1141                         else if (akt->fragment_num > fm->message_pos) {
1142                                 break;
1143                         }
1144
1145                         akt = akt->next;
1146                 }
1147           } else {
1148                 // there is no need to split
1149                 copystart = fm->msg;
1150                 copysize = fm->message_size;
1151           }
1152
1153         size += copysize;
1154         size += sizeof(struct RadiotapHeader) + sizeof(struct IeeeHeader)
1155                 + sizeof(struct GNUNET_MessageHeader);
1156         msgheader = GNUNET_malloc(size);
1157         msgheader->size = htons(size);
1158         msgheader->type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1159
1160         radioHeader = (struct RadiotapHeader*) &msgheader[1];
1161         getRadiotapHeader(radioHeader);
1162
1163         ieeewlanheader = (struct IeeeHeader *) &radioHeader[1];
1164         getWlanHeader(ieeewlanheader);
1165
1166
1167         //could be faster if content is just send and not copyed before
1168         //fragmentheader is needed
1169         if (fm->message_size > WLAN_MTU){
1170                 fragheader.message_crc = htons(getcrc16(copystart, copysize));
1171                 memcpy(&ieeewlanheader[1],&fragheader, sizeof(struct FragmentationHeader));
1172                 memcpy(&ieeewlanheader[1] + sizeof(struct FragmentationHeader),copystart,copysize);
1173         } else {
1174                 memcpy(&ieeewlanheader[1],copystart,copysize);
1175         }
1176
1177         bytes = GNUNET_DISK_file_write(plugin->server_stdin_handle, msgheader, size);
1178         GNUNET_assert(bytes == size);
1179
1180         //check if this was the last fragment of this message, if true then queue at the end of the list
1181         if (copysize + copyoffset >= fm->message_size){
1182                 GNUNET_assert(copysize + copyoffset == fm->message_size);
1183
1184                 GNUNET_CONTAINER_DLL_remove (plugin->pending_Fragment_Messages_head,
1185                                 plugin->pending_Fragment_Messages_tail, fm);
1186
1187                 GNUNET_CONTAINER_DLL_insert_tail(plugin->pending_Fragment_Messages_head,
1188                                 plugin->pending_Fragment_Messages_tail, fm);
1189                 // if fragments have opimized timeouts
1190                 //sort_fragment_into_queue(plugin,fm);
1191
1192         }
1193         check_next_fragment_timeout(plugin);
1194
1195   }
1196 }
1197
1198
1199 /**
1200  * 32bit CRC
1201  *
1202  * @param msgbuf pointer tor the data
1203  * @param msgbuf_size size of the data
1204  *
1205  * @return 32bit crc value
1206  */
1207
1208 uint32_t
1209 getcrc32 (const char *msgbuf,
1210                   size_t msgbuf_size){
1211         //TODO calc some crc
1212         return 0;
1213 }
1214
1215 /**
1216  * 16bit CRC
1217  *
1218  * @param msgbuf pointer tor the data
1219  * @param msgbuf_size size of the data
1220  *
1221  * @return 16bit crc value
1222  */
1223
1224 uint16_t
1225 getcrc16 (const char *msgbuf,
1226                   size_t msgbuf_size){
1227         //TODO calc some crc
1228         return 0;
1229 }
1230
1231 /**
1232  * Function that can be used by the transport service to transmit
1233  * a message using the plugin.
1234  *
1235  * @param cls closure
1236  * @param target who should receive this message
1237  * @param priority how important is the message
1238  * @param msgbuf the message to transmit
1239  * @param msgbuf_size number of bytes in 'msgbuf'
1240  * @param timeout when should we time out 
1241  * @param session which session must be used (or NULL for "any")
1242  * @param addr the address to use (can be NULL if the plugin
1243  *                is "on its own" (i.e. re-use existing TCP connection))
1244  * @param addrlen length of the address in bytes
1245  * @param force_address GNUNET_YES if the plugin MUST use the given address,
1246  *                otherwise the plugin may use other addresses or
1247  *                existing connections (if available)
1248  * @param cont continuation to call once the message has
1249  *        been transmitted (or if the transport is ready
1250  *        for the next transmission call; or if the
1251  *        peer disconnected...)
1252  * @param cont_cls closure for cont
1253  * @return number of bytes used (on the physical network, with overheads);
1254  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
1255  *         and does NOT mean that the message was not transmitted (DV)
1256  */
1257 static ssize_t
1258 wlan_plugin_send (void *cls,
1259                   const struct GNUNET_PeerIdentity * target,
1260                   const char *msgbuf,
1261                   size_t msgbuf_size,
1262                   unsigned int priority,
1263                   struct GNUNET_TIME_Relative timeout,
1264                   struct Session *session,
1265                   const void *addr,
1266                   size_t addrlen,
1267                   int force_address,
1268                   GNUNET_TRANSPORT_TransmitContinuation cont,
1269                   void *cont_cls)
1270 {
1271   struct Plugin * plugin = cls;
1272   struct PendingMessage * newmsg = NULL;
1273   struct WlanHeader * wlanheader = NULL;
1274   //check if msglen > 0
1275   GNUNET_assert(msgbuf_size > 0);
1276
1277   //get session if needed
1278   if (session == NULL)
1279     {
1280       if (wlan_plugin_address_suggested(plugin, addr, addrlen) == GNUNET_OK)
1281         {
1282           session = get_Session(plugin, addr);
1283         }
1284       else
1285         {
1286           GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1287               _("Wlan Address len %d is wrong\n"), addrlen);
1288           return -1;
1289         }
1290     }
1291
1292   //TODO target "problem" not solved
1293   session->target = *target;
1294
1295   //queue message:
1296   //first queue session
1297   queue_Session(plugin, session);
1298
1299   //queue message in session
1300   //test if there is no other message in the "queue"
1301   GNUNET_assert (session->pending_message == NULL);
1302
1303   newmsg = GNUNET_malloc(sizeof(struct PendingMessage));
1304   (newmsg->msg) = GNUNET_malloc(msgbuf_size + sizeof(struct WlanHeader));
1305   wlanheader = (struct WlanHeader *) newmsg->msg;
1306   //copy msg to buffer, not fragmented / segmented yet, but with message header
1307   wlanheader->header.size = htons(msgbuf_size + sizeof(struct WlanHeader));
1308   wlanheader->header.type = htons(GNUNET_MESSAGE_TYPE_WLAN_DATA);
1309   memcpy(&(wlanheader->target), target, sizeof(struct GNUNET_PeerIdentity));
1310   wlanheader->crc = htonl(getcrc32(msgbuf, msgbuf_size));
1311   memcpy(&wlanheader[1], msgbuf, msgbuf_size);
1312   newmsg->transmit_cont = cont;
1313   newmsg->transmit_cont_cls = cont_cls;
1314   newmsg->timeout = GNUNET_TIME_relative_to_absolute(timeout);
1315   newmsg->message_size = msgbuf_size + sizeof(struct WlanHeader);
1316
1317   check_fragment_queue(plugin);
1318   //FIXME not the correct size
1319   return msgbuf_size;
1320
1321 }
1322
1323 //TODO doxigen
1324 static struct FragmentMessage *
1325 get_fragment_message_from_session(struct Session * session)
1326 {
1327   struct FragmentMessage * fm = session->plugin->pending_Fragment_Messages_head;
1328   while (fm != NULL)
1329     {
1330       if (fm->session == session)
1331         {
1332           return fm;
1333         }
1334       fm = fm->next;
1335     }
1336   return NULL;
1337 }
1338
1339 /**
1340  * Function that can be used to force the plugin to disconnect
1341  * from the given peer and cancel all previous transmissions
1342  * (and their continuation).
1343  *
1344  * @param cls closure
1345  * @param target peer from which to disconnect
1346  */
1347 static void
1348 wlan_plugin_disconnect(void *cls, const struct GNUNET_PeerIdentity *target)
1349 {
1350   struct Plugin *plugin = cls;
1351   struct Sessionqueue * queue = plugin->sessions;
1352   struct Sessionqueue * pendingsession = plugin->pending_Sessions;
1353   struct PendingMessage * pm = NULL;
1354   struct FragmentMessage * fm;
1355
1356   // just look at all the session for the needed one
1357   while (queue != NULL)
1358     {
1359       // content is never NULL
1360       GNUNET_assert (queue->content == NULL);
1361       if (memcmp(target, &(queue->content->target),
1362           sizeof(struct GNUNET_PeerIdentity)) == 0)
1363         {
1364           //session found
1365           //is this session pending for send
1366           while (pendingsession != NULL)
1367             {
1368               if (pendingsession->content == queue->content)
1369                 {
1370                   plugin->pendingsessions --;
1371                   GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions,
1372                       plugin->pending_Sessions_tail, pendingsession);
1373                   GNUNET_free(pendingsession);
1374                   break;
1375                 }
1376               pendingsession = pendingsession->next;
1377             }
1378
1379           //is something of this session in the fragment queue?
1380           fm = get_fragment_message_from_session(queue->content);
1381           free_fragment_message(plugin,fm);
1382
1383           //dispose all received fragments
1384           free_rec_frag_queue(queue->content);
1385
1386           // remove PendingMessage
1387           pm = queue->content->pending_message;
1388           GNUNET_free(pm->msg);
1389           GNUNET_free(pm);
1390
1391           GNUNET_free(queue->content);
1392           GNUNET_CONTAINER_DLL_remove(plugin->sessions, plugin->sessions_tail, queue);
1393           GNUNET_free(queue);
1394           plugin->session_count --;
1395
1396           return;
1397         }
1398       // try next
1399       queue = queue->next;
1400     }
1401 }
1402
1403
1404 /**
1405  * Convert the transports address to a nice, human-readable
1406  * format.
1407  *
1408  * @param cls closure
1409  * @param type name of the transport that generated the address
1410  * @param addr one of the addresses of the host, NULL for the last address
1411  *        the specific address format depends on the transport
1412  * @param addrlen length of the address
1413  * @param numeric should (IP) addresses be displayed in numeric form?
1414  * @param timeout after how long should we give up?
1415  * @param asc function to call on each string
1416  * @param asc_cls closure for asc
1417  */
1418 static void
1419 wlan_plugin_address_pretty_printer (void *cls,
1420                                     const char *type,
1421                                     const void *addr,
1422                                     size_t addrlen,
1423                                     int numeric,
1424                                     struct GNUNET_TIME_Relative timeout,
1425                                     GNUNET_TRANSPORT_AddressStringCallback
1426                                     asc, void *asc_cls)
1427 {
1428   char ret[92];
1429   const unsigned char * input;
1430   
1431   GNUNET_assert(cls !=NULL);
1432   if (addrlen != 6)
1433     {
1434       /* invalid address (MAC addresses have 6 bytes) */
1435       GNUNET_break (0);
1436       asc (asc_cls, NULL);
1437       return;
1438     }
1439   input = (const unsigned char*) addr;
1440   GNUNET_snprintf (ret, 
1441                    sizeof (ret),
1442                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1443                    PROTOCOL_PREFIX, 
1444                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1445   asc (asc_cls, ret);
1446 }
1447
1448
1449
1450 /**
1451  * Another peer has suggested an address for this
1452  * peer and transport plugin.  Check that this could be a valid
1453  * address.  If so, consider adding it to the list
1454  * of addresses.
1455  *
1456  * @param cls closure
1457  * @param addr pointer to the address
1458  * @param addrlen length of addr
1459  * @return GNUNET_OK if this is a plausible address for this peer
1460  *         and transport
1461  */
1462
1463
1464 static int
1465 wlan_plugin_address_suggested (void *cls,
1466                                    const void *addr,
1467                                    size_t addrlen)
1468 {
1469   //struct Plugin *plugin = cls;
1470
1471   /* check if the address is plausible; if so,
1472      add it to our list! */
1473
1474   GNUNET_assert(cls !=NULL);
1475   //FIXME mitm is not checked
1476   //Mac Adress has 6 bytes
1477   if (addrlen == 6){
1478     /* TODO check for bad addresses like milticast, broadcast, etc */
1479     return GNUNET_OK;
1480   } else {
1481     return GNUNET_SYSERR;
1482   }
1483
1484   return GNUNET_SYSERR;
1485 }
1486
1487
1488 /**
1489  * Function called for a quick conversion of the binary address to
1490  * a numeric address.  Note that the caller must not free the 
1491  * address and that the next call to this function is allowed
1492  * to override the address again.
1493  *
1494  * @param cls closure
1495  * @param addr binary address
1496  * @param addrlen length of the address
1497  * @return string representing the same address 
1498  */
1499 static const char* 
1500 wlan_plugin_address_to_string (void *cls,
1501                                const void *addr,
1502                                size_t addrlen)
1503 {
1504   char ret[92];
1505   const unsigned char * input;
1506   
1507   GNUNET_assert(cls !=NULL);
1508   if (addrlen != 6)
1509     {
1510       /* invalid address (MAC addresses have 6 bytes) */
1511       GNUNET_break (0);
1512       return NULL;
1513     }
1514   input = (const unsigned char*) addr;
1515   GNUNET_snprintf (ret, 
1516                    sizeof (ret),
1517                    "%s Mac-Adress %X:%X:%X:%X:%X:%X",
1518                    PROTOCOL_PREFIX, 
1519                    input[0], input[1], input[2], input[3], input[4], input[5]);  
1520   return GNUNET_strdup (ret);
1521 }
1522
1523 /**
1524  * Function to test if fragment number already exists in the fragments received
1525  */
1526 //TODO doxigen
1527 static const int
1528 is_double_msg(struct Session * session, struct FragmentationHeader * fh)
1529 {
1530   struct RecQueue * rec_queue = session->frag_head;
1531   while (rec_queue != NULL)
1532     {
1533       if (rec_queue->num == fh->fragment_off_or_num)
1534         {
1535           return GNUNET_YES;
1536         }
1537       rec_queue = rec_queue->next;
1538
1539     }
1540   return GNUNET_NO;
1541 }
1542
1543
1544 static void
1545 insert_fragment_in_queue(struct Session * session, struct RecQueue * rec_queue)
1546 {
1547   struct RecQueue * rec_queue2 = session->frag_head;
1548   struct WlanHeader * wlanheader = NULL;
1549   //first received fragment of message
1550   if (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED)
1551     {
1552       session->rec_size = MESSAGE_LENGHT_UNKNOWN;
1553     }
1554   //this is the first fragment of the message (fragment id 0)
1555   if (rec_queue->num == 0)
1556     {
1557       wlanheader = (struct WlanHeader *) rec_queue->msg;
1558       session->rec_size = wlanheader->header.size;
1559     }
1560
1561   //sort into list
1562   while (rec_queue2 != NULL)
1563     {
1564       if (rec_queue2->num > rec_queue->num)
1565         {
1566           //next element number is grater than the current num
1567           GNUNET_CONTAINER_DLL_insert_before(session->frag_head, session->frag_tail, rec_queue2, rec_queue);
1568           return;
1569         }
1570       rec_queue = rec_queue->next;
1571     }
1572   //no element has a grater number
1573   GNUNET_CONTAINER_DLL_insert_tail(session->frag_head, session->frag_tail, rec_queue);
1574 }
1575
1576 /**
1577  * Function to dispose the fragments received for a message
1578  */
1579 //TODO doxigen
1580 static void
1581 free_rec_frag_queue(struct Session * session)
1582 {
1583   struct RecQueue * rec_queue = session->frag_head;
1584   struct RecQueue * rec_queue2;
1585   while (rec_queue != NULL)
1586     {
1587       rec_queue2 = rec_queue;
1588       rec_queue = rec_queue->next;
1589       GNUNET_free(rec_queue2);
1590     }
1591   session->frag_head = NULL;
1592   session->frag_tail = NULL;
1593   session->rec_size = NO_MESSAGE_OR_MESSAGE_FINISHED;
1594 }
1595
1596 /**
1597  * Function to check if all fragments of a message have been received
1598  */
1599 //TODO doxigen
1600 static void
1601 check_rec_finished_msg (struct Plugin* plugin, struct Session_light * session_light, struct Session * session){
1602   struct RecQueue * rec_queue = session->frag_head;
1603   int packetsize = session->rec_size;
1604   int sum = 0;
1605   int aktnum = 0;
1606   char * msg;
1607   //some fragment should be received
1608   GNUNET_assert(session->rec_size != NO_MESSAGE_OR_MESSAGE_FINISHED);
1609   //check if first fragment is present
1610   if (session->rec_size == MESSAGE_LENGHT_UNKNOWN){
1611     return;
1612   }
1613   while (rec_queue != NULL){
1614     sum += rec_queue->size;
1615     //check if all fragment numbers are present
1616     if (rec_queue->num != aktnum){
1617       return;
1618     }
1619     aktnum ++;
1620     rec_queue = rec_queue->next;
1621   }
1622   //sum should always be smaller or equal of
1623   GNUNET_assert(sum <= packetsize);
1624   if (sum == packetsize){
1625     //copy fragments together
1626     msg = GNUNET_malloc(packetsize);
1627     rec_queue = session->frag_head;
1628     aktnum = 0;
1629     while (rec_queue != NULL){
1630       memcpy(msg + aktnum, rec_queue->msg, rec_queue->size);
1631       aktnum += rec_queue->size;
1632       rec_queue = rec_queue->next;
1633     }
1634     free_rec_frag_queue(session);
1635     //call wlan_process_helper to process the message
1636     wlan_process_helper (plugin, session_light, (struct GNUNET_MessageHeader*) msg);
1637
1638     GNUNET_free(msg);
1639   }
1640 }
1641
1642 /**
1643  * Function used for to process the data from the suid process
1644  */
1645 //TODO doxigen
1646
1647 static void
1648 wlan_process_helper (void *cls,
1649                       void *client,
1650                       const struct GNUNET_MessageHeader *hdr)
1651 {
1652   struct Plugin *plugin = cls;
1653   struct IeeeHeader * wlanIeeeHeader = NULL;
1654   struct Session * session = NULL;
1655   struct WlanHeader * wlanheader = NULL;
1656   struct FragmentationHeader * fh = NULL;
1657   struct FragmentMessage * fm = NULL;
1658   struct RecQueue * rec_queue = NULL;
1659   const struct GNUNET_MessageHeader * temp_hdr = NULL;
1660   const char * tempmsg = NULL;
1661   struct Session_light * session_light;
1662   struct AckQueue * ack;
1663   struct AckQueue * ack2;
1664   int pos = 0;
1665
1666
1667   if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA)
1668     {
1669       //call wlan_process_helper with the message inside, later with wlan: analyze signal
1670       GNUNET_assert(ntohs(hdr->size) >= sizeof(struct IeeeHeader));
1671       wlanIeeeHeader = (struct IeeeHeader *) &hdr[1];
1672
1673       session_light = GNUNET_malloc(sizeof(struct Session_light));
1674       memcpy(session_light->addr, wlanIeeeHeader->mac3, 6);
1675       session_light->session = search_session(plugin, session_light->addr);
1676
1677       //process only if it is an broadcast or for this computer both with the gnunet bssid
1678       //check for bssid
1679       if (memcmp(wlanIeeeHeader->mac2, macbc, sizeof(macbc)))
1680         {
1681           //check for broadcast or mac
1682           if (memcmp(wlanIeeeHeader->mac1, bc_all_mac, sizeof(bc_all_mac))
1683               || memcmp(wlanIeeeHeader->mac1, plugin->mac_address,
1684                   sizeof(plugin->mac_address)))
1685             {
1686               // process the inner data
1687             pos = 0;
1688             temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1];
1689               while (pos < hdr->size)
1690                 {
1691                   wlan_process_helper(plugin, &session_light,
1692                       temp_hdr);
1693                   pos += temp_hdr->size + sizeof(struct GNUNET_MessageHeader);
1694                 }
1695             }
1696         }
1697
1698     }
1699
1700
1701   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT)
1702     {
1703       //TODO better DOS protection, error handling
1704       GNUNET_assert(client != NULL);
1705       session_light = (struct Session_light *) client;
1706       if (session_light->session == NULL){
1707         session_light->session = get_Session(plugin, session_light->addr);
1708       }
1709       GNUNET_assert(GNUNET_HELLO_get_id(
1710           (const struct GNUNET_HELLO_Message *) &hdr[1],
1711           &(session_light->session->target) ) != GNUNET_SYSERR);
1712
1713     }
1714
1715
1716   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
1717     {
1718       GNUNET_assert(client != NULL);
1719       session_light = (struct Session_light *) client;
1720       if (session_light->session == NULL){
1721         session_light->session = search_session(plugin, session_light->addr);
1722       }
1723       session = session_light->session;
1724       wlanheader =(struct WlanHeader *) &hdr[1];
1725       tempmsg = (char*) &wlanheader[1];
1726       temp_hdr = ( const struct GNUNET_MessageHeader *) &wlanheader[1];
1727
1728       if (getcrc32(tempmsg, wlanheader->header.size) != wlanheader->crc){
1729         //wrong crc, dispose message
1730         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1731                                      "WLAN message crc was wrong\n");
1732         return;
1733       }
1734
1735       //if not in session list
1736       if (session == NULL){
1737
1738         //try if it is a hello message
1739         if (ntohs(temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO){
1740           session = create_session(plugin, session_light->addr);
1741           session_light->session = session;
1742           GNUNET_assert(GNUNET_HELLO_get_id(
1743               (const struct GNUNET_HELLO_Message *) temp_hdr,
1744               &session->target ) != GNUNET_SYSERR);
1745
1746         } else {
1747           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1748                              "WLAN client not in session list and not a hello message\n");
1749           return;
1750         }
1751       }
1752       //"receive" the message
1753       plugin->env->receive(plugin, &session->target,
1754            temp_hdr, 1, session, session->addr, sizeof(session->addr));
1755     }
1756
1757   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT)
1758     {
1759       GNUNET_assert(client != NULL);
1760       session_light = (struct Session_light *) client;
1761       if (session_light->session == NULL)
1762         {
1763           session_light->session = search_session(plugin, session_light->addr);
1764         }
1765       session = session_light->session;
1766
1767       fh = (struct FragmentationHeader *) hdr;
1768       tempmsg = (char*) &fh[1];
1769
1770       //if not in session list
1771       if (session != NULL)
1772         {
1773           if (getcrc16(tempmsg, fh->header.size) != fh->message_crc)
1774             {
1775               //wrong crc, dispose message
1776               GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1777                   "WLAN fragment crc was wrong\n");
1778               return;
1779             }
1780           else
1781             {
1782               //todo fragments do not timeout
1783               //check if message_id is rigth or it is a new msg
1784               if ((session->message_id_in == ntohs(fh->message_id))
1785                   || (session->rec_size == NO_MESSAGE_OR_MESSAGE_FINISHED))
1786                 {
1787                 session->message_id_in = ntohs(fh->message_id);
1788                   if (is_double_msg(session, fh) != GNUNET_YES)
1789                     {
1790                       rec_queue = GNUNET_malloc(sizeof (struct RecQueue) +
1791                               ntohs(fh->header.size) - sizeof(struct FragmentationHeader));
1792                       rec_queue->size = ntohs(fh->header.size
1793                           - sizeof(struct FragmentationHeader));
1794                       rec_queue->num = ntohs(fh->fragment_off_or_num);
1795                       rec_queue->msg = (char*) &rec_queue[1];
1796                       //copy msg to buffer
1797                       memcpy((char*) rec_queue->msg, tempmsg, rec_queue->size);
1798                       insert_fragment_in_queue(session, rec_queue);
1799                       check_rec_finished_msg(plugin, session_light, session);
1800                     }
1801                   else
1802                     {
1803                       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1804                           "WLAN fragment is a clone\n");
1805                       return;
1806                     }
1807                 }
1808               else
1809                 {
1810                 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1811                       "WLAN fragment message_id and session message_id are not the same and a message is already (partly) received\n");
1812                   return;
1813                 }
1814             }
1815         }
1816       else
1817         {
1818           GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1819               "WLAN client not in session list and it is a fragment message\n");
1820           return;
1821         }
1822
1823     }
1824
1825   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT_ACK)
1826     {
1827       GNUNET_assert(client != NULL);
1828       session_light = (struct Session_light *) client;
1829       if (session_light->session == NULL)
1830         {
1831           session_light->session = search_session(plugin, session_light->addr);
1832         }
1833       session = session_light->session;
1834       fh = (struct FragmentationHeader *) &hdr[1];
1835       if (fh->message_id == session->message_id_out)
1836         {
1837           fm = get_fragment_message_from_session(session);
1838           if (fm != NULL)
1839             {
1840               ack = GNUNET_malloc(sizeof(struct AckQueue));
1841               ack->fragment_num = fh->fragment_off_or_num;
1842               ack2 = fm->head;
1843               while (ack2!=NULL){
1844                 if (ack2->fragment_num != ack->fragment_num)
1845                     {
1846                       if (ack2->fragment_num > ack->fragment_num)
1847                         {
1848                           GNUNET_CONTAINER_DLL_insert_before(fm->head,fm->tail,ack2,ack);
1849                           //check if finished
1850                           check_finished_fragment(plugin, fm);
1851                         }
1852                     }
1853                   else
1854                     {
1855                       //double ack
1856                       return;
1857                     }
1858                 ack2 = ack2->next;
1859               }
1860               GNUNET_CONTAINER_DLL_insert_tail(fm->head,fm->tail,ack);
1861               //should never happen but...
1862               check_finished_fragment(plugin, fm);
1863             }
1864           else
1865             {
1866               GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1867                   "WLAN fragment not in fragment list but id is right\n");
1868               return;
1869             }
1870
1871         }
1872
1873     }
1874
1875   else if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL)
1876     {
1877       //TODO more control
1878       if (ntohs(hdr->size) == 6)
1879         {
1880           plugin->mac_address = GNUNET_malloc(6);
1881           memcpy(plugin->mac_address, &hdr[1], 6);
1882           GNUNET_log(
1883               GNUNET_ERROR_TYPE_DEBUG,
1884               "Notifying transport of address %s\n",
1885               wlan_plugin_address_to_string(cls, plugin->mac_address, hdr->size));
1886           plugin->env->notify_address(plugin->env->cls, "wlan",
1887               &plugin->mac_address, sizeof(plugin->mac_address),
1888               GNUNET_TIME_UNIT_FOREVER_REL);
1889         }
1890       else
1891         {
1892           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Wrong wlan mac address %s\n",
1893               plugin->mac_address);
1894         }
1895
1896     }
1897
1898
1899   else
1900     {
1901       // TODO Wrong data?
1902       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "WLAN packet has not the right type\n");
1903       return;
1904     }
1905 }
1906
1907
1908 static void
1909 wlan_plugin_helper_read (void *cls,
1910                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1911 {
1912   struct Plugin *plugin = cls;
1913   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1914
1915   char mybuf[WLAN_MTU + sizeof(struct GNUNET_MessageHeader)];
1916   ssize_t bytes;
1917
1918   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1919     return;
1920
1921   bytes = GNUNET_DISK_file_read (plugin->server_stdout_handle, 
1922                                  mybuf, sizeof(mybuf));
1923   if (bytes <= 0)
1924     {
1925 #if DEBUG_wlan
1926       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1927                       _("Finished reading from wlan-helper stdout with code: %d\n"), bytes);
1928 #endif
1929       return;
1930     }
1931   GNUNET_SERVER_mst_receive(plugin->consoltoken, NULL,
1932                             mybuf, bytes, GNUNET_NO, GNUNET_NO);
1933
1934   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1935   plugin->server_read_task =
1936   GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1937                                   plugin->server_stdout_handle, &wlan_plugin_helper_read, plugin);
1938 }
1939
1940
1941 /**
1942  * Start the gnunet-wlan-helper process.
1943  *
1944  * @param plugin the transport plugin
1945  *
1946  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1947  */
1948 static int
1949 wlan_transport_start_wlan_helper(struct Plugin *plugin)
1950 {
1951
1952   plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
1953   if (plugin->server_stdout == NULL)
1954     return GNUNET_SYSERR;
1955
1956   plugin->server_stdin = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_NO);
1957   if (plugin->server_stdin == NULL)
1958     return GNUNET_SYSERR;
1959
1960 #if DEBUG_wlan
1961   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1962       "Starting gnunet-wlan-helper process cmd: %s %s\n", "gnunet-wlan-helper", plugin->interface);
1963 #endif
1964   /* Start the server process */
1965   plugin->server_proc = GNUNET_OS_start_process(plugin->server_stdin,
1966       plugin->server_stdout, "gnunet-transport-wlan-helper",
1967       "gnunet-transport-wlan-helper", plugin->interface, NULL);
1968   if (plugin->server_proc == NULL)
1969     {
1970 #if DEBUG_wlan
1971       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1972           "Failed to start gnunet-wlan-helper process\n");
1973 #endif
1974       return GNUNET_SYSERR;
1975     }
1976   /* Close the write end of the read pipe */
1977   GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1978
1979   /* Close the read end of the write pipe */
1980   GNUNET_DISK_pipe_close_end(plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1981
1982   plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout,
1983       GNUNET_DISK_PIPE_END_READ);
1984   plugin->server_stdin_handle = GNUNET_DISK_pipe_handle(plugin->server_stdin,
1985       GNUNET_DISK_PIPE_END_WRITE);
1986
1987   GNUNET_assert(plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1988   plugin->server_read_task = GNUNET_SCHEDULER_add_read_file(
1989       GNUNET_TIME_UNIT_FOREVER_REL, plugin->server_stdout_handle,
1990       &wlan_plugin_helper_read, plugin);
1991   return GNUNET_YES;
1992 }
1993
1994
1995
1996 /**
1997  * Entry point for the plugin.
1998  *
1999  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
2000  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
2001  */
2002 void *
2003 libgnunet_plugin_transport_wlan_init (void *cls)
2004 {
2005   struct GNUNET_SERVICE_Context *service;
2006   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2007   struct GNUNET_TRANSPORT_PluginFunctions *api;
2008   struct Plugin *plugin;
2009
2010   GNUNET_assert(cls !=NULL);
2011
2012   service = GNUNET_SERVICE_start ("transport-wlan", env->cfg);
2013         if (service == NULL){
2014                 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2015                            _("Failed to start service for `%s' transport plugin.\n"),
2016                            "wlan");
2017                 return NULL;
2018         }
2019
2020   plugin = GNUNET_malloc (sizeof (struct Plugin));
2021   plugin->env = env;
2022   plugin->pendingsessions = 0;
2023   plugin->session_count = 0;
2024   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2025   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
2026   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
2027
2028   wlan_transport_start_wlan_helper(plugin);
2029   plugin->consoltoken = GNUNET_SERVER_mst_create(&wlan_process_helper,plugin);
2030
2031   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2032   //plugin->pending_Sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
2033
2034   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2035   api->cls = plugin;
2036   api->send = &wlan_plugin_send;
2037   api->disconnect = &wlan_plugin_disconnect;
2038   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
2039   api->check_address = &wlan_plugin_address_suggested;
2040   api->address_to_string = &wlan_plugin_address_to_string;
2041
2042
2043   start_next_message_id();
2044
2045   return api;
2046 }
2047
2048
2049 /**
2050  * Exit point from the plugin.
2051  */
2052 //TODO doxigen
2053 //FIXME cleanup
2054 void *
2055 libgnunet_plugin_transport_wlan_done (void *cls)
2056 {
2057   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2058   struct Plugin *plugin = api->cls;
2059
2060   GNUNET_assert(cls !=NULL);
2061
2062   GNUNET_SERVER_mst_destroy(plugin->consoltoken);
2063
2064   GNUNET_free_non_null(plugin->mac_address);
2065   GNUNET_free (plugin);
2066   GNUNET_free (api);
2067   return NULL;
2068 }
2069
2070 /* end of plugin_transport_wlan.c */