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