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