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