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