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