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