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