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