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