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