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