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