bf5411d597938ab608a65590261bfc8e57a8c4ed
[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   {
1071     return;
1072   }
1073
1074   //cancel old task
1075   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1076   {
1077     GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
1078     plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1079   }
1080
1081   //check if some acks are in the queue
1082   if (plugin->ack_send_queue_head != NULL)
1083   {
1084     next_send = GNUNET_TIME_UNIT_ZERO;
1085   }
1086
1087   //check if there are some fragments in the queue
1088   else if (plugin->sending_messages_head != NULL)
1089   {
1090     next_send = GNUNET_TIME_UNIT_ZERO;
1091   }
1092   else
1093   {
1094     next_send = GNUNET_TIME_absolute_get_remaining (plugin->beacon_time);
1095   }
1096
1097 #if DEBUG_wlan
1098   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1099                    "Next packet is send in: %u\n", next_send.rel_value);
1100 #endif
1101
1102   if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
1103   {
1104     if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
1105     {
1106       plugin->server_write_task =
1107           GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1108                                            plugin->server_stdin_handle,
1109                                            &do_transmit, plugin);
1110     }
1111   }
1112   else
1113   {
1114     if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
1115     {
1116       plugin->server_write_delay_task =
1117           GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
1118                                         plugin);
1119     }
1120   }
1121 }
1122
1123 /**
1124  * Function to get the next queued Session, removes the session from the queue
1125  * @param plugin pointer to the plugin struct
1126  * @return pointer to the session found, returns NULL if there is now session in the queue
1127  */
1128 static struct Session *
1129 get_next_queue_session (struct Plugin *plugin)
1130 {
1131   struct Session *session;
1132   struct Sessionqueue *sessionqueue;
1133   struct Sessionqueue *sessionqueue_alt;
1134   struct PendingMessage *pm;
1135
1136   sessionqueue = plugin->pending_Sessions_head;
1137
1138   while (sessionqueue != NULL)
1139   {
1140     session = sessionqueue->content;
1141
1142     GNUNET_assert (session != NULL);
1143     pm = session->pending_message_head;
1144
1145     if (pm == NULL)
1146     {
1147 #if DEBUG_wlan
1148       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1149                        "pending message is empty, should not happen. session %p\n",
1150                        session);
1151 #endif
1152       sessionqueue_alt = sessionqueue;
1153       sessionqueue = sessionqueue->next;
1154       plugin->pendingsessions--;
1155       GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1156                              plugin->pendingsessions, GNUNET_NO);
1157       GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1158                                    plugin->pending_Sessions_tail,
1159                                    sessionqueue_alt);
1160
1161       GNUNET_free (sessionqueue_alt);
1162       continue;
1163
1164     }
1165
1166     //check for message timeout
1167     if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
1168     {
1169       //check if session has no message in the fragment queue
1170       if ((session->mac->fragment_messages_out_count <
1171            FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT) &&
1172           (session->fragment_messages_out_count <
1173            FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
1174       {
1175         plugin->pendingsessions--;
1176         GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1177                                plugin->pendingsessions, GNUNET_NO);
1178         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1179                                      plugin->pending_Sessions_tail,
1180                                      sessionqueue);
1181         GNUNET_free (sessionqueue);
1182
1183         return session;
1184       }
1185       else
1186       {
1187         sessionqueue = sessionqueue->next;
1188       }
1189     }
1190     else
1191     {
1192       GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1193                                    session->pending_message_tail, pm);
1194
1195       //call the cont func that it did not work
1196       if (pm->transmit_cont != NULL)
1197         pm->transmit_cont (pm->transmit_cont_cls, &(session->target),
1198                            GNUNET_SYSERR);
1199       GNUNET_free (pm->msg);
1200       GNUNET_free (pm);
1201
1202       if (session->pending_message_head == NULL)
1203       {
1204         sessionqueue_alt = sessionqueue;
1205         sessionqueue = sessionqueue->next;
1206         plugin->pendingsessions--;
1207         GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
1208                                plugin->pendingsessions, GNUNET_NO);
1209         GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
1210                                      plugin->pending_Sessions_tail,
1211                                      sessionqueue_alt);
1212
1213         GNUNET_free (sessionqueue_alt);
1214       }
1215     }
1216
1217   }
1218   return NULL;
1219 }
1220
1221 /**
1222  * frees the space of a message in the fragment queue (send queue)
1223  * @param plugin the plugin struct
1224  * @param fm message to free
1225  */
1226 static void
1227 free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
1228 {
1229   struct Session *session = fm->session;
1230   struct MacEndpoint *endpoint = session->mac;
1231   struct FragmentMessage_queue *fmq;
1232   struct FragmentMessage_queue *fmq_next;
1233
1234   fmq = plugin->sending_messages_head;
1235   while (fmq != NULL)
1236   {
1237     fmq_next = fmq->next;
1238     if (fmq->content == fm)
1239     {
1240       GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
1241                                    plugin->sending_messages_tail, fmq);
1242       GNUNET_free (fmq);
1243     }
1244     fmq = fmq_next;
1245   }
1246
1247   (session->mac->fragment_messages_out_count)--;
1248   session->fragment_messages_out_count--;
1249   plugin->pending_Fragment_Messages--;
1250   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
1251                          plugin->pending_Fragment_Messages, GNUNET_NO);
1252   GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
1253                                endpoint->sending_messages_tail, fm);
1254   GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
1255   if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1256   {
1257     GNUNET_SCHEDULER_cancel (fm->timeout_task);
1258     fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1259   }
1260
1261   GNUNET_free (fm);
1262
1263   queue_session (plugin, session);
1264 #if DEBUG_wlan
1265   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1266                    "Free pending fragment messages %p, session %p\n", fm,
1267                    session);
1268 #endif
1269 }
1270
1271 /**
1272  * function to fill the radiotap header
1273  * @param plugin pointer to the plugin struct
1274  * @param endpoint pointer to the endpoint
1275  * @param header pointer to the radiotap header
1276  * @return GNUNET_YES at success
1277  */
1278 static int
1279 getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
1280                    struct Radiotap_Send *header)
1281 {
1282
1283   if (endpoint != NULL)
1284   {
1285     header->rate = endpoint->rate;
1286     header->tx_power = endpoint->tx_power;
1287     header->antenna = endpoint->antenna;
1288   }
1289   else
1290   {
1291     header->rate = 255;
1292     header->tx_power = 0;
1293     header->antenna = 0;
1294   }
1295
1296   return GNUNET_YES;
1297 }
1298
1299 /**
1300  * function to generate the wlan hardware header for one packet
1301  * @param Header address to write the header to
1302  * @param to_mac_addr address of the recipient
1303  * @param plugin pointer to the plugin struct
1304  * @param size size of the whole packet, needed to calculate the time to send the packet
1305  * @return GNUNET_YES if there was no error
1306  */
1307 static int
1308 getWlanHeader (struct ieee80211_frame *Header,
1309                const struct MacAddress *to_mac_addr, struct Plugin *plugin,
1310                unsigned int size)
1311 {
1312   uint16_t *tmp16;
1313   const int rate = 11000000;
1314
1315   Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
1316   Header->i_fc[1] = 0x00;
1317   memcpy (&Header->i_addr3, &mac_bssid, sizeof (mac_bssid));
1318   memcpy (&Header->i_addr2, plugin->mac_address.mac,
1319           sizeof (plugin->mac_address));
1320   memcpy (&Header->i_addr1, to_mac_addr, sizeof (struct MacAddress));
1321
1322   tmp16 = (uint16_t *) Header->i_dur;
1323   *tmp16 = (uint16_t) htole16 ((size * 1000000) / rate + 290);
1324   Header->llc[0] = WLAN_LLC_DSAP_FIELD;
1325   Header->llc[1] = WLAN_LLC_SSAP_FIELD;
1326
1327 #if DEBUG_wlan_ip_udp_packets_on_air > 1
1328   uint crc = 0;
1329   uint16_t *x;
1330   int count;
1331
1332   Header->ip.ip_dst.s_addr = *((uint32_t *) & to_mac_addr->mac[2]);
1333   Header->ip.ip_src.s_addr = *((uint32_t *) & plugin->mac_address.mac[2]);
1334   Header->ip.ip_v = 4;
1335   Header->ip.ip_hl = 5;
1336   Header->ip.ip_p = 17;
1337   Header->ip.ip_ttl = 1;
1338   Header->ip.ip_len = htons (size + 8);
1339   Header->ip.ip_sum = 0;
1340   x = (uint16_t *) & Header->ip;
1341   count = sizeof (struct iph);
1342   while (count > 1)
1343   {
1344     /* This is the inner loop */
1345     crc += (unsigned short) *x++;
1346     count -= 2;
1347   }
1348   /* Add left-over byte, if any */
1349   if (count > 0)
1350     crc += *(unsigned char *) x;
1351   crc = (crc & 0xffff) + (crc >> 16);
1352   Header->ip.ip_sum = htons (~(unsigned short) crc);
1353   Header->udp.len = htons (size - sizeof (struct ieee80211_frame));
1354
1355 #endif
1356
1357   return GNUNET_YES;
1358 }
1359
1360
1361 /**
1362  * function to add a fragment of a message to send
1363  * @param cls FragmentMessage this message belongs to
1364  * @param hdr pointer to the start of the message
1365  */
1366 static void
1367 add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
1368 {
1369
1370   struct FragmentMessage *fm = cls;
1371   struct FragmentMessage_queue *fmqueue;
1372
1373   GNUNET_assert (cls != NULL);
1374   GNUNET_assert (fm->frag == NULL);
1375   struct MacEndpoint *endpoint = fm->session->mac;
1376   struct Plugin *plugin = endpoint->plugin;
1377   struct GNUNET_MessageHeader *msgheader;
1378   struct GNUNET_MessageHeader *msgheader2;
1379   uint16_t size;
1380
1381 #if DEBUG_wlan_retransmission > 1
1382   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1383                    "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
1384                    fm, fm->session, endpoint, hdr->type);
1385 #endif
1386
1387   size =
1388       sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1389       sizeof (struct ieee80211_frame) + ntohs (hdr->size);
1390   fm->frag = GNUNET_malloc (size);
1391   fm->size = size;
1392
1393   msgheader = (struct GNUNET_MessageHeader *) fm->frag;
1394   msgheader->size = htons (size);
1395   msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1396
1397   fm->radioHeader = (struct Radiotap_Send *) &msgheader[1];
1398   fm->ieeewlanheader = (struct ieee80211_frame *) &fm->radioHeader[1];
1399   msgheader2 = (struct GNUNET_MessageHeader *) &fm->ieeewlanheader[1];
1400   memcpy (msgheader2, hdr, ntohs (hdr->size));
1401
1402   fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue));
1403   fmqueue->content = fm;
1404
1405   GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head,
1406                                     plugin->sending_messages_tail, fmqueue);
1407   set_next_send (plugin);
1408 }
1409
1410
1411 /**
1412  * We have been notified that wlan-helper has written something to stdout.
1413  * Handle the output, then reschedule this function to be called again once
1414  * more is available.
1415  *
1416  * @param cls the plugin handle
1417  * @param tc the scheduling context
1418  */
1419 static void
1420 wlan_plugin_helper_read (void *cls,
1421                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1422 {
1423   struct Plugin *plugin = cls;
1424
1425   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1426
1427   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1428     return;
1429
1430   char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)];
1431   ssize_t bytes;
1432
1433   bytes =
1434       GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf,
1435                              sizeof (mybuf));
1436   if (bytes <= 0)
1437   {
1438 #if DEBUG_wlan
1439     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1440                      _
1441                      ("Finished reading from wlan-helper stdout with code: %d\n"),
1442                      bytes);
1443 #endif
1444     return;
1445   }
1446   GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes,
1447                              GNUNET_NO, GNUNET_NO);
1448
1449   GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1450   plugin->server_read_task =
1451       GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1452                                       plugin->server_stdout_handle,
1453                                       &wlan_plugin_helper_read, plugin);
1454 }
1455
1456 /**
1457  * Start the gnunet-wlan-helper process.
1458  *
1459  * @param plugin the transport plugin
1460  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1461  */
1462 static int
1463 wlan_transport_start_wlan_helper (struct Plugin *plugin)
1464 {
1465   const char *filenamehw = "gnunet-transport-wlan-helper";
1466   const char *filenameloopback = "gnunet-transport-wlan-helper-dummy";
1467   char *absolute_filename = NULL;
1468
1469   if (plugin->helper_is_running == GNUNET_YES)
1470   {
1471 #if DEBUG_wlan
1472     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1473                      "wlan_transport_start_wlan_helper not needed, helper already running!");
1474 #endif
1475     return GNUNET_YES;
1476   }
1477
1478   plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
1479   if (plugin->server_stdout == NULL)
1480     return GNUNET_SYSERR;
1481
1482   plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
1483   if (plugin->server_stdin == NULL)
1484     return GNUNET_SYSERR;
1485
1486   if ((plugin->testmode == 1) || (plugin->testmode == 2))
1487   {
1488     if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
1489     {
1490       absolute_filename = GNUNET_strdup (filenameloopback);
1491     }
1492     else
1493     {
1494       char cwd[FILENAME_MAX];
1495
1496       GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
1497
1498       GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
1499                        filenameloopback);
1500
1501       if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
1502       {
1503         GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1504                          "Helper `%s' not found! %i\n", absolute_filename);
1505         GNUNET_break (0);
1506       }
1507     }
1508   }
1509
1510   /* Start the server process */
1511
1512   if (plugin->testmode == 0)
1513   {
1514
1515 #if DEBUG_wlan
1516     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1517                      "Starting gnunet-wlan-helper process cmd: %s %s %i\n",
1518                      filenamehw, plugin->interface, plugin->testmode);
1519 #endif
1520
1521     if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES)
1522     {
1523       plugin->server_proc =
1524           GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
1525                                    filenamehw, filenamehw, plugin->interface,
1526                                    NULL);
1527     }
1528     else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO)
1529     {
1530       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1531                        "gnunet-transport-wlan-helper is not suid, please change it or look at the doku\n");
1532       GNUNET_break (0);
1533     }
1534     else
1535     {
1536       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1537                        "gnunet-transport-wlan-helper not found, please look if it exists and is the $PATH variable!\n");
1538       GNUNET_break (0);
1539     }
1540
1541   }
1542   else if (plugin->testmode == 1)
1543   {
1544
1545 #if DEBUG_wlan
1546     GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
1547                      "Starting gnunet-transport-wlan-helper-dummy loopback 1 process cmd: %s %s %i\n",
1548                      absolute_filename, plugin->interface, plugin->testmode);
1549 #endif
1550     plugin->server_proc =
1551         GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
1552                                  absolute_filename, absolute_filename, "1",
1553                                  NULL);
1554     if (plugin->server_proc == NULL)
1555     {
1556       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1557                        "`%s' not found, please look if it exists and is in the $PATH variable!\n",
1558                        absolute_filename);
1559       GNUNET_break (0);
1560     }
1561   }
1562   else if (plugin->testmode == 2)
1563   {
1564 #if DEBUG_wlan
1565     GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
1566                      "Starting gnunet-transport-wlan-helper-dummy loopback 2 process cmd: %s %s %i\n",
1567                      absolute_filename, plugin->interface, plugin->testmode);
1568 #endif
1569
1570     plugin->server_proc =
1571         GNUNET_OS_start_process (plugin->server_stdin, plugin->server_stdout,
1572                                  absolute_filename, absolute_filename, "2",
1573                                  NULL);
1574     if (plugin->server_proc == NULL)
1575     {
1576       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1577                        "`%s' not found, please look if it exists and is in the $PATH variable!\n",
1578                        absolute_filename);
1579       GNUNET_break (0);
1580     }
1581   }
1582   if (absolute_filename != NULL)
1583     GNUNET_free (absolute_filename);
1584   if (plugin->server_proc == NULL)
1585   {
1586 #if DEBUG_wlan
1587     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1588                      "Failed to start gnunet-transport-wlan-helper process\n");
1589 #endif
1590     return GNUNET_SYSERR;
1591   }
1592
1593
1594
1595   /* Close the write end of the read pipe */
1596   GNUNET_DISK_pipe_close_end (plugin->server_stdout,
1597                               GNUNET_DISK_PIPE_END_WRITE);
1598
1599   /* Close the read end of the write pipe */
1600   GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
1601
1602   plugin->server_stdout_handle =
1603       GNUNET_DISK_pipe_handle (plugin->server_stdout,
1604                                GNUNET_DISK_PIPE_END_READ);
1605   plugin->server_stdin_handle =
1606       GNUNET_DISK_pipe_handle (plugin->server_stdin,
1607                                GNUNET_DISK_PIPE_END_WRITE);
1608
1609   GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
1610
1611 #if DEBUG_wlan
1612   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1613                    "Adding server_read_task for the wlan-helper\n");
1614 #endif
1615
1616   plugin->server_read_task =
1617       GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1618                                       plugin->server_stdout_handle,
1619                                       &wlan_plugin_helper_read, plugin);
1620
1621   plugin->helper_is_running = GNUNET_YES;
1622   return GNUNET_YES;
1623 }
1624
1625 /**
1626  * Stops the gnunet-wlan-helper process.
1627  *
1628  * @param plugin the transport plugin
1629  * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
1630  */
1631 static int
1632 wlan_transport_stop_wlan_helper (struct Plugin *plugin)
1633 {
1634 #if DEBUG_wlan
1635   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1636                    "Stoping WLAN helper process\n");
1637 #endif
1638
1639   if (plugin->helper_is_running == GNUNET_NO)
1640   {
1641 #if DEBUG_wlan
1642     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1643                      "wlan_transport_stop_wlan_helper not needed, helper already stopped!");
1644 #endif
1645     return GNUNET_YES;
1646   }
1647
1648   if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
1649   {
1650     GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
1651     plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
1652   }
1653
1654   if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
1655   {
1656     GNUNET_SCHEDULER_cancel (plugin->server_write_task);
1657     plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1658   }
1659
1660   if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
1661   {
1662     GNUNET_SCHEDULER_cancel (plugin->server_read_task);
1663     plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
1664   }
1665
1666   GNUNET_DISK_pipe_close (plugin->server_stdout);
1667   GNUNET_DISK_pipe_close (plugin->server_stdin);
1668   GNUNET_OS_process_kill (plugin->server_proc, SIGKILL);
1669   GNUNET_OS_process_wait (plugin->server_proc);
1670   GNUNET_OS_process_close (plugin->server_proc);
1671
1672   plugin->helper_is_running = GNUNET_NO;
1673
1674   return GNUNET_YES;
1675 }
1676
1677 /**
1678  * function for delayed restart of the helper process
1679  * @param cls Finish_send struct if message should be finished
1680  * @param tc TaskContext
1681  */
1682 static void
1683 delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1684 {
1685   struct Finish_send *finish = cls;
1686   struct Plugin *plugin;
1687
1688   plugin = finish->plugin;
1689
1690   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1691   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1692   {
1693     GNUNET_free_non_null (finish->msgstart);
1694     GNUNET_free (finish);
1695     return;
1696   }
1697
1698   wlan_transport_start_wlan_helper (plugin);
1699
1700   if (finish->size != 0)
1701   {
1702     plugin->server_write_task =
1703         GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1704                                          plugin->server_stdin_handle,
1705                                          &finish_sending, finish);
1706   }
1707   else
1708   {
1709     set_next_send (plugin);
1710     GNUNET_free_non_null (finish->msgstart);
1711     GNUNET_free (finish);
1712   }
1713
1714 }
1715
1716 /**
1717  * Function to restart the helper
1718  * @param plugin pointer to the global plugin struct
1719  * @param finish pointer to the Finish_send struct to finish
1720  */
1721 static void
1722 restart_helper (struct Plugin *plugin, struct Finish_send *finish)
1723 {
1724   static struct GNUNET_TIME_Relative next_try = { 1000 };
1725   GNUNET_assert (finish != NULL);
1726
1727   wlan_transport_stop_wlan_helper (plugin);
1728   plugin->server_write_task =
1729       GNUNET_SCHEDULER_add_delayed (next_try, &delay_restart_helper, finish);
1730   GNUNET_TIME_relative_multiply (next_try, HELPER_RESTART_SCALING_FACTOR);
1731
1732 }
1733
1734 /**
1735  * function to finish a sending if not all could have been writen befor
1736  * @param cls pointer to the Finish_send struct
1737  * @param tc TaskContext
1738  */
1739 static void
1740 finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1741 {
1742   struct Finish_send *finish = cls;
1743   struct Plugin *plugin;
1744   ssize_t bytes;
1745
1746   plugin = finish->plugin;
1747   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
1748
1749   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1750   {
1751     GNUNET_free (finish->msgstart);
1752     GNUNET_free (finish);
1753     return;
1754   }
1755   bytes =
1756       GNUNET_DISK_file_write (plugin->server_stdin_handle,
1757                               finish->head_of_next_write, finish->size);
1758
1759   if (bytes != finish->size)
1760   {
1761     if (bytes != GNUNET_SYSERR)
1762     {
1763       finish->head_of_next_write += bytes;
1764       finish->size -= bytes;
1765       plugin->server_write_task =
1766           GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
1767                                            plugin->server_stdin_handle,
1768                                            &finish_sending, finish);
1769     }
1770     else
1771     {
1772       restart_helper (plugin, finish);
1773     }
1774   }
1775   else
1776   {
1777     GNUNET_free (finish->msgstart);
1778     GNUNET_free (finish);
1779     set_next_send (plugin);
1780   }
1781 }
1782
1783 /**
1784  * function to send a hello beacon
1785  * @param plugin pointer to the plugin struct
1786  */
1787 static void
1788 send_hello_beacon (struct Plugin *plugin)
1789 {
1790
1791 #if DEBUG_wlan
1792   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1793                    "Sending hello beacon\n");
1794 #endif
1795
1796   uint16_t size;
1797   ssize_t bytes;
1798   uint16_t hello_size;
1799   struct GNUNET_MessageHeader *msgheader;
1800   struct ieee80211_frame *ieeewlanheader;
1801   struct Radiotap_Send *radioHeader;
1802   struct GNUNET_MessageHeader *msgheader2;
1803   const struct GNUNET_MessageHeader *hello;
1804   struct Finish_send *finish;
1805
1806   GNUNET_assert (plugin != NULL);
1807
1808   GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"),
1809                             1, GNUNET_NO);
1810
1811   hello = plugin->env->get_our_hello ();
1812   hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1813   GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
1814   size =
1815       sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1816       sizeof (struct ieee80211_frame) + hello_size;
1817
1818   msgheader = GNUNET_malloc (size);
1819   msgheader->size = htons (size);
1820   msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1821
1822   radioHeader = (struct Radiotap_Send *) &msgheader[1];
1823   getRadiotapHeader (plugin, NULL, radioHeader);
1824   ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
1825   getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size);
1826
1827   msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
1828   /*msgheader2->size =
1829    * htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) +
1830    * sizeof (struct GNUNET_MessageHeader));
1831    *
1832    * msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); */
1833   memcpy (msgheader2, hello, hello_size);
1834
1835   bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size);
1836
1837   if (bytes == GNUNET_SYSERR)
1838   {
1839     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
1840                      _
1841                      ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
1842                      errno, strerror (errno));
1843     finish = GNUNET_malloc (sizeof (struct Finish_send));
1844     finish->plugin = plugin;
1845     finish->head_of_next_write = NULL;
1846     finish->size = 0;
1847     finish->msgstart = NULL;
1848     restart_helper (plugin, finish);
1849
1850     set_next_beacon_time (plugin);
1851
1852   }
1853   else
1854   {
1855     GNUNET_assert (bytes == size);
1856     set_next_beacon_time (plugin);
1857     set_next_send (plugin);
1858   }
1859   GNUNET_free (msgheader);
1860
1861
1862 }
1863
1864 /**
1865  * function to add an ack to send it for a received fragment
1866  * @param cls MacEndpoint this ack belongs to
1867  * @param msg_id id of the message
1868  * @param hdr pointer to the hdr where the ack is stored
1869  *
1870  */
1871 static void
1872 add_ack_for_send (void *cls, uint32_t msg_id,
1873                   const struct GNUNET_MessageHeader *hdr)
1874 {
1875
1876   struct AckSendQueue *ack;
1877
1878   GNUNET_assert (cls != NULL);
1879   struct MacEndpoint *endpoint = cls;
1880   struct Plugin *plugin = endpoint->plugin;
1881   struct GNUNET_MessageHeader *msgheader;
1882   struct GNUNET_MessageHeader *msgheader2;
1883   uint16_t size;
1884
1885   size =
1886       sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1887       sizeof (struct ieee80211_frame) + ntohs (hdr->size) +
1888       sizeof (struct AckSendQueue);
1889
1890   ack = GNUNET_malloc (size);
1891   ack->message_id = msg_id;
1892   ack->endpoint = endpoint;
1893
1894   size =
1895       sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
1896       sizeof (struct ieee80211_frame) + ntohs (hdr->size);
1897
1898   msgheader = (struct GNUNET_MessageHeader *) &ack[1];
1899   ack->hdr = (struct GNUNET_MessageHeader *) &ack[1];
1900   msgheader->size = htons (size);
1901   msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
1902
1903   ack->radioHeader = (struct Radiotap_Send *) &msgheader[1];
1904   ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1];
1905   msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1];
1906   memcpy (msgheader2, hdr, ntohs (hdr->size));
1907
1908   GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
1909                                     plugin->ack_send_queue_tail, ack);
1910
1911 #if DEBUG_wlan_retransmission > 1
1912   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1913                    "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
1914                    msg_id, ack, endpoint);
1915 #endif
1916
1917   set_next_send (plugin);
1918 }
1919
1920 /**
1921  * Function for the scheduler if a FragmentMessage times out
1922  * @param cls pointer to the FragmentMessage
1923  * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
1924  */
1925 static void
1926 fragmentmessage_timeout (void *cls,
1927                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1928 {
1929   struct FragmentMessage *fm = cls;
1930
1931   GNUNET_assert (fm != NULL);
1932   fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1933   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1934   {
1935     return;
1936   }
1937   free_fragment_message (fm->session->mac->plugin, fm);
1938 }
1939
1940 /**
1941  * Function to check if there is some space in the fragment queue
1942  * inserts a message if space is available
1943  * @param plugin the plugin struct
1944  */
1945
1946 static void
1947 check_fragment_queue (struct Plugin *plugin)
1948 {
1949   struct Session *session;
1950   struct FragmentMessage *fm;
1951   struct GNUNET_PeerIdentity pid;
1952
1953   struct PendingMessage *pm;
1954
1955   if (plugin->pending_Fragment_Messages < FRAGMENT_QUEUE_SIZE)
1956   {
1957     session = get_next_queue_session (plugin);
1958     if (session != NULL)
1959     {
1960       pm = session->pending_message_head;
1961       GNUNET_assert (pm != NULL);
1962       GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
1963                                    session->pending_message_tail, pm);
1964       session->mac->fragment_messages_out_count++;
1965       session->fragment_messages_out_count++;
1966       plugin->pending_Fragment_Messages++;
1967       GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
1968                              plugin->pending_Fragment_Messages, GNUNET_NO);
1969
1970       fm = GNUNET_malloc (sizeof (struct FragmentMessage));
1971       fm->session = session;
1972       fm->timeout.abs_value = pm->timeout.abs_value;
1973       fm->frag = NULL;
1974       fm->fragcontext =
1975           GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
1976                                           &plugin->tracker,
1977                                           GNUNET_TIME_UNIT_SECONDS,
1978                                           &(pm->msg->header),
1979                                           &add_message_for_send, fm);
1980       fm->timeout_task =
1981           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
1982                                         (fm->timeout), fragmentmessage_timeout,
1983                                         fm);
1984       GNUNET_CONTAINER_DLL_insert_tail (session->mac->sending_messages_head,
1985                                         session->mac->sending_messages_tail,
1986                                         fm);
1987
1988       if (pm->transmit_cont != NULL)
1989       {
1990         pid = session->target;
1991         pm->transmit_cont (pm->transmit_cont_cls, &pid, GNUNET_OK);
1992 #if DEBUG_wlan
1993         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
1994                          "called pm->transmit_cont for %p\n", session);
1995 #endif
1996       }
1997       else
1998       {
1999 #if DEBUG_wlan
2000         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2001                          "no pm->transmit_cont for %p\n", session);
2002 #endif
2003       }
2004       GNUNET_free (pm);
2005
2006       if (session->pending_message_head != NULL)
2007       {
2008         //requeue session
2009         queue_session (plugin, session);
2010       }
2011
2012     }
2013   }
2014
2015   //check if timeout changed
2016   set_next_send (plugin);
2017 }
2018
2019 /**
2020  * Function to send an ack, does not free the ack
2021  * @param plugin pointer to the plugin
2022  */
2023 static void
2024 send_ack (struct Plugin *plugin)
2025 {
2026
2027   ssize_t bytes;
2028   struct AckSendQueue *ack;
2029   struct Finish_send *finish;
2030
2031   ack = plugin->ack_send_queue_head;
2032
2033
2034 #if DEBUG_wlan
2035   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2036                    "Sending ack for message_id %u for mac endpoint %p, size %u\n",
2037                    ack->message_id, ack->endpoint,
2038                    ntohs (ack->hdr->size) - sizeof (struct Radiotap_Send));
2039 #endif
2040
2041   GNUNET_assert (plugin != NULL);
2042   GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1,
2043                             GNUNET_NO);
2044
2045   getRadiotapHeader (plugin, ack->endpoint, ack->radioHeader);
2046   getWlanHeader (ack->ieeewlanheader, &ack->endpoint->addr, plugin,
2047                  ntohs (ack->hdr->size));
2048
2049   bytes =
2050       GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->hdr,
2051                               ntohs (ack->hdr->size));
2052   if (bytes == GNUNET_SYSERR)
2053   {
2054     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2055                      _
2056                      ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
2057                      errno, strerror (errno));
2058     finish = GNUNET_malloc (sizeof (struct Finish_send));
2059     finish->plugin = plugin;
2060     finish->head_of_next_write = NULL;
2061     finish->size = 0;
2062     finish->msgstart = NULL;
2063     restart_helper (plugin, finish);
2064   }
2065   else
2066   {
2067     GNUNET_assert (bytes == ntohs (ack->hdr->size));
2068     GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
2069                                  plugin->ack_send_queue_tail, ack);
2070     GNUNET_free (ack);
2071     set_next_send (plugin);
2072   }
2073 }
2074
2075 /**
2076  * Function called when wlan helper is ready to get some data
2077  *
2078  * @param cls closure
2079  * @param tc GNUNET_SCHEDULER_TaskContext
2080  */
2081 static void
2082 do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2083 {
2084   struct Plugin *plugin = cls;
2085
2086   GNUNET_assert (plugin != NULL);
2087
2088   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
2089   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2090     return;
2091
2092   struct Session *session;
2093   struct FragmentMessage *fm;
2094   struct Finish_send *finish;
2095   struct FragmentMessage_queue *fmq;
2096   ssize_t bytes;
2097
2098   if (plugin->ack_send_queue_head != NULL)
2099   {
2100     send_ack (plugin);
2101     return;
2102   }
2103
2104   //test if a "hello-beacon" has to be send
2105   if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0)
2106   {
2107     send_hello_beacon (plugin);
2108     return;
2109   }
2110
2111   if (plugin->sending_messages_head != NULL)
2112   {
2113     GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan fragments send"), 1,
2114                               GNUNET_NO);
2115
2116     fmq = plugin->sending_messages_head;
2117     fm = fmq->content;
2118     GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
2119                                  plugin->sending_messages_tail, fmq);
2120     GNUNET_free (fmq);
2121
2122     session = fm->session;
2123     GNUNET_assert (session != NULL);
2124
2125 #if DEBUG_wlan
2126     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2127                      "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT for fragment message %p, size: %u\n",
2128                      fm, fm->size);
2129 #endif
2130
2131     getRadiotapHeader (plugin, session->mac, fm->radioHeader);
2132     getWlanHeader (fm->ieeewlanheader, &(fm->session->mac->addr), plugin,
2133                    fm->size);
2134
2135     bytes =
2136         GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag,
2137                                 fm->size);
2138
2139
2140     if (bytes != fm->size)
2141     {
2142       finish = GNUNET_malloc (sizeof (struct Finish_send));
2143       finish->plugin = plugin;
2144       finish->msgstart = (struct GNUNET_MessageHeader *) fm->frag;
2145       GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
2146
2147       if (bytes == GNUNET_SYSERR)
2148       {
2149         GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2150                          _
2151                          ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
2152                          errno, strerror (errno));
2153
2154         finish->head_of_next_write = fm->frag;
2155         finish->size = fm->size;
2156         restart_helper (plugin, finish);
2157       }
2158       else
2159       {
2160         finish->head_of_next_write = fm->frag + bytes;
2161         finish->size = fm->size - bytes;
2162         plugin->server_write_task =
2163             GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
2164                                              plugin->server_stdin_handle,
2165                                              &finish_sending, finish);
2166       }
2167
2168       fm->frag = NULL;
2169     }
2170     else
2171     {
2172       GNUNET_free (fm->frag);
2173       fm->frag = NULL;
2174       set_next_send (plugin);
2175     }
2176     GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
2177     return;
2178   }
2179
2180 #if 1
2181   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2182                    "do_transmit did nothing, should not happen!\n");
2183 #endif
2184   set_next_send (plugin);
2185 }
2186
2187 /**
2188  * Another peer has suggested an address for this
2189  * peer and transport plugin.  Check that this could be a valid
2190  * address.  If so, consider adding it to the list
2191  * of addresses.
2192  *
2193  * @param cls closure
2194  * @param addr pointer to the address
2195  * @param addrlen length of addr
2196  * @return GNUNET_OK if this is a plausible address for this peer
2197  *         and transport
2198  */
2199 static int
2200 wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
2201 {
2202   //struct Plugin *plugin = cls;
2203
2204   /* check if the address is plausible; if so,
2205    * add it to our list! */
2206
2207   GNUNET_assert (cls != NULL);
2208   //FIXME mitm is not checked
2209   //Mac Address has 6 bytes
2210   if (addrlen == 6)
2211   {
2212     /* TODO check for bad addresses like multicast, broadcast, etc */
2213 #if DEBUG_wlan
2214     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2215                      "wlan_plugin_address_suggested got good address, size %u!\n",
2216                      addrlen);
2217 #endif
2218     return GNUNET_OK;
2219   }
2220 #if DEBUG_wlan
2221   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2222                    "wlan_plugin_address_suggested got bad address, size %u!\n",
2223                    addrlen);
2224 #endif
2225   return GNUNET_SYSERR;
2226 }
2227
2228 /**
2229  * Function that can be used by the transport service to transmit
2230  * a message using the plugin.
2231  *
2232  * @param cls closure
2233  * @param target who should receive this message
2234  * @param priority how important is the message
2235  * @param msgbuf the message to transmit
2236  * @param msgbuf_size number of bytes in 'msgbuf'
2237  * @param timeout when should we time out
2238  * @param session which session must be used (or NULL for "any")
2239  * @param addr the address to use (can be NULL if the plugin
2240  *                is "on its own" (i.e. re-use existing TCP connection))
2241  * @param addrlen length of the address in bytes
2242  * @param force_address GNUNET_YES if the plugin MUST use the given address,
2243  *                otherwise the plugin may use other addresses or
2244  *                existing connections (if available)
2245  * @param cont continuation to call once the message has
2246  *        been transmitted (or if the transport is ready
2247  *        for the next transmission call; or if the
2248  *        peer disconnected...)
2249  * @param cont_cls closure for cont
2250  * @return number of bytes used (on the physical network, with overheads);
2251  *         -1 on hard errors (i.e. address invalid); 0 is a legal value
2252  *         and does NOT mean that the message was not transmitted (DV)
2253  */
2254 static ssize_t
2255 wlan_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
2256                   const char *msgbuf, size_t msgbuf_size, unsigned int priority,
2257                   struct GNUNET_TIME_Relative timeout, struct Session *session,
2258                   const void *addr, size_t addrlen, int force_address,
2259                   GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
2260 {
2261   struct Plugin *plugin = cls;
2262   struct PendingMessage *newmsg;
2263   struct WlanHeader *wlanheader;
2264
2265   GNUNET_assert (plugin != NULL);
2266   //check if msglen > 0
2267   GNUNET_assert (msgbuf_size > 0);
2268
2269   //get session if needed
2270   if (session == NULL)
2271   {
2272     if (wlan_plugin_address_suggested (plugin, addr, addrlen) == GNUNET_OK)
2273     {
2274       session = get_session (plugin, addr, target);
2275     }
2276     else
2277     {
2278       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
2279                        _("Wlan Address len %d is wrong\n"), addrlen);
2280       return -1;
2281     }
2282   }
2283
2284   GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan messages queued"), 1,
2285                             GNUNET_NO);
2286
2287   //queue message:
2288
2289   //queue message in session
2290   //test if there is no other message in the "queue"
2291   //FIXME: to many send requests
2292   if (session->pending_message_head != NULL)
2293   {
2294     newmsg = session->pending_message_head;
2295     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2296                      "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",
2297                      GNUNET_TIME_absolute_get_remaining (newmsg->
2298                                                          timeout).rel_value,
2299                      session->mac->fragment_messages_out_count);
2300   }
2301
2302   newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
2303   newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
2304   wlanheader = newmsg->msg;
2305   //copy msg to buffer, not fragmented / segmented yet, but with message header
2306   wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
2307   wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
2308   memcpy (&(wlanheader->target), target, sizeof (struct GNUNET_PeerIdentity));
2309   memcpy (&(wlanheader->source), plugin->env->my_identity,
2310           sizeof (struct GNUNET_PeerIdentity));
2311   wlanheader->crc = 0;
2312   memcpy (&wlanheader[1], msgbuf, msgbuf_size);
2313   wlanheader->crc =
2314       htonl (GNUNET_CRYPTO_crc32_n
2315              ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
2316
2317   newmsg->transmit_cont = cont;
2318   newmsg->transmit_cont_cls = cont_cls;
2319   newmsg->timeout = GNUNET_TIME_relative_to_absolute (timeout);
2320
2321   newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
2322
2323   newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
2324
2325   GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
2326                                     session->pending_message_tail, newmsg);
2327
2328 #if DEBUG_wlan
2329   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2330                    "New message for %p with size (incl wlan header) %u added\n",
2331                    session, newmsg->message_size);
2332 #endif
2333 #if DEBUG_wlan_msg_dump > 1
2334   hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
2335 #endif
2336   //queue session
2337   queue_session (plugin, session);
2338
2339   check_fragment_queue (plugin);
2340   //FIXME not the correct size
2341   return msgbuf_size;
2342
2343 }
2344
2345 /**
2346  * function to free a mac endpoint
2347  * @param plugin pointer to the plugin struct
2348  * @param endpoint pointer to the MacEndpoint to free
2349  */
2350 static void
2351 free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
2352 {
2353   struct Sessionqueue *sessions;
2354   struct Sessionqueue *sessions_next;
2355
2356   GNUNET_assert (endpoint != NULL);
2357
2358   sessions = endpoint->sessions_head;
2359   while (sessions != NULL)
2360   {
2361     sessions_next = sessions->next;
2362     free_session (plugin, sessions, GNUNET_NO);
2363     sessions = sessions_next;
2364   }
2365
2366   GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint);
2367   if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2368   {
2369     GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
2370     endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2371   }
2372   plugin->mac_count--;
2373   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
2374                          plugin->mac_count, GNUNET_NO);
2375   GNUNET_free (endpoint);
2376
2377 }
2378
2379 /**
2380  * function to free a session
2381  * @param plugin pointer to the plugin
2382  * @param queue pointer to the sessionqueue element to free
2383  * @param do_free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
2384  */
2385 static void
2386 free_session (struct Plugin *plugin, struct Sessionqueue *queue,
2387               int do_free_macendpoint)
2388 {
2389   struct Sessionqueue *pendingsession;
2390   struct Sessionqueue *pendingsession_tmp;
2391   struct PendingMessage *pm;
2392   struct MacEndpoint *endpoint;
2393   struct FragmentMessage *fm;
2394   struct FragmentMessage *fmnext;
2395   int check = 0;
2396
2397   GNUNET_assert (plugin != NULL);
2398   GNUNET_assert (queue != NULL);
2399   GNUNET_assert (queue->content != NULL);
2400
2401   //session found
2402   //is this session pending for send
2403   pendingsession = plugin->pending_Sessions_head;
2404   while (pendingsession != NULL)
2405   {
2406     pendingsession_tmp = pendingsession;
2407     pendingsession = pendingsession->next;
2408     GNUNET_assert (pendingsession_tmp->content != NULL);
2409     if (pendingsession_tmp->content == queue->content)
2410     {
2411       plugin->pendingsessions--;
2412       GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
2413                              plugin->pendingsessions, GNUNET_NO);
2414       GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
2415                                    plugin->pending_Sessions_tail,
2416                                    pendingsession_tmp);
2417       GNUNET_free (pendingsession_tmp);
2418
2419       GNUNET_assert (check == 0);
2420       check = 1;
2421     }
2422   }
2423
2424   endpoint = queue->content->mac;
2425   fm = endpoint->sending_messages_head;
2426   while (fm != NULL)
2427   {
2428     fmnext = fm->next;
2429     if (fm->session == queue->content)
2430     {
2431       free_fragment_message (plugin, fm);
2432     }
2433     fm = fmnext;
2434   }
2435
2436   // remove PendingMessage
2437   pm = queue->content->pending_message_head;
2438   while (pm != NULL)
2439   {
2440     GNUNET_CONTAINER_DLL_remove (queue->content->pending_message_head,
2441                                  queue->content->pending_message_tail, pm);
2442     GNUNET_free (pm->msg);
2443     GNUNET_free (pm);
2444     pm = queue->content->pending_message_head;
2445   }
2446
2447   GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail,
2448                                queue);
2449   //Check that no ohter session on this endpoint for this session exits
2450   GNUNET_assert (search_session (plugin, endpoint, &queue->content->target) ==
2451                  NULL);
2452   if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
2453   {
2454     free_macendpoint (plugin, endpoint);
2455     //check if no endpoint with the same address exists
2456     GNUNET_assert (get_macendpoint (plugin, &endpoint->addr, GNUNET_NO) ==
2457                    NULL);
2458   }
2459
2460   if (queue->content->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2461   {
2462     GNUNET_SCHEDULER_cancel (queue->content->timeout_task);
2463     queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2464   }
2465   GNUNET_free (queue);
2466
2467   check_fragment_queue (plugin);
2468 }
2469
2470 /**
2471  * Function that can be used to force the plugin to disconnect
2472  * from the given peer and cancel all previous transmissions
2473  * (and their continuation).
2474  *
2475  * @param cls closure
2476  * @param target peer from which to disconnect
2477  */
2478 static void
2479 wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
2480 {
2481   struct Plugin *plugin = cls;
2482   struct Sessionqueue *queue;
2483   struct Sessionqueue *queue_next;
2484   struct MacEndpoint *endpoint = plugin->mac_head;
2485   struct MacEndpoint *endpoint_next;
2486
2487   // just look at all the session for the needed one
2488   while (endpoint != NULL)
2489   {
2490     queue = endpoint->sessions_head;
2491     endpoint_next = endpoint->next;
2492     while (queue != NULL)
2493     {
2494       // content is never NULL
2495       GNUNET_assert (queue->content != NULL);
2496       queue_next = queue->next;
2497       if (memcmp
2498           (target, &(queue->content->target),
2499            sizeof (struct GNUNET_PeerIdentity)) == 0)
2500       {
2501         free_session (plugin, queue, GNUNET_YES);
2502       }
2503       // try next
2504       queue = queue_next;
2505     }
2506     endpoint = endpoint_next;
2507   }
2508 }
2509
2510 /**
2511  * Convert the transports address to a nice, human-readable
2512  * format.
2513  *
2514  * @param cls closure
2515  * @param type name of the transport that generated the address
2516  * @param addr one of the addresses of the host, NULL for the last address
2517  *        the specific address format depends on the transport
2518  * @param addrlen length of the address
2519  * @param numeric should (IP) addresses be displayed in numeric form?
2520  * @param timeout after how long should we give up?
2521  * @param asc function to call on each string
2522  * @param asc_cls closure for asc
2523  */
2524 static void
2525 wlan_plugin_address_pretty_printer (void *cls, const char *type,
2526                                     const void *addr, size_t addrlen,
2527                                     int numeric,
2528                                     struct GNUNET_TIME_Relative timeout,
2529                                     GNUNET_TRANSPORT_AddressStringCallback asc,
2530                                     void *asc_cls)
2531 {
2532   char *ret;
2533   const unsigned char *input;
2534
2535   //GNUNET_assert(cls !=NULL);
2536   if (addrlen != sizeof (struct MacAddress))
2537   {
2538     /* invalid address (MAC addresses have 6 bytes) */
2539     //GNUNET_break (0);
2540 #if DEBUG_wlan
2541     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2542                      "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
2543                      addrlen);
2544 #endif
2545     asc (asc_cls, NULL);
2546     return;
2547   }
2548   input = (const unsigned char *) addr;
2549   GNUNET_asprintf (&ret,
2550                    "Transport %s: %s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
2551                    type, PROTOCOL_PREFIX, input[0], input[1], input[2],
2552                    input[3], input[4], input[5]);
2553 #if DEBUG_wlan
2554   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2555                    "Func wlan_plugin_address_pretty_printer got size: %u, nummeric %u, type %s; made string: %s\n",
2556                    addrlen, numeric, type, ret);
2557 #endif
2558   asc (asc_cls, ret);
2559   //only one mac address per plugin
2560   asc (asc_cls, NULL);
2561 }
2562
2563
2564
2565 /**
2566  * handels the data after all fragments are put together
2567  * @param cls macendpoint this messages belongs to
2568  * @param hdr pointer to the data
2569  */
2570 static void
2571 wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
2572 {
2573   struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
2574   struct Plugin *plugin = endpoint->plugin;
2575   struct WlanHeader *wlanheader;
2576   struct Session *session;
2577
2578   const struct GNUNET_MessageHeader *temp_hdr;
2579   struct GNUNET_PeerIdentity tmpsource;
2580   int crc;
2581
2582   GNUNET_assert (plugin != NULL);
2583
2584   if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
2585   {
2586
2587 #if DEBUG_wlan
2588     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2589                      "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
2590                      ntohs (hdr->size));
2591 #endif
2592
2593     if (ntohs (hdr->size) <
2594         sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
2595     {
2596       //packet not big enought
2597       return;
2598     }
2599
2600     GNUNET_STATISTICS_update (plugin->env->stats,
2601                               _("# wlan whole messages received"), 1,
2602                               GNUNET_NO);
2603     wlanheader = (struct WlanHeader *) hdr;
2604
2605     session = search_session (plugin, endpoint, &wlanheader->source);
2606
2607     temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
2608     crc = ntohl (wlanheader->crc);
2609     wlanheader->crc = 0;
2610     if (GNUNET_CRYPTO_crc32_n
2611         ((char *) wlanheader, ntohs (wlanheader->header.size)) != crc)
2612     {
2613       //wrong crc, dispose message
2614       GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2615                        "Wlan message header crc was wrong: %u != %u\n",
2616                        GNUNET_CRYPTO_crc32_n ((char *) wlanheader,
2617                                               ntohs (wlanheader->header.size)),
2618                        crc);
2619       hexdump ((void *) hdr, ntohs (hdr->size));
2620       return;
2621     }
2622
2623     //if not in session list
2624     if (session == NULL)
2625     {
2626 #if DEBUG_wlan
2627       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2628                        "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
2629                        ntohs (wlanheader->header.size), ntohs (temp_hdr->size),
2630                        sizeof (struct WlanHeader));
2631 #endif
2632       //try if it is a hello message
2633       if (ntohs (wlanheader->header.size) >=
2634           ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
2635       {
2636         if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2637         {
2638           if (GNUNET_HELLO_get_id
2639               ((const struct GNUNET_HELLO_Message *) temp_hdr,
2640                &tmpsource) == GNUNET_OK)
2641           {
2642             session = create_session (plugin, endpoint, &tmpsource);
2643           }
2644           else
2645           {
2646             GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2647                              "WLAN client not in session list and hello message is not okay\n");
2648             return;
2649           }
2650
2651         }
2652         else
2653         {
2654           GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2655                            "WLAN client not in session list and not a hello message\n");
2656           return;
2657         }
2658       }
2659       else
2660       {
2661         GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2662                          "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
2663                          ntohs (wlanheader->header.size),
2664                          ntohs (temp_hdr->size), sizeof (struct WlanHeader));
2665         return;
2666       }
2667     }
2668
2669     //"receive" the message
2670
2671     if (memcmp
2672         (&wlanheader->source, &session->target,
2673          sizeof (struct GNUNET_PeerIdentity)) != 0)
2674     {
2675       //wrong peer id
2676 #if DEBUG_wlan
2677       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2678                        "WLAN peer source id doesn't match packet peer source id: session %p\n",
2679                        session);
2680 #endif
2681       return;
2682     }
2683
2684     if (memcmp
2685         (&wlanheader->target, plugin->env->my_identity,
2686          sizeof (struct GNUNET_PeerIdentity)) != 0)
2687     {
2688       //wrong peer id
2689 #if DEBUG_wlan
2690       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2691                        "WLAN peer target id doesn't match our peer id: session %p\n",
2692                        session);
2693 #endif
2694       return;
2695     }
2696
2697     GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
2698                                (const char *) temp_hdr,
2699                                ntohs (hdr->size) - sizeof (struct WlanHeader),
2700                                GNUNET_YES, GNUNET_NO);
2701
2702     return;
2703   }
2704   else
2705   {
2706     GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2707                      "wlan_data_message_handler got wrong message type: %u\n",
2708                      ntohs (hdr->size));
2709     return;
2710   }
2711 }
2712
2713 /**
2714  * function to process the a message, give it to the higher layer
2715  * @param cls pointer to the plugin
2716  * @param client pointer to the session this message belongs to
2717  * @param hdr start of the message
2718  */
2719 //TODO ATS informations
2720 static void
2721 process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
2722 {
2723
2724   GNUNET_assert (client != NULL);
2725   GNUNET_assert (cls != NULL);
2726   struct Session *session = (struct Session *) client;
2727   struct Plugin *plugin = (struct Plugin *) cls;
2728
2729   struct GNUNET_ATS_Information distance;
2730
2731   distance.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
2732   distance.value = htonl (1);
2733
2734 #if DEBUG_wlan
2735   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2736                    "Calling plugin->env->receive for session %p; %s; size: %u\n",
2737                    session, wlan_plugin_address_to_string (NULL,
2738                                                            session->mac->
2739                                                            addr.mac, 6),
2740                    htons (hdr->size));
2741 #endif
2742
2743   plugin->env->receive (plugin->env->cls, &(session->target), hdr,
2744                         (const struct GNUNET_ATS_Information *) &distance, 1,
2745                         session, (const char *) &session->mac->addr,
2746                         sizeof (session->mac->addr));
2747 }
2748
2749 /**
2750  * Function used for to process the data received from the wlan interface
2751  *
2752  * @param cls the plugin handle
2753  * @param session_light pointer to the struct holding known informations
2754  * @param hdr hdr of the GNUNET_MessageHeader
2755  * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS for info
2756  */
2757 static void
2758 wlan_data_helper (void *cls, struct Session_light *session_light,
2759                   const struct GNUNET_MessageHeader *hdr,
2760                   const struct Radiotap_rx *rxinfo)
2761 {
2762   struct Plugin *plugin = cls;
2763   struct FragmentMessage *fm;
2764   struct FragmentMessage *fm2;
2765   struct GNUNET_PeerIdentity tmpsource;
2766
2767   GNUNET_assert (plugin != NULL);
2768
2769   //ADVERTISEMENT
2770   if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
2771   {
2772
2773     //TODO better DOS protection, error handling
2774     //TODO test first than create session
2775     GNUNET_assert (session_light != NULL);
2776
2777 #if DEBUG_wlan
2778     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2779                      "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_HELLO size: %u; %s\n",
2780                      ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2781                                                                        session_light->addr.
2782                                                                        mac, 6));
2783 #endif
2784
2785     if (session_light->macendpoint == NULL)
2786     {
2787       session_light->macendpoint =
2788           get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
2789     }
2790
2791
2792     if (GNUNET_HELLO_get_id
2793         ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
2794     {
2795       session_light->session =
2796           search_session (plugin, session_light->macendpoint, &tmpsource);
2797       if (session_light->session == NULL)
2798       {
2799         session_light->session =
2800             create_session (plugin, session_light->macendpoint, &tmpsource);
2801       }
2802       GNUNET_STATISTICS_update (plugin->env->stats,
2803                                 _("# wlan hello messages received"), 1,
2804                                 GNUNET_NO);
2805       plugin->env->receive (plugin->env->cls, &session_light->session->target,
2806                             hdr, NULL, 0, session_light->session,
2807                             (const char *) &session_light->session->mac->addr,
2808                             sizeof (session_light->session->mac->addr));
2809     }
2810     else
2811     {
2812       GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
2813                        "WLAN client not in session list and hello message is not okay\n");
2814       return;
2815     }
2816   }
2817
2818   //FRAGMENT
2819
2820   else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT)
2821   {
2822
2823     GNUNET_assert (session_light != NULL);
2824     if (session_light->macendpoint == NULL)
2825     {
2826       session_light->macendpoint =
2827           get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
2828     }
2829
2830 #if DEBUG_wlan
2831     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2832                      "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT with size: %u; mac endpoint %p: %s\n",
2833                      ntohs (hdr->size), session_light->macendpoint,
2834                      wlan_plugin_address_to_string (NULL,
2835                                                     session_light->addr.mac,
2836                                                     6));
2837 #endif
2838
2839     GNUNET_STATISTICS_update (plugin->env->stats,
2840                               _("# wlan fragments received"), 1, GNUNET_NO);
2841     int ret =
2842         GNUNET_DEFRAGMENT_process_fragment (session_light->macendpoint->defrag,
2843                                             hdr);
2844
2845     if (ret == GNUNET_NO)
2846     {
2847       session_light->macendpoint->dups++;
2848     }
2849     else if (ret == GNUNET_OK)
2850     {
2851       session_light->macendpoint->fragc++;
2852     }
2853     set_next_send (plugin);
2854
2855   }
2856
2857   //ACK
2858
2859   else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT_ACK)
2860   {
2861     GNUNET_assert (session_light != NULL);
2862     if (session_light->macendpoint == NULL)
2863     {
2864       session_light->macendpoint =
2865           get_macendpoint (plugin, &session_light->addr, GNUNET_NO);
2866     }
2867
2868     if (session_light->macendpoint == NULL)
2869     {
2870 #if DEBUG_wlan
2871       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2872                        "Macendpoint does not exist for this GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; %s\n",
2873                        ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
2874                                                                          session_light->addr.mac,
2875                                                                          6));
2876 #endif
2877       return;
2878     }
2879
2880 #if DEBUG_wlan
2881     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2882                      "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; mac endpoint: %p; %s\n",
2883                      ntohs (hdr->size), session_light->macendpoint,
2884                      wlan_plugin_address_to_string (NULL,
2885                                                     session_light->addr.mac,
2886                                                     6));
2887 #endif
2888     fm = session_light->macendpoint->sending_messages_head;
2889     while (fm != NULL)
2890     {
2891       fm2 = fm->next;
2892       GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks received"),
2893                                 1, GNUNET_NO);
2894       int ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
2895
2896       if (ret == GNUNET_OK)
2897       {
2898 #if DEBUG_wlan_retransmission > 1
2899         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2900                          "Got last ack, finished fragment message %p\n", fm);
2901 #endif
2902         session_light->macendpoint->acks++;
2903         fm->session->last_activity = GNUNET_TIME_absolute_get ();
2904         session_light->macendpoint->last_activity = fm->session->last_activity;
2905         free_fragment_message (plugin, fm);
2906         check_fragment_queue (plugin);
2907         return;
2908       }
2909       if (ret == GNUNET_NO)
2910       {
2911 #if DEBUG_wlan_retransmission > 1
2912         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2913                          "Got ack for: %p\n", fm);
2914 #endif
2915         session_light->macendpoint->acks++;
2916         return;
2917       }
2918       if (ret == GNUNET_SYSERR)
2919       {
2920
2921       }
2922
2923       fm = fm2;
2924     }
2925
2926 #if DEBUG_wlan_retransmission > 1
2927     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2928                      "WLAN fragment not in fragment list\n");
2929 #endif
2930     return;
2931
2932   }
2933   else
2934   {
2935     // TODO Wrong data?
2936     GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
2937                      "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
2938                      ntohs (hdr->type), ntohs (hdr->size));
2939     GNUNET_break (0);
2940     return;
2941   }
2942
2943 #if 0
2944   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
2945                    "Helper finished\n");
2946 #endif
2947
2948 }
2949
2950 #if DEBUG_wlan
2951 /**
2952  * Function to print mac addresses nice *
2953  * @param pointer to 6 byte with the mac address
2954  * @return pointer to the chars which hold the print out
2955  */
2956 static const char *
2957 macprinter (const u_int8_t * mac)
2958 {
2959   static char macstr[20];
2960
2961   GNUNET_snprintf (macstr, sizeof (macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
2962                    mac[2], mac[3], mac[4], mac[5]);
2963   return macstr;
2964 }
2965 #endif
2966
2967 /**
2968  * Function for the scheduler if a mac endpoint times out
2969  * @param cls pointer to the MacEndpoint
2970  * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
2971  */
2972 static void
2973 macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2974 {
2975   struct MacEndpoint *endpoint = cls;
2976
2977   GNUNET_assert (endpoint != NULL);
2978   endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2979   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
2980   {
2981     return;
2982   }
2983   if (GNUNET_TIME_absolute_get_remaining
2984       (GNUNET_TIME_absolute_add
2985        (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
2986   {
2987     GNUNET_assert (endpoint->plugin != NULL);
2988     GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
2989                               _("# wlan mac endpoints timeouts"), 1, GNUNET_NO);
2990     free_macendpoint (endpoint->plugin, endpoint);
2991   }
2992   else
2993   {
2994     endpoint->timeout_task =
2995         GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
2996                                       endpoint);
2997   }
2998 }
2999
3000 /**
3001  * function to create an macendpoint
3002  * @param plugin pointer to the plugin struct
3003  * @param addr pointer to the macaddress
3004  * @return returns a macendpoint
3005  */
3006 static struct MacEndpoint *
3007 create_macendpoint (struct Plugin *plugin, const struct MacAddress *addr)
3008 {
3009   struct MacEndpoint *newend = GNUNET_malloc (sizeof (struct MacEndpoint));
3010
3011   GNUNET_assert (plugin != NULL);
3012   GNUNET_STATISTICS_update (plugin->env->stats,
3013                             _("# wlan mac endpoints created"), 1, GNUNET_NO);
3014   newend->addr = *addr;
3015   newend->plugin = plugin;
3016   newend->addr = *addr;
3017   newend->fragment_messages_out_count = 0;
3018   newend->defrag =
3019       GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
3020                                         MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
3021                                         newend, &wlan_data_message_handler,
3022                                         &add_ack_for_send);
3023   newend->last_activity = GNUNET_TIME_absolute_get ();
3024   newend->timeout_task =
3025       GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
3026                                     newend);
3027
3028   plugin->mac_count++;
3029   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
3030                          plugin->mac_count, GNUNET_NO);
3031   GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend);
3032 #if DEBUG_wlan
3033   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3034                    "New Mac Endpoint %p: %s\n", newend,
3035                    wlan_plugin_address_to_string (NULL, newend->addr.mac, 6));
3036 #endif
3037   return newend;
3038 }
3039
3040 /**
3041  * Function used for to process the data from the suid process
3042  *
3043  * @param cls the plugin handle
3044  * @param client client that send the data (not used)
3045  * @param hdr header of the GNUNET_MessageHeader
3046  */
3047 static void
3048 wlan_process_helper (void *cls, void *client,
3049                      const struct GNUNET_MessageHeader *hdr)
3050 {
3051   struct Plugin *plugin = cls;
3052   struct ieee80211_frame *wlanIeeeHeader = NULL;
3053   struct Session_light *session_light = NULL;
3054   struct Radiotap_rx *rxinfo;
3055   const struct GNUNET_MessageHeader *temp_hdr = NULL;
3056
3057   int datasize = 0;
3058   int pos;
3059
3060   GNUNET_assert (plugin != NULL);
3061   switch (ntohs (hdr->type))
3062   {
3063   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
3064 #if DEBUG_wlan
3065     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3066                      "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
3067                      ntohs (hdr->size));
3068 #endif
3069
3070     GNUNET_STATISTICS_update (plugin->env->stats,
3071                               _("# wlan WLAN_HELPER_DATA received"), 1,
3072                               GNUNET_NO);
3073     //call wlan_process_helper with the message inside, later with wlan: analyze signal
3074     if (ntohs (hdr->size) <
3075         sizeof (struct ieee80211_frame) +
3076         2 * sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_rx))
3077     {
3078 #if DEBUG_wlan
3079       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3080                        "Size of packet is too small; size: %u min size: %u\n",
3081                        ntohs (hdr->size),
3082                        sizeof (struct ieee80211_frame) +
3083                        sizeof (struct GNUNET_MessageHeader));
3084 #endif
3085       //GNUNET_break (0);
3086       /* FIXME: restart SUID process */
3087       return;
3088     }
3089
3090     rxinfo = (struct Radiotap_rx *) &hdr[1];
3091     wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
3092
3093     //process only if it is an broadcast or for this computer both with the gnunet bssid
3094
3095     //check for bssid
3096     if (memcmp
3097         (&(wlanIeeeHeader->i_addr3), &mac_bssid,
3098          sizeof (struct MacAddress)) == 0)
3099     {
3100       //check for broadcast or mac
3101       if ((memcmp
3102            (&(wlanIeeeHeader->i_addr1), &bc_all_mac,
3103             sizeof (struct MacAddress)) == 0) ||
3104           (memcmp
3105            (&(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
3106             sizeof (struct MacAddress)) == 0))
3107       {
3108         //if packet is from us return
3109         if ((memcmp
3110              (&(wlanIeeeHeader->i_addr2), &(plugin->mac_address),
3111               sizeof (struct MacAddress)) == 0))
3112         {
3113           return;
3114         }
3115         // process the inner data
3116
3117
3118         datasize =
3119             ntohs (hdr->size) - sizeof (struct ieee80211_frame) -
3120             sizeof (struct GNUNET_MessageHeader) - sizeof (struct Radiotap_rx);
3121
3122         session_light = GNUNET_malloc (sizeof (struct Session_light));
3123         memcpy (&session_light->addr, &(wlanIeeeHeader->i_addr2),
3124                 sizeof (struct MacAddress));
3125         //session_light->session = search_session(plugin,session_light->addr);
3126         GNUNET_STATISTICS_update (plugin->env->stats,
3127                                   _("# wlan messages for this client received"),
3128                                   1, GNUNET_NO);
3129
3130         pos = 0;
3131         while (pos < datasize)
3132         {
3133           temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1] + pos;
3134           if (ntohs (temp_hdr->size) <= datasize + pos)
3135           {
3136             GNUNET_STATISTICS_update (plugin->env->stats,
3137                                       _
3138                                       ("# wlan messages inside WLAN_HELPER_DATA received"),
3139                                       1, GNUNET_NO);
3140             wlan_data_helper (plugin, session_light, temp_hdr, rxinfo);
3141           }
3142           else
3143           {
3144 #if DEBUG_wlan
3145             GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3146                              "Size of packet is too small; size: %u > size of packet: %u\n",
3147                              ntohs (temp_hdr->size), datasize + pos);
3148 #endif
3149           }
3150           pos += ntohs (temp_hdr->size);
3151
3152         }
3153
3154         //clean up
3155         GNUNET_free (session_light);
3156       }
3157       else
3158       {
3159 #if DEBUG_wlan
3160         GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3161                          "Func wlan_process_helper got wrong MAC: %s\n",
3162                          macprinter (wlanIeeeHeader->i_addr1));
3163 #endif
3164       }
3165     }
3166     else
3167     {
3168 #if DEBUG_wlan
3169       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3170                        "Func wlan_process_helper got wrong BSSID: %s\n",
3171                        macprinter (wlanIeeeHeader->i_addr2));
3172 #endif
3173     }
3174     break;
3175   case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
3176     //TODO more control messages
3177     if (ntohs (hdr->size) != sizeof (struct Wlan_Helper_Control_Message))
3178     {
3179       GNUNET_break (0);
3180       /* FIXME: restart SUID process */
3181       return;
3182     }
3183     memcpy (&plugin->mac_address, &hdr[1], sizeof (struct MacAddress));
3184 #if DEBUG_wlan
3185     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3186                      "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
3187                      wlan_plugin_address_to_string (cls, &plugin->mac_address,
3188                                                     sizeof (struct
3189                                                             MacAddress)));
3190 #endif
3191     plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
3192                                  &plugin->mac_address,
3193                                  sizeof (struct MacAddress));
3194     break;
3195   default:
3196 #if DEBUG_wlan
3197     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3198                      "Func wlan_process_helper got unknown message with number %u, size %u\n",
3199                      ntohs (hdr->type), ntohs (hdr->size));
3200
3201 #endif
3202 #if DEBUG_wlan_msg_dump > 1
3203     hexdump (hdr, GNUNET_MIN (ntohs (hdr->size), 256));
3204 #endif
3205     GNUNET_break (0);
3206     return;
3207   }
3208 }
3209
3210 /**
3211  * Exit point from the plugin.
3212  * @param cls pointer to the api struct
3213  */
3214
3215 //FIXME cleanup
3216 void *
3217 libgnunet_plugin_transport_wlan_done (void *cls)
3218 {
3219   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
3220   struct Plugin *plugin = api->cls;
3221   struct MacEndpoint *endpoint = plugin->mac_head;
3222   struct MacEndpoint *endpoint_next;
3223
3224 #if DEBUG_wlan
3225   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3226                    "libgnunet_plugin_transport_wlan_done started\n");
3227 #endif
3228
3229   wlan_transport_stop_wlan_helper (plugin);
3230
3231   GNUNET_assert (cls != NULL);
3232   //free sessions
3233   while (endpoint != NULL)
3234   {
3235     endpoint_next = endpoint->next;
3236     free_macendpoint (plugin, endpoint);
3237     endpoint = endpoint_next;
3238
3239   }
3240
3241
3242   if (plugin->suid_tokenizer != NULL)
3243     GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
3244
3245   if (plugin->data_tokenizer != NULL)
3246     GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
3247
3248   GNUNET_free_non_null (plugin->interface);
3249   GNUNET_free (plugin);
3250   GNUNET_free (api);
3251   return NULL;
3252 }
3253
3254 /**
3255  * Entry point for the plugin.
3256  *
3257  * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
3258  * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
3259  */
3260 void *
3261 libgnunet_plugin_transport_wlan_init (void *cls)
3262 {
3263   //struct GNUNET_SERVICE_Context *service;
3264   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
3265   struct GNUNET_TRANSPORT_PluginFunctions *api;
3266   struct Plugin *plugin;
3267
3268   GNUNET_assert (cls != NULL);
3269
3270   plugin = GNUNET_malloc (sizeof (struct Plugin));
3271   plugin->env = env;
3272   plugin->pendingsessions = 0;
3273   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
3274                          plugin->pendingsessions, GNUNET_NO);
3275   plugin->mac_count = 0;
3276   GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
3277                          plugin->mac_count, GNUNET_NO);
3278   plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
3279   plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
3280   plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
3281   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
3282                                  GNUNET_BANDWIDTH_value_init (100 * 1024 *
3283                                                               1024 / 8), 100);
3284
3285   plugin->suid_tokenizer =
3286       GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
3287
3288   plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
3289
3290   //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
3291   //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
3292
3293   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
3294   api->cls = plugin;
3295   api->send = &wlan_plugin_send;
3296   api->disconnect = &wlan_plugin_disconnect;
3297   api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
3298   api->check_address = &wlan_plugin_address_suggested;
3299   api->address_to_string = &wlan_plugin_address_to_string;
3300
3301   //read config
3302
3303   if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
3304   {
3305     if (GNUNET_SYSERR ==
3306         GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
3307                                                "TESTMODE", &(plugin->testmode)))
3308       plugin->testmode = 0;     //default value
3309   }
3310
3311   if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE"))
3312   {
3313     if (GNUNET_CONFIGURATION_get_value_string
3314         (env->cfg, "transport-wlan", "INTERFACE",
3315          &(plugin->interface)) != GNUNET_YES)
3316     {
3317       libgnunet_plugin_transport_wlan_done (api);
3318       return NULL;
3319     }
3320   }
3321
3322   //start the plugin
3323   wlan_transport_start_wlan_helper (plugin);
3324   set_next_beacon_time (plugin);
3325   set_next_send (plugin);
3326 #if DEBUG_wlan
3327   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
3328                    "wlan init finished\n");
3329 #endif
3330
3331   return api;
3332 }
3333
3334 /* end of plugin_transport_wlan.c */